-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
116 lines (96 loc) · 2.8 KB
/
main.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
fn load_input() -> String {
std::fs::read_to_string("dec08/src/input.txt").expect("Unable to read input file")
}
#[derive(Clone, Debug)]
struct Instruction<'a> {
operation: &'a str,
argument: i32,
called: bool,
}
impl<'a> Instruction<'a> {
fn new(instruction: &'a str) -> Self {
let parts = instruction.split_ascii_whitespace().collect::<Vec<&str>>();
let operation = parts[0];
let argument = parts[1].parse::<i32>().unwrap();
Self {
operation,
argument,
called: false,
}
}
}
enum ExecutionResult {
Loop(i32),
Exit(i32),
}
fn execute(instructions: &[Instruction]) -> ExecutionResult {
let mut instructions = instructions.iter().cloned().collect::<Vec<Instruction>>();
let mut accumulator = 0;
let mut index = 0;
while index < instructions.len() {
let instruction = &mut instructions[index];
if instruction.called {
return ExecutionResult::Loop(accumulator);
}
instruction.called = true;
match instruction.operation {
"acc" => {
accumulator += instruction.argument;
index += 1;
}
"jmp" => {
index = ((index as i32) + instruction.argument) as usize;
}
"nop" => {
index += 1;
}
_ => panic!("unknown operation {}", instruction.operation),
}
}
ExecutionResult::Exit(accumulator)
}
fn puzzle_1() -> i32 {
let input = load_input();
let instructions = input
.split('\n')
.map(Instruction::new)
.collect::<Vec<Instruction>>();
match execute(&instructions) {
ExecutionResult::Loop(acc) => acc,
_ => panic!("Should cause loop"),
}
}
fn puzzle_2() -> i32 {
let input = load_input();
let instructions = input
.split('\n')
.map(Instruction::new)
.collect::<Vec<Instruction>>();
let mut changed_index = 0;
loop {
let mut instructions = instructions.iter().cloned().collect::<Vec<Instruction>>();
let (index, inst) = instructions[changed_index..]
.iter_mut()
.enumerate()
.find(|(_, i)| i.operation == "jmp" || i.operation == "nop")
.unwrap();
if inst.operation == "jmp" {
inst.operation = "nop";
} else {
inst.operation = "jmp";
}
changed_index += index + 1;
match execute(&instructions) {
ExecutionResult::Exit(acc) => {
return acc;
}
ExecutionResult::Loop(_) => (),
}
}
}
fn main() {
let result = puzzle_1();
println!("Puzzle 1 output: {}", result);
let result = puzzle_2();
println!("Puzzle 2 output: {}", result);
}