aoc/year2015/
day23.rs

1//! # Opening the Turing Lock
2//!
3//! Reverse engineering the code shows that it calculates the length of the
4//! [3n + 1 sequence](https://en.wikipedia.org/wiki/Collatz_conjecture)
5//! for one of two different numbers chosen depending on whether `a` is 0 or 1.
6//!
7//! The code fast enough to emulate directly without needing any understanding of what it's doing.
8use 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}