Finished day 11 part 1 aoc in rust
This commit is contained in:
193
advent_of_code/2022/11/src/main.rs
Normal file
193
advent_of_code/2022/11/src/main.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use nom::{
|
||||
character::complete::{self, multispace1, one_of, multispace0},
|
||||
multi::{separated_list1, many1},
|
||||
bytes::complete::tag,
|
||||
sequence::{delimited, preceded},
|
||||
branch::alt,
|
||||
*,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Value {
|
||||
Old,
|
||||
Val(u32),
|
||||
} use Value::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Operation {
|
||||
Mult(Value),
|
||||
Add(Value),
|
||||
} use Operation::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Test {
|
||||
divisible_by: u32,
|
||||
on_false: usize,
|
||||
on_true: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Monkey {
|
||||
items: VecDeque<u32>,
|
||||
operation: Operation,
|
||||
test: Test,
|
||||
number_of_inspections: u32,
|
||||
}
|
||||
|
||||
impl Monkey {
|
||||
pub fn handle_items(&mut self) -> Vec<(u32, usize)> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
while !self.items.is_empty() {
|
||||
self.number_of_inspections += 1;
|
||||
|
||||
let mut item = self.items.pop_front().unwrap();
|
||||
item = match self.operation {
|
||||
Mult(Old) => {item * item},
|
||||
Mult(Val(num)) => {item * num},
|
||||
Add(Old) => {item * 2},
|
||||
Add(Val(num)) => {item + num},
|
||||
};
|
||||
|
||||
item /= 3;
|
||||
|
||||
let throw_to_monkey = match item % self.test.divisible_by == 0 {
|
||||
true => self.test.on_true,
|
||||
false => self.test.on_false,
|
||||
};
|
||||
|
||||
result.push((item, throw_to_monkey));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_operation(input: &str) -> IResult<&str, Operation> {
|
||||
let (input, op) = preceded(
|
||||
tag("Operation: new = old "),
|
||||
one_of("+*"),
|
||||
)(input)?;
|
||||
|
||||
let (input, num) : (&str, Value) = preceded(
|
||||
multispace1,
|
||||
alt((
|
||||
complete::u32.map(|num| Value::Val(num)),
|
||||
tag("old").map(|_| Value::Old),
|
||||
)),
|
||||
)(input)?;
|
||||
|
||||
let func = match op {
|
||||
'*' => Operation::Mult(num),
|
||||
'+' => Operation::Add(num),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Ok((input, func))
|
||||
}
|
||||
|
||||
fn parse_test(input: &str) -> IResult<&str, Test> {
|
||||
let (input, divisible_by) = preceded(
|
||||
tag("Test: divisible by "),
|
||||
complete::u32,
|
||||
)(input)?;
|
||||
|
||||
let (input, _) = multispace1(input)?;
|
||||
|
||||
let (input, on_true) = preceded(
|
||||
tag("If true: throw to monkey "),
|
||||
complete::u32,
|
||||
)(input)?;
|
||||
|
||||
let (input, _) = multispace1(input)?;
|
||||
|
||||
let (input, on_false) = preceded(
|
||||
tag("If false: throw to monkey "),
|
||||
complete::u32,
|
||||
)(input)?;
|
||||
|
||||
// Generate Test
|
||||
|
||||
let t = Test {
|
||||
divisible_by,
|
||||
on_false: on_false as usize,
|
||||
on_true: on_true as usize,
|
||||
};
|
||||
|
||||
Ok((input, t))
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> IResult<&str, Monkey> {
|
||||
// Parse: Monkey _id:
|
||||
let (input, _id) = delimited(
|
||||
tag("Monkey "),
|
||||
complete::u32,
|
||||
tag(":"),
|
||||
)(input)?;
|
||||
|
||||
let (input, _) = multispace1(input)?;
|
||||
|
||||
// Parse: Starting items: num1, num2
|
||||
let (input, levels) = preceded(
|
||||
tag("Starting items: "),
|
||||
separated_list1(tag(", "), complete::u32),
|
||||
)(input)?;
|
||||
|
||||
let (input, _) = multispace1(input)?;
|
||||
|
||||
//Parse: Operation: new = old {+ num|old}, {* num|old}
|
||||
let (input, operation) = parse_operation(input)?;
|
||||
|
||||
let (input, _) = multispace1(input)?;
|
||||
|
||||
//Parse: Test: divisible by num
|
||||
// If true: throw to monkey #
|
||||
// If false: throw to monkey #
|
||||
let (input, test) = parse_test(input)?;
|
||||
|
||||
let (input, _) = multispace0(input)?;
|
||||
|
||||
// Generate a monkey here
|
||||
|
||||
let items = VecDeque::from_iter(levels);
|
||||
|
||||
let m = Monkey {
|
||||
items,
|
||||
operation,
|
||||
test,
|
||||
number_of_inspections: 0,
|
||||
};
|
||||
|
||||
Ok((input, m))
|
||||
}
|
||||
|
||||
fn part1() {
|
||||
let input_text = include_str!("../input.txt");
|
||||
let (_, mut monkeys) = many1(parse_input)(input_text).unwrap();
|
||||
|
||||
for _i in 0..20 {
|
||||
for monkey_index in 0..monkeys.len() {
|
||||
let monkey = monkeys.get_mut(monkey_index).unwrap();
|
||||
let new_item_list = monkey.handle_items();
|
||||
|
||||
for (item, thrown_to_monkey) in new_item_list {
|
||||
monkeys[thrown_to_monkey].items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut results = monkeys
|
||||
.iter()
|
||||
.map(|m| m.number_of_inspections)
|
||||
.collect::<Vec<u32>>();
|
||||
results.sort_by(|a, b| b.cmp(a));
|
||||
|
||||
println!("{}", results[0] * results[1]);
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
part1();
|
||||
}
|
||||
Reference in New Issue
Block a user