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