1use std::iter::repeat_with;
13
14use crate::util::hash::*;
15use crate::util::parse::*;
16
17const UPPER: u128 = u128::MAX << 64;
18const LOWER: u128 = u128::MAX >> 64;
19
20pub struct Input {
21 state: usize,
22 steps: u32,
23 rules: Vec<[Rule; 2]>,
24}
25
26struct Rule {
27 next_state: usize,
28 next_tape: bool,
29 advance: bool,
30}
31
32impl Rule {
33 fn parse(block: &[&[u8]]) -> Self {
34 let next_tape = block[0][22] == b'1';
35 let advance = block[1][27] == b'r';
36 let next_state = (block[2][26] - b'A') as usize;
37 Self { next_state, next_tape, advance }
38 }
39}
40
41struct Skip {
42 next_state: usize,
43 next_tape: u128,
44 steps: u32,
45 advance: bool,
46}
47
48pub fn parse(input: &str) -> Input {
50 let lines: Vec<_> = input.lines().map(str::as_bytes).collect();
51
52 let state = (lines[0][15] - b'A') as usize;
53 let steps = input.unsigned();
54 let rules: Vec<_> = lines[3..]
55 .chunks(10)
56 .map(|chunk| [Rule::parse(&chunk[2..5]), Rule::parse(&chunk[6..9])])
57 .collect();
58
59 Input { state, steps, rules }
60}
61
62pub fn part1(input: &Input) -> u32 {
63 let mut state = input.state;
64 let mut remaining = input.steps;
65 let mut tape = 0;
66 let mut left = Vec::new();
67 let mut right = Vec::new();
68 let mut cache: Vec<_> = repeat_with(FastMap::new).take(input.rules.len()).collect();
69
70 loop {
71 let Skip { next_state, next_tape, steps, advance } = *cache[state]
73 .entry(tape)
74 .or_insert_with(|| turing(&input.rules, state, tape, u32::MAX));
75
76 if steps > remaining {
78 let Skip { next_tape, .. } = turing(&input.rules, state, tape, remaining);
79 left.push(next_tape);
80 break;
81 }
82
83 state = next_state;
84 tape = next_tape;
85 remaining -= steps;
86
87 if advance {
91 left.push(tape & UPPER);
92 tape = (tape << 64) | right.pop().unwrap_or(0);
93 } else {
94 right.push(tape & LOWER);
95 tape = (tape >> 64) | left.pop().unwrap_or(0);
96 }
97 }
98
99 left.into_iter().chain(right).map(u128::count_ones).sum()
100}
101
102pub fn part2(_input: &Input) -> &'static str {
103 "n/a"
104}
105
106#[inline]
108fn turing(rules: &[[Rule; 2]], mut state: usize, mut tape: u128, max_steps: u32) -> Skip {
109 let mut mask = 1 << 63;
110 let mut steps = 0;
111
112 while 0 < mask && mask < (1 << 127) && steps < max_steps {
115 let current = usize::from(tape & mask != 0);
116 let rule = &rules[state][current];
117
118 tape = if rule.next_tape { tape | mask } else { tape & !mask };
119 mask = if rule.advance { mask >> 1 } else { mask << 1 };
120 state = rule.next_state;
121 steps += 1;
122 }
123
124 Skip { next_state: state, next_tape: tape, steps, advance: mask == 0 }
125}