-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathday23.rs
79 lines (72 loc) · 1.9 KB
/
day23.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! # Opening the Turing Lock
//!
//! Reverse engineering the code shows that it calculates the length of the
//! [3n + 1 sequence](https://en.wikipedia.org/wiki/Collatz_conjecture)
//! for one of two different numbers chosen depending on whether `a` is 0 or 1.
//!
//! The code fast enough to emulate directly without needing any understanding of what it's doing.
use crate::util::parse::*;
pub enum Op {
Hlf,
Tpl,
IncA,
IncB,
Jmp(usize),
Jie(usize),
Jio(usize),
}
pub fn parse(input: &str) -> Vec<Op> {
input
.lines()
.enumerate()
.map(|(i, s)| match s {
"hlf a" => Op::Hlf,
"tpl a" => Op::Tpl,
"inc a" => Op::IncA,
"inc b" => Op::IncB,
_ => {
let index = i.wrapping_add(s.signed::<i32>() as usize);
match &s[..3] {
"jmp" => Op::Jmp(index),
"jie" => Op::Jie(index),
"jio" => Op::Jio(index),
_ => unreachable!(),
}
}
})
.collect()
}
pub fn part1(input: &[Op]) -> u64 {
execute(input, 0)
}
pub fn part2(input: &[Op]) -> u64 {
execute(input, 1)
}
fn execute(input: &[Op], mut a: u64) -> u64 {
let mut pc = 0;
let mut b = 0;
while pc < input.len() {
match input[pc] {
Op::Hlf => {
a /= 2;
pc += 1;
}
Op::Tpl => {
a *= 3;
pc += 1;
}
Op::IncA => {
a += 1;
pc += 1;
}
Op::IncB => {
b += 1;
pc += 1;
}
Op::Jmp(index) => pc = index,
Op::Jie(index) => pc = if a % 2 == 0 { index } else { pc + 1 },
Op::Jio(index) => pc = if a == 1 { index } else { pc + 1 },
}
}
b
}