[rs] Optimize 2022_11
This commit is contained in:
parent
ff64e5db06
commit
a396c81172
1 changed files with 33 additions and 36 deletions
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue