1use crate::elfcode::{HookControlFlow, Instruction, Interpreter};
2use utils::number::sum_of_divisors;
3use utils::prelude::*;
4
5#[derive(Clone, Debug)]
9pub struct Day19 {
10 interpreter: Interpreter,
11}
12
13impl Day19 {
14 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
15 Ok(Self {
16 interpreter: Interpreter::new(input)?,
17 })
18 }
19
20 #[must_use]
21 pub fn part1(&self) -> u32 {
22 self.run(0)
23 }
24
25 #[must_use]
26 pub fn part2(&self) -> u32 {
27 self.run(1)
28 }
29
30 fn run(&self, reg0: u32) -> u32 {
31 let mut reg = [reg0, 0, 0, 0, 0, 0];
32
33 self.interpreter.run(&mut reg, |instructions, instruction_pointer, reg| {
34 let addr = reg[instruction_pointer] as usize;
35
36 #[rustfmt::skip]
53 if let [
54 Instruction::Seti(1, div),
55 Instruction::Seti(1, mul),
56 Instruction::Mulr(div2, mul2, tmp),
57 Instruction::Eqrr(tmp2, tgt, tmp3),
58 Instruction::Addr(tmp4, ip, ip2),
59 Instruction::Addi(ip3, 1, ip4),
60 Instruction::Addr(div3, sum, sum2),
61 Instruction::Addi(mul3, 1, mul4),
62 Instruction::Gtrr(mul5, tgt2, tmp5),
63 Instruction::Addr(ip5, tmp6, ip6),
64 Instruction::Seti(loop1, ip7),
65 Instruction::Addi(div4, 1, div5),
66 Instruction::Gtrr(div6, tgt3, tmp7),
67 Instruction::Addr(tmp8, ip8, ip9),
68 Instruction::Seti(loop0, ip10),
69 ..,
70 ] = instructions[addr..]
71 && div == div2 && div == div3 && div == div4 && div == div5 && div == div6
72 && mul == mul2 && mul == mul3 && mul == mul4 && mul == mul5
73 && tmp == tmp2 && tmp == tmp3 && tmp == tmp4 && tmp == tmp5 && tmp == tmp6 && tmp == tmp7 && tmp == tmp8
74 && tgt == tgt2 && tgt == tgt3
75 && ip == ip2 && ip == ip3 && ip == ip4 && ip == ip5 && ip == ip6 && ip == ip7 && ip == ip8 && ip == ip9 && ip == ip10
76 && sum == sum2
77 && ip == instruction_pointer
78 && loop0 as usize == addr
79 && loop1 as usize == addr + 1
80 {
81 reg[sum] += sum_of_divisors(reg[tgt])
82 .expect("the target's sum of divisors should fit within a u32");
83 reg[div] = reg[tgt] + 1;
84 reg[mul] = reg[tgt] + 1;
85 reg[tmp] = 1;
86 reg[ip] += 15;
87 return HookControlFlow::Next
88 };
89
90 HookControlFlow::Execute
91 });
92
93 reg[0]
94 }
95}
96
97examples!(Day19 -> (u32, u32) [
98 {
99 input: "#ip 0\n\
100 seti 5 0 1\n\
101 seti 6 0 2\n\
102 addi 0 1 0\n\
103 addr 1 2 3\n\
104 setr 1 0 0\n\
105 seti 8 0 4\n\
106 seti 9 0 5",
107 part1: 7,
108 },
109]);