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 pc < input.len() {
56 match input[pc] {
57 Op::Hlf => {
58 a /= 2;
59 pc += 1;
60 }
61 Op::Tpl => {
62 a *= 3;
63 pc += 1;
64 }
65 Op::IncA => {
66 a += 1;
67 pc += 1;
68 }
69 Op::IncB => {
70 b += 1;
71 pc += 1;
72 }
73 Op::Jmp(index) => pc = index,
74 Op::Jie(index) => pc = if a.is_multiple_of(2) { index } else { pc + 1 },
75 Op::Jio(index) => pc = if a == 1 { index } else { pc + 1 },
76 }
77 }
78
79 b
80}