main
mat ess 2022-12-11 01:33:56 -05:00
parent b6eaa973c4
commit 083636f274
3 changed files with 225 additions and 0 deletions

27
inputs/11.small.txt Normal file
View File

@ -0,0 +1,27 @@
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1

55
inputs/11.txt Normal file
View File

@ -0,0 +1,55 @@
Monkey 0:
Starting items: 89, 73, 66, 57, 64, 80
Operation: new = old * 3
Test: divisible by 13
If true: throw to monkey 6
If false: throw to monkey 2
Monkey 1:
Starting items: 83, 78, 81, 55, 81, 59, 69
Operation: new = old + 1
Test: divisible by 3
If true: throw to monkey 7
If false: throw to monkey 4
Monkey 2:
Starting items: 76, 91, 58, 85
Operation: new = old * 13
Test: divisible by 7
If true: throw to monkey 1
If false: throw to monkey 4
Monkey 3:
Starting items: 71, 72, 74, 76, 68
Operation: new = old * old
Test: divisible by 2
If true: throw to monkey 6
If false: throw to monkey 0
Monkey 4:
Starting items: 98, 85, 84
Operation: new = old + 7
Test: divisible by 19
If true: throw to monkey 5
If false: throw to monkey 7
Monkey 5:
Starting items: 78
Operation: new = old + 8
Test: divisible by 5
If true: throw to monkey 3
If false: throw to monkey 0
Monkey 6:
Starting items: 86, 70, 60, 88, 88, 78, 74, 83
Operation: new = old + 4
Test: divisible by 11
If true: throw to monkey 1
If false: throw to monkey 2
Monkey 7:
Starting items: 81, 58
Operation: new = old + 5
Test: divisible by 17
If true: throw to monkey 3
If false: throw to monkey 5

View File

@ -262,9 +262,152 @@ solutions! {
let cmds = input.lines().map(Cmd::from_str).collect();
Screen::new().draw(cmds).to_string().into()
}
],
[
// day 11 part 1
|input| {
let monkeys = input.split("\n\n").map(|s| Monkey::from_str(s, false)).collect();
run_rounds(monkeys, 20).into()
},
// day 11 part 2
|input| {
let monkeys = input.split("\n\n").map(|s| Monkey::from_str(s, true)).collect();
run_rounds(monkeys, 10000).into()
}
]
}
fn run_rounds(mut monkeys: Vec<Monkey>, n: usize) -> u64 {
let mod_factor: usize = monkeys.iter().map(|m| m.test).product();
let mut counts = vec![0; monkeys.len()];
for round in 1..=n {
let next = run_round(&mut monkeys, mod_factor);
counts = next.iter().zip(counts).map(|(x, y)| x + y).collect();
if round % 1000 == 0 || round == 20 || round == 1 {}
}
counts.sort();
counts[counts.len() - 1] * counts[counts.len() - 2]
}
fn run_round(monkeys: &mut Vec<Monkey>, mod_factor: usize) -> Vec<u64> {
let mut inspects = vec![];
for i in 0..monkeys.len() {
let monkey = &mut monkeys[i];
let throws = monkey.take_turn(mod_factor);
inspects.push(throws.len() as u64);
for (to, item) in throws {
monkeys[to].items.push(item)
}
}
inspects
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
enum OpType {
Add,
Mul,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Op {
op_type: OpType,
operand: Option<usize>,
}
impl Op {
fn operand(s: &str) -> Option<usize> {
match s {
"old" => None,
_ => Some(s.parse::<usize>().unwrap()),
}
}
fn from_str(s: &str) -> Self {
let (op_type, y) = s.split_once(' ').unwrap();
Self {
op_type: match op_type {
"+" => OpType::Add,
"*" => OpType::Mul,
_ => unreachable!("whoa"),
},
operand: Self::operand(y),
}
}
fn apply(&self, old: usize) -> usize {
let operand = self.operand.unwrap_or(old);
match self.op_type {
OpType::Add => old.wrapping_add(operand),
OpType::Mul => old.wrapping_mul(operand),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct Monkey {
items: Vec<usize>,
operation: Op,
test: usize,
throw_true: usize,
throw_false: usize,
part_two: bool,
}
impl Monkey {
fn from_str(s: &str, part_two: bool) -> Self {
let (_, s) = s.split_once('\n').unwrap();
let (items, s) = s.split_once('\n').unwrap();
let (operation, s) = s.split_once('\n').unwrap();
let (test, s) = s.split_once('\n').unwrap();
let (throw_true, throw_false) = s.split_once('\n').unwrap();
Monkey {
items: items
.strip_prefix(" Starting items: ")
.unwrap()
.split(", ")
.map(|n| n.parse::<usize>().unwrap())
.collect(),
operation: Op::from_str(operation.strip_prefix(" Operation: new = old ").unwrap()),
test: test
.strip_prefix(" Test: divisible by ")
.unwrap()
.parse::<usize>()
.unwrap(),
throw_true: throw_true
.strip_prefix(" If true: throw to monkey ")
.unwrap()
.parse::<usize>()
.unwrap(),
throw_false: throw_false
.strip_prefix(" If false: throw to monkey ")
.unwrap()
.trim()
.parse::<usize>()
.unwrap(),
part_two,
}
}
fn take_turn(&mut self, mod_factor: usize) -> Vec<(usize, usize)> {
self.items
.drain(..)
.map(|item| {
let level = self.operation.apply(item);
let level = if self.part_two {
level % mod_factor
} else {
level / 3
};
if level % self.test == 0 {
(self.throw_true, level)
} else {
(self.throw_false, level)
}
})
.collect()
}
}
struct Screen {
x: isize,
cycle: isize,