1use crate::util::parse::*;
10
11pub enum Op {
12 Hlf,
13 Tpl,
14 IncA,
15 IncB,
16 Jmp(usize),
17 Jie(usize),
18 Jio(usize),
19}
20
21pub fn parse(input: &str) -> Vec<Op> {
22 input
23 .lines()
24 .enumerate()
25 .map(|(i, s)| match s {
26 "hlf a" => Op::Hlf,
27 "tpl a" => Op::Tpl,
28 "inc a" => Op::IncA,
29 "inc b" => Op::IncB,
30 _ => {
31 let index = i.wrapping_add_signed(s.signed());
32 match &s[..3] {
33 "jmp" => Op::Jmp(index),
34 "jie" => Op::Jie(index),
35 "jio" => Op::Jio(index),
36 _ => unreachable!(),
37 }
38 }
39 })
40 .collect()
41}
42
43pub fn part1(input: &[Op]) -> u64 {
44 execute(input, 0)
45}
46
47pub fn part2(input: &[Op]) -> u64 {
48 execute(input, 1)
49}
50
51fn execute(input: &[Op], mut a: u64) -> u64 {
52 let mut pc = 0;
53 let mut b = 0;
54
55 while let Some(op) = input.get(pc) {
56 pc += 1;
57
58 match *op {
59 Op::Hlf => a /= 2,
60 Op::Tpl => a *= 3,
61 Op::IncA => a += 1,
62 Op::IncB => b += 1,
63 Op::Jmp(index) => pc = index,
64 Op::Jie(index) if a.is_multiple_of(2) => pc = index,
65 Op::Jio(index) if a == 1 => pc = index,
66 Op::Jie(_) | Op::Jio(_) => (),
67 }
68 }
69
70 b
71}