Compare commits

...

2 Commits

Author SHA1 Message Date
f02033811d Day 8 part 2 solution 2020-12-08 18:52:33 -08:00
69f84f4819 Day 8 part 1 solution 2020-12-08 18:29:32 -08:00
3 changed files with 858 additions and 0 deletions

612
2020/input/2020/day8.txt Normal file
View File

@ -0,0 +1,612 @@
acc +18
nop +222
acc -16
acc +28
jmp +475
acc -6
jmp +584
acc -12
acc -8
jmp +554
acc -9
acc +12
acc -16
acc +27
jmp +336
acc -4
jmp +214
acc +38
jmp +61
acc +3
acc +28
acc +5
acc -19
jmp +584
nop +206
jmp +506
acc +36
jmp +133
acc +20
acc +43
acc -18
jmp +409
acc +24
jmp +131
acc -12
acc +7
acc +7
jmp +454
acc +37
acc -6
nop +558
acc +31
jmp +124
acc -15
nop +201
acc -7
jmp +297
acc +3
nop +517
jmp +221
jmp +211
acc +28
acc +35
jmp +5
acc +31
nop +325
acc -15
jmp +116
jmp +1
nop +333
acc -2
acc -5
jmp +138
acc +19
acc +9
jmp +180
acc +18
jmp +228
jmp +495
jmp +382
acc +20
nop +414
nop +139
acc +33
jmp +171
acc -10
jmp +41
acc -2
jmp +80
acc +20
nop +451
acc +2
acc +24
jmp +102
acc +1
acc -11
acc +9
acc +38
jmp -73
acc +17
acc +16
acc +12
acc +43
jmp +168
jmp +286
acc +6
acc +6
jmp +271
acc -17
acc -5
acc +1
jmp -50
acc -9
acc +6
acc -2
acc +33
jmp +385
acc +18
acc +24
jmp +370
acc -5
acc +23
acc +6
jmp +98
acc -10
acc -16
jmp +329
nop +41
jmp +463
nop +224
acc +35
jmp +345
acc +34
acc -18
acc +5
jmp +177
nop -57
nop -80
acc +20
jmp -12
acc +24
acc +39
jmp +363
jmp +253
acc -14
acc +0
acc +22
jmp +118
acc +43
acc -2
jmp +300
acc -14
acc +8
acc +47
jmp +271
jmp +420
acc +33
acc +15
acc +20
acc +25
jmp +84
acc +41
jmp +420
acc +25
jmp +238
jmp +1
acc +14
jmp +415
jmp +68
jmp +262
acc +34
jmp +346
acc +39
jmp +56
jmp +364
jmp -133
acc +13
jmp +1
acc +33
jmp +408
acc +29
acc -4
jmp +319
jmp +106
jmp +228
acc -8
acc +8
acc +22
jmp -146
jmp +223
acc +27
nop +191
acc +49
jmp +331
jmp +39
jmp -170
acc +28
acc -6
acc +50
jmp +268
acc +41
nop +254
acc +28
jmp +269
jmp +140
acc +10
nop +131
acc +3
jmp -40
jmp +373
acc +47
jmp -91
acc -19
jmp +300
acc -2
jmp +1
acc +44
acc -11
jmp +306
acc +33
jmp -15
acc +9
jmp +1
jmp +144
acc +40
nop +184
nop -75
nop +228
jmp +296
acc +22
nop +364
jmp -214
jmp +18
jmp +375
acc +22
jmp -67
acc +8
acc -17
jmp +174
jmp -99
nop -45
acc +7
jmp -213
jmp -218
acc +50
nop +52
nop +98
jmp -142
acc +18
jmp +252
acc +36
jmp -194
acc +1
nop -53
jmp -127
jmp +327
acc +7
acc -9
acc +39
nop -127
jmp +84
jmp -117
nop -29
acc +43
jmp -216
acc +25
acc +16
acc +40
nop +122
jmp +140
jmp +180
acc +42
acc -5
acc -14
jmp -84
jmp -31
acc +37
acc -11
jmp -217
jmp +210
jmp +170
nop +301
jmp +309
acc +6
jmp +135
acc +6
nop -123
acc +17
jmp +315
acc -1
nop -46
nop -58
nop -59
jmp +202
acc +48
acc +38
jmp +86
acc -4
acc +33
acc +28
jmp -50
nop +43
acc +38
acc +13
jmp +33
acc +4
acc +6
jmp -78
acc +22
acc +7
acc -9
jmp -56
acc +30
nop +54
nop -81
nop +198
jmp +252
jmp +1
acc +6
acc -10
acc +29
jmp -242
jmp +1
acc +42
acc +34
acc +22
jmp +231
acc +29
acc -10
jmp -161
acc +37
acc +9
jmp -77
acc -15
acc +32
acc +32
jmp -6
acc +0
nop -124
nop +174
jmp +20
acc +45
acc +24
jmp -13
acc +6
acc -10
acc +23
acc -15
jmp +34
acc +5
acc +38
acc +42
jmp -116
acc +0
acc +8
jmp -243
acc -18
acc +25
acc +1
jmp +158
nop +65
jmp +1
jmp +151
acc +12
acc +12
jmp +1
jmp -305
jmp +29
jmp -263
acc +33
jmp +1
nop +142
jmp +78
acc +41
nop -141
acc -9
acc +5
jmp -245
jmp +41
acc +16
nop -83
jmp -28
nop -149
acc +38
jmp -15
acc +7
nop -329
acc +5
acc +21
jmp -7
acc -19
jmp -38
acc +5
acc +3
acc +10
jmp -181
jmp -240
acc +19
acc +15
acc +31
acc -11
jmp -340
acc +12
acc +46
jmp +127
acc +12
acc +31
acc +30
jmp -158
acc -10
jmp -374
jmp +50
acc +43
nop +42
acc +19
jmp -232
acc -14
acc -4
jmp +95
acc +23
acc +49
acc +31
nop -139
jmp -272
jmp -141
acc +26
acc -8
jmp +173
nop +145
nop +133
jmp +164
acc +7
jmp +23
acc -4
acc +48
jmp -138
acc +4
jmp -389
nop +156
acc +44
acc +40
jmp +146
nop -247
acc +44
jmp +1
acc +28
jmp +95
acc +13
acc +2
jmp -254
acc +24
jmp +122
acc +39
acc +0
jmp -12
jmp -179
nop -44
nop +100
acc -19
nop -47
jmp -107
acc +32
acc +33
acc +42
acc +6
jmp -366
jmp -122
acc +2
nop -443
nop +72
jmp -381
jmp -446
jmp -332
acc -7
acc +45
jmp -355
acc +27
acc -4
acc +3
jmp +96
acc +45
jmp -402
acc +45
acc -3
acc +22
jmp -141
acc +29
acc -1
jmp +29
acc -1
acc -10
jmp -208
acc +6
nop -196
jmp -218
acc -12
acc +49
nop -137
jmp -430
acc +21
jmp -110
nop -287
acc -3
jmp -42
jmp -487
acc -16
acc -1
acc +7
acc +39
jmp -119
jmp +1
acc +9
jmp -23
acc +27
jmp -300
acc +12
jmp -440
acc +2
acc +38
acc +12
jmp -84
acc +25
acc -14
jmp -418
acc -15
acc +48
jmp +1
nop -383
jmp -365
acc +47
jmp -193
acc +23
jmp -235
jmp +1
acc -4
acc +35
nop -64
jmp -87
acc +32
jmp -339
jmp -479
acc -4
acc +32
acc -10
jmp -77
acc +0
acc +47
acc +41
jmp -308
acc -8
acc -9
jmp -229
acc -14
acc +24
nop -380
acc +49
jmp -174
acc -11
nop -69
jmp +3
acc -14
jmp -89
jmp -301
acc +46
acc +8
nop -156
acc +44
jmp +1
jmp +26
acc +17
acc +23
acc +6
jmp -4
jmp -97
jmp -324
acc +2
jmp -27
nop -195
acc +3
acc -13
acc +15
jmp -19
acc +30
nop -318
jmp +19
nop -72
jmp -315
acc +4
nop +6
jmp -384
jmp -505
jmp -512
acc +33
jmp -168
jmp -443
nop -519
acc +7
acc +41
acc +15
jmp -269
nop -539
jmp -416
jmp -326
nop -221
acc +14
jmp -186
acc -1
jmp -295
acc +29
acc +43
nop -436
nop -421
jmp -123
acc +13
acc -11
acc +12
jmp -155
acc +9
acc -16
acc -15
nop -380
jmp +1

245
2020/src/day8.rs Normal file
View File

@ -0,0 +1,245 @@
//! --- Day 8: Handheld Halting ---
//! Your flight to the major airline hub reaches cruising altitude without incident. While you consider checking the in-flight menu for one of those drinks that come with a little umbrella, you are interrupted by the kid sitting next to you.
//!
//! Their handheld game console won't turn on! They ask if you can take a look.
//!
//! You narrow the problem down to a strange infinite loop in the boot code (your puzzle input) of the device. You should be able to fix it, but first you need to be able to run the code in isolation.
//!
//! The boot code is represented as a text file with one instruction per line of text. Each instruction consists of an operation (acc, jmp, or nop) and an argument (a signed number like +4 or -20).
//!
//! acc increases or decreases a single global value called the accumulator by the value given in the argument. For example, acc +7 would increase the accumulator by 7. The accumulator starts at 0. After an acc instruction, the instruction immediately below it is executed next.
//! jmp jumps to a new instruction relative to itself. The next instruction to execute is found using the argument as an offset from the jmp instruction; for example, jmp +2 would skip the next instruction, jmp +1 would continue to the instruction immediately below it, and jmp -20 would cause the instruction 20 lines above to be executed next.
//! nop stands for No OPeration - it does nothing. The instruction immediately below it is executed next.
//! For example, consider the following program:
//!
//! nop +0
//! acc +1
//! jmp +4
//! acc +3
//! jmp -3
//! acc -99
//! acc +1
//! jmp -4
//! acc +6
//! These instructions are visited in this order:
//!
//! nop +0 | 1
//! acc +1 | 2, 8(!)
//! jmp +4 | 3
//! acc +3 | 6
//! jmp -3 | 7
//! acc -99 |
//! acc +1 | 4
//! jmp -4 | 5
//! acc +6 |
//! First, the nop +0 does nothing. Then, the accumulator is increased from 0 to 1 (acc +1) and jmp +4 sets the next instruction to the other acc +1 near the bottom. After it increases the accumulator from 1 to 2, jmp -4 executes, setting the next instruction to the only acc +3. It sets the accumulator to 5, and jmp -3 causes the program to continue back at the first acc +1.
//!
//! This is an infinite loop: with this sequence of jumps, the program will run forever. The moment the program tries to run any instruction a second time, you know it will never terminate.
//!
//! Immediately before the program would run an instruction a second time, the value in the accumulator is 5.
//!
//! Run your copy of the boot code. Immediately before any instruction is executed a second time, what value is in the accumulator?
//!
//! --- Part Two ---
//! After some careful analysis, you believe that exactly one instruction is corrupted.
//!
//! Somewhere in the program, either a jmp is supposed to be a nop, or a nop is supposed to be a jmp. (No acc instructions were harmed in the corruption of this boot code.)
//!
//! The program is supposed to terminate by attempting to execute an instruction immediately after the last instruction in the file. By changing exactly one jmp or nop, you can repair the boot code and make it terminate correctly.
//!
//! For example, consider the same program from above:
//!
//! nop +0
//! acc +1
//! jmp +4
//! acc +3
//! jmp -3
//! acc -99
//! acc +1
//! jmp -4
//! acc +6
//! If you change the first instruction from nop +0 to jmp +0, it would create a single-instruction infinite loop, never leaving that instruction. If you change almost any of the jmp instructions, the program will still eventually find another jmp instruction and loop forever.
//!
//! However, if you change the second-to-last instruction (from jmp -4 to nop -4), the program terminates! The instructions are visited in this order:
//!
//! nop +0 | 1
//! acc +1 | 2
//! jmp +4 | 3
//! acc +3 |
//! jmp -3 |
//! acc -99 |
//! acc +1 | 4
//! nop -4 | 5
//! acc +6 | 6
//! After the last instruction (acc +6), the program terminates by attempting to run the instruction below the last instruction in the file. With this change, after the program terminates, the accumulator contains the value 8 (acc +1, acc +1, acc +6).
//!
//! Fix the program so that it terminates normally by changing exactly one jmp (to nop) or nop (to jmp). What is the value of the accumulator after the program terminates?
use std::str::FromStr;
use aoc_runner_derive::aoc;
#[derive(Copy, Clone, Debug, PartialEq)]
enum Instruction {
Nop(i32),
Acc(i32),
Jmp(i32),
}
impl FromStr for Instruction {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut it = s.split(' ');
Ok(match it.next() {
Some("nop") => Instruction::Nop(it.next().ok_or(())?.parse().map_err(|_| ())?),
Some("acc") => Instruction::Acc(it.next().ok_or(())?.parse().map_err(|_| ())?),
Some("jmp") => Instruction::Jmp(it.next().ok_or(())?.parse().map_err(|_| ())?),
Some(c) => panic!(format!("unknown instruction '{}'", c)),
None => panic!(format!("no space in '{}'", s)),
})
}
}
#[derive(Default, Debug, PartialEq)]
struct Program {
ip: usize,
acc: i32,
intrs: Vec<Instruction>,
executed: Vec<bool>,
}
impl Program {
fn reset(&mut self) {
self.ip = 0;
self.acc = 0;
self.executed.iter_mut().for_each(|i| *i = false);
}
fn debug(&mut self, bad_ip: usize) -> Option<i32> {
loop {
if self.executed[self.ip] {
return None;
}
self.executed[self.ip] = true;
let intr = self.intrs[self.ip];
let intr = if self.ip == bad_ip {
match intr {
// Swap instruction as this is a possible bug location.
Instruction::Nop(op) => Instruction::Jmp(op),
Instruction::Jmp(op) => Instruction::Nop(op),
// Acc can't be buggy per the instructions.
Instruction::Acc(_) => return None,
}
} else {
intr
};
match intr {
Instruction::Nop(_) => self.ip += 1,
Instruction::Acc(op) => {
self.acc += op;
self.ip += 1;
}
Instruction::Jmp(op) => self.ip = (self.ip as i32 + op) as usize,
}
if self.ip >= self.intrs.len() {
return Some(self.acc);
}
}
}
fn run(&mut self) -> i32 {
loop {
if self.executed[self.ip] {
return self.acc;
}
self.executed[self.ip] = true;
match self.intrs[self.ip] {
Instruction::Nop(_) => self.ip += 1,
Instruction::Acc(op) => {
self.acc += op;
self.ip += 1;
}
Instruction::Jmp(op) => self.ip = (self.ip as i32 + op) as usize,
}
}
}
}
impl FromStr for Program {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let intrs: Vec<_> = s.split('\n').filter_map(|i| i.parse().ok()).collect();
let executed = vec![false; intrs.len()];
Ok(Program {
ip: 0,
acc: 0,
intrs,
executed,
})
}
}
#[aoc(day8, part1)]
fn solution1(input: &str) -> i32 {
let mut p: Program = input.parse().expect("Failed to parse Program");
p.run()
}
#[aoc(day8, part2)]
fn solution2(input: &str) -> i32 {
let mut p: Program = input.parse().expect("Failed to parse Program");
for bad_ip in 0..p.intrs.len() {
if let Some(acc) = p.debug(bad_ip) {
return acc;
}
p.reset();
}
panic!("no bugfix found")
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT1: &'static str = r#"nop +0
acc +1
jmp +4
acc +3
jmp -3
acc -99
acc +1
jmp -4
acc +6"#;
#[test]
fn make() {
assert_eq!(
INPUT1.parse::<Program>().expect("Failed to parse input"),
Program {
ip: 0,
acc: 0,
intrs: vec![
Instruction::Nop(0),
Instruction::Acc(1),
Instruction::Jmp(4),
Instruction::Acc(3),
Instruction::Jmp(-3),
Instruction::Acc(-99),
Instruction::Acc(1),
Instruction::Jmp(-4),
Instruction::Acc(6),
],
executed: vec![false; 9],
}
);
}
#[test]
fn part1() {
assert_eq!(solution1(&INPUT1), 5);
}
#[test]
fn part2() {
assert_eq!(solution2(&INPUT1), 8);
}
}

View File

@ -5,6 +5,7 @@ pub mod day4;
pub mod day5;
pub mod day6;
pub mod day7;
pub mod day8;
use aoc_runner_derive::aoc_lib;