[rs] Optimize 2022_11

This commit is contained in:
Joscha 2022-12-15 20:17:20 +01:00
parent ff64e5db06
commit a396c81172

View file

@ -1,28 +1,29 @@
use std::mem; use std::mem;
use std::str::Lines; use std::str::Lines;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, Default)]
enum Operation { enum Operation {
Add, Add(u64),
Mul, Mul(u64),
#[default]
Square,
} }
impl Operation { impl Operation {
fn eval(self, lhs: u64, rhs: u64) -> u64 { fn eval(self, old: u64) -> u64 {
match self { match self {
Self::Add => lhs + rhs, Self::Add(lit) => old + lit,
Self::Mul => lhs * rhs, Self::Mul(lit) => old * lit,
Self::Square => old * old,
} }
} }
} }
#[derive(Clone)] #[derive(Clone, Default)]
struct Monkey { struct Monkey {
holds: Vec<u64>, holds: Vec<u64>,
// Left hand side is always "old"
op: Operation, op: Operation,
rhs: Option<u64>,
div_by: u64, div_by: u64,
if_true: usize, if_true: usize,
@ -48,15 +49,12 @@ impl Monkey {
let (op, rhs) = prefixed(&mut lines, " Operation: new = old ") let (op, rhs) = prefixed(&mut lines, " Operation: new = old ")
.split_once(' ') .split_once(' ')
.unwrap(); .unwrap();
let op = match op { let op = match (op, rhs) {
"+" => Operation::Add, ("+", _) => Operation::Add(rhs.parse().unwrap()),
"*" => Operation::Mul, ("*", "old") => Operation::Square,
("*", _) => Operation::Mul(rhs.parse().unwrap()),
_ => panic!(), _ => panic!(),
}; };
let rhs = match rhs {
"old" => None,
_ => Some(rhs.parse().unwrap()),
};
let div_by = prefixed(&mut lines, " Test: divisible by ") let div_by = prefixed(&mut lines, " Test: divisible by ")
.parse() .parse()
@ -73,7 +71,6 @@ impl Monkey {
Self { Self {
holds, holds,
op, op,
rhs,
div_by, div_by,
if_true, if_true,
if_false, if_false,
@ -81,31 +78,30 @@ impl Monkey {
} }
} }
fn take(&mut self) -> Self { fn fill_into(&mut self, into: &mut Self) {
Self { mem::swap(&mut self.holds, &mut into.holds);
holds: mem::take(&mut self.holds), self.holds.clear();
op: self.op, into.op = self.op;
rhs: self.rhs, into.div_by = self.div_by;
div_by: self.div_by, into.if_true = self.if_true;
if_true: self.if_true, into.if_false = self.if_false;
if_false: self.if_false, into.inspections = self.inspections;
inspections: self.inspections,
}
} }
} }
fn round(monkeys: &mut Vec<Monkey>, reduce_worry: bool, modulo: u64) { #[inline]
fn round(monkeys: &mut Vec<Monkey>, swapmonkey: &mut Monkey, reduce_worry: bool, modulo: u64) {
for i in 0..monkeys.len() { for i in 0..monkeys.len() {
monkeys[i].inspections += monkeys[i].holds.len(); monkeys[i].inspections += monkeys[i].holds.len();
let monkey = monkeys[i].take(); monkeys[i].fill_into(swapmonkey);
for item in monkey.holds { for item in &swapmonkey.holds {
let item = monkey.op.eval(item, monkey.rhs.unwrap_or(item)); let item = swapmonkey.op.eval(*item);
let item = if reduce_worry { item / 3 } else { item }; let item = if reduce_worry { item / 3 } else { item };
let item = item % modulo; let item = item % modulo;
let target = if item % monkey.div_by == 0 { let target = if item % swapmonkey.div_by == 0 {
monkey.if_true swapmonkey.if_true
} else { } else {
monkey.if_false swapmonkey.if_false
}; };
monkeys[target].holds.push(item); monkeys[target].holds.push(item);
} }
@ -123,19 +119,20 @@ pub fn solve(input: String) {
for monkey in input.trim().split("\n\n") { for monkey in input.trim().split("\n\n") {
monkeys.push(Monkey::parse(monkey)); monkeys.push(Monkey::parse(monkey));
} }
let mut swapmonkey = Monkey::default();
let common_multiple = monkeys.iter().map(|m| m.div_by).product::<u64>(); let common_multiple = monkeys.iter().map(|m| m.div_by).product::<u64>();
eprintln!("Common multiple: {common_multiple}"); eprintln!("Common multiple: {common_multiple}");
let mut part1 = monkeys.clone(); let mut part1 = monkeys.clone();
for _ in 0..20 { for _ in 0..20 {
round(&mut part1, true, common_multiple); round(&mut part1, &mut swapmonkey, true, common_multiple);
} }
println!("Part 1: {}", monkey_business(&part1)); println!("Part 1: {}", monkey_business(&part1));
let mut part2 = monkeys.clone(); let mut part2 = monkeys.clone();
for _ in 0..10000 { for _ in 0..10000 {
round(&mut part2, false, common_multiple); round(&mut part2, &mut swapmonkey, false, common_multiple);
} }
println!("Part 2: {}", monkey_business(&part2)); println!("Part 2: {}", monkey_business(&part2));
} }