Day 11
parent
b6eaa973c4
commit
083636f274
|
@ -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
|
|
@ -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
|
143
src/main.rs
143
src/main.rs
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue