diff options
author | Irene Knapp <ireneista@gmail.com> | 2020-12-07 22:26:59 -0800 |
---|---|---|
committer | Irene Knapp <ireneista@gmail.com> | 2020-12-07 22:26:59 -0800 |
commit | 41a912de958c72336628239d0196d4f0b7627fd7 (patch) | |
tree | c5d335a10d372a62a8c440cb7fc3ea6785dbf90a | |
parent | e3e71ffb705208cc188ff19a4936880f709aaf12 (diff) |
08
-rw-r--r-- | 08/Cargo.toml | 11 | ||||
-rw-r--r-- | 08/input | 623 | ||||
-rw-r--r-- | 08/src/main.rs | 149 | ||||
-rw-r--r-- | 08/tests/main.rs | 14 | ||||
-rw-r--r-- | Cargo.lock | 8 | ||||
-rw-r--r-- | Cargo.toml | 1 |
6 files changed, 806 insertions, 0 deletions
diff --git a/08/Cargo.toml b/08/Cargo.toml new file mode 100644 index 0000000..dbfa6d2 --- /dev/null +++ b/08/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "advent_08" +version = "0.1.0" +authors = ["Irene Knapp <ireneista@gmail.com>"] +edition = "2018" + +[dependencies] +advent_lib = { path = "../lib" } + +[dev-dependencies] +assert_cmd = "0.10" diff --git a/08/input b/08/input new file mode 100644 index 0000000..1089fa5 --- /dev/null +++ b/08/input @@ -0,0 +1,623 @@ +acc +37 +acc -4 +nop +405 +jmp +276 +acc +39 +acc +40 +acc -3 +jmp +231 +acc +44 +acc +12 +jmp +505 +acc +35 +jmp +282 +acc +23 +jmp +598 +nop +392 +acc +18 +acc +44 +acc +18 +jmp +297 +nop +460 +jmp +152 +nop +541 +acc +33 +jmp -11 +acc -5 +acc +9 +jmp +327 +acc +30 +acc -1 +acc -3 +jmp +50 +acc +22 +acc +18 +acc +33 +acc +37 +jmp +57 +acc -17 +acc -6 +acc -2 +jmp +535 +acc -15 +jmp +279 +acc +34 +acc +44 +acc +41 +jmp +349 +acc +2 +acc +6 +nop +351 +nop +252 +jmp +505 +jmp +1 +jmp +1 +nop +61 +jmp +524 +nop +351 +jmp +399 +acc +1 +nop +397 +acc +39 +nop +141 +jmp +134 +acc +46 +acc +14 +acc +26 +jmp +236 +acc +7 +acc -6 +acc +35 +jmp +397 +acc +15 +jmp +140 +acc +3 +acc -4 +acc +37 +acc +12 +jmp +86 +jmp +416 +jmp +1 +jmp +55 +acc -19 +jmp +536 +jmp +1 +acc -11 +acc +15 +jmp -61 +acc +25 +jmp -25 +acc +50 +acc +43 +jmp +1 +jmp +140 +acc +46 +nop -53 +acc +1 +nop +440 +jmp +488 +jmp +396 +nop +443 +acc +41 +jmp +168 +acc +25 +nop +383 +acc +12 +acc -19 +jmp +21 +acc +29 +acc +30 +jmp +497 +jmp +502 +jmp +417 +nop +351 +acc -15 +jmp +243 +acc +21 +acc +16 +jmp +332 +acc +28 +acc +22 +acc +38 +jmp +476 +acc +8 +acc -11 +jmp +458 +acc +9 +jmp +246 +acc +40 +acc +31 +acc +26 +jmp +218 +acc +27 +acc +9 +nop +347 +jmp +478 +nop +28 +nop +106 +acc +25 +acc -15 +jmp +397 +acc +31 +jmp +231 +acc -4 +nop +136 +acc +14 +jmp +181 +jmp +361 +acc +16 +acc +11 +jmp -108 +nop +299 +acc +21 +acc -2 +jmp -106 +jmp +246 +acc +31 +jmp +407 +jmp +377 +acc +43 +acc -12 +nop +142 +acc +8 +jmp -91 +jmp +1 +acc +34 +acc +5 +acc +31 +jmp +12 +acc +34 +acc +7 +acc +34 +acc +20 +jmp -45 +acc -11 +acc +41 +acc +10 +jmp +310 +nop -106 +jmp -36 +acc +23 +acc +46 +acc +46 +jmp +112 +acc +41 +nop +179 +acc +17 +nop +356 +jmp +147 +acc +42 +nop +49 +jmp +119 +acc +0 +acc +7 +acc -18 +acc -8 +jmp +11 +acc +12 +acc +38 +acc +39 +jmp +281 +nop +186 +jmp +162 +acc +44 +acc +20 +jmp +153 +jmp +395 +acc +49 +jmp +1 +acc +2 +jmp +1 +jmp -31 +jmp +301 +nop +97 +jmp -102 +jmp +262 +acc +28 +acc -15 +acc +44 +acc -13 +jmp +191 +jmp +281 +acc +36 +acc +1 +nop +15 +jmp +211 +acc +6 +acc -4 +jmp +42 +acc +34 +acc +0 +jmp +104 +jmp +311 +jmp +84 +acc +43 +acc -8 +acc -10 +acc +38 +jmp -90 +acc +49 +jmp +303 +nop +132 +jmp +301 +nop +60 +acc +37 +nop +96 +jmp +182 +acc +16 +acc +18 +nop +152 +acc +19 +jmp +325 +jmp -63 +acc +28 +jmp +56 +acc +18 +acc +29 +acc +33 +jmp -115 +acc +47 +acc +19 +jmp +1 +nop +41 +jmp +1 +jmp -207 +nop -62 +acc -9 +acc +42 +acc -12 +jmp -56 +acc +28 +jmp -163 +acc +25 +acc +17 +jmp -217 +acc +7 +jmp +272 +acc +43 +acc +22 +jmp +70 +acc -17 +jmp -117 +acc +24 +acc +26 +nop -275 +jmp -46 +nop +87 +acc +19 +acc +28 +jmp -34 +acc +4 +acc +9 +acc +6 +jmp +1 +jmp +28 +acc -6 +nop -67 +acc -10 +jmp +271 +acc +40 +acc +25 +acc -4 +jmp -63 +acc +46 +jmp +78 +acc +41 +nop -126 +nop +70 +jmp +1 +jmp +172 +nop +270 +jmp +30 +jmp +1 +acc +38 +nop +68 +acc +29 +jmp +253 +acc -18 +jmp -89 +acc +18 +acc +30 +jmp +147 +acc +24 +acc +11 +acc +50 +jmp -225 +jmp -210 +acc -18 +acc +1 +acc +38 +jmp +1 +jmp -79 +acc +45 +acc +12 +jmp +209 +jmp -207 +acc +32 +acc +4 +acc +32 +acc +14 +jmp +83 +acc +13 +acc +1 +acc +46 +acc +38 +jmp +28 +nop +153 +acc -17 +jmp -73 +acc +11 +jmp +248 +acc +29 +acc +45 +acc +16 +jmp +96 +jmp -273 +acc +34 +jmp +87 +nop +99 +acc -3 +jmp -74 +acc +12 +nop -119 +jmp -141 +acc -18 +nop -79 +acc +1 +acc +6 +jmp +9 +acc +3 +acc +44 +acc +39 +jmp -165 +acc +6 +jmp +44 +acc +25 +jmp -133 +acc +0 +jmp +14 +jmp +1 +acc +1 +jmp -223 +jmp +71 +nop -1 +acc +22 +acc +11 +jmp -274 +jmp -330 +acc +45 +jmp +1 +acc +15 +jmp -158 +jmp -128 +acc +50 +acc +26 +jmp -73 +nop +99 +jmp +71 +acc +35 +acc +7 +jmp +192 +acc +13 +jmp +190 +acc +4 +acc -1 +acc +40 +acc -15 +jmp +50 +acc +29 +jmp -337 +jmp -75 +acc +41 +jmp +1 +jmp -387 +acc +28 +acc +18 +acc +19 +jmp -62 +nop -196 +jmp -410 +jmp +1 +acc -17 +jmp -267 +acc +22 +jmp -301 +nop -98 +acc -15 +jmp -124 +acc +45 +acc -18 +acc +15 +acc +42 +jmp -296 +nop -10 +acc +29 +jmp -371 +acc +3 +jmp +1 +nop +61 +acc +5 +jmp -361 +acc -5 +nop -326 +jmp -379 +acc -10 +jmp +1 +acc +44 +jmp -231 +acc +3 +jmp -94 +acc +1 +jmp +113 +jmp -336 +acc +4 +jmp -299 +acc -13 +jmp +1 +acc +13 +jmp +143 +acc -11 +acc -19 +acc +18 +nop -390 +jmp -27 +acc +42 +jmp -232 +acc +15 +jmp -228 +acc +21 +acc +39 +acc +47 +acc +6 +jmp +57 +acc +28 +acc +27 +acc +50 +jmp -397 +acc +12 +jmp -445 +acc +30 +jmp -352 +acc -4 +acc +26 +acc +48 +jmp +1 +jmp -205 +jmp +22 +nop -284 +acc -1 +nop -361 +acc +0 +jmp -368 +acc -17 +nop -223 +jmp -41 +acc +4 +acc +46 +jmp +79 +jmp -370 +jmp -260 +acc +42 +jmp -14 +acc +30 +acc +50 +acc +13 +jmp -61 +acc +46 +jmp -63 +nop -55 +nop -320 +jmp -11 +acc +10 +jmp -424 +jmp -11 +acc +3 +jmp -71 +acc +42 +acc -13 +jmp +4 +nop -155 +nop -138 +jmp +62 +acc +11 +acc +19 +acc +15 +acc +17 +jmp -73 +acc -11 +jmp -273 +acc +8 +acc +6 +acc -7 +acc +41 +jmp -311 +jmp -111 +jmp -260 +jmp +50 +jmp -60 +jmp +1 +nop -89 +acc +36 +acc +14 +jmp -220 +nop -415 +acc +28 +jmp -402 +acc +41 +jmp -165 +acc +9 +acc -13 +acc -18 +acc +18 +jmp -504 +acc -9 +acc +29 +acc +44 +jmp -444 +acc +5 +acc +47 +jmp -545 +acc +23 +acc +7 +nop -240 +jmp -320 +jmp -141 +jmp +1 +acc +28 +nop -287 +jmp -118 +acc +44 +acc -7 +jmp -550 +acc +10 +acc +20 +acc -3 +jmp -401 +acc +45 +acc +36 +jmp -375 +jmp -485 +acc +9 +jmp -338 +jmp -510 +jmp -196 +acc -16 +jmp -372 +acc +0 +jmp -380 +acc -3 +nop -473 +nop -361 +jmp -311 +acc +0 +nop +20 +jmp -436 +acc +9 +jmp +1 +jmp -215 +acc +19 +jmp -451 +jmp -43 +acc -13 +acc -10 +acc -5 +jmp -208 +acc -11 +jmp -156 +acc +11 +acc -2 +nop -357 +jmp -73 +acc +21 +jmp -159 +acc +28 +acc -16 +acc +12 +acc +1 +jmp -282 +jmp -131 +acc -11 +acc +45 +acc +0 +acc +28 +jmp +1 diff --git a/08/src/main.rs b/08/src/main.rs new file mode 100644 index 0000000..b25d85e --- /dev/null +++ b/08/src/main.rs @@ -0,0 +1,149 @@ +use advent_lib::prelude::*; + +use std::convert::TryFrom; +use std::collections::BTreeSet; + +#[derive(Clone, Debug)] +enum Operation { + Accumulator(isize), + Jump(isize), + NoOp(isize), +} + +#[derive(Clone, Debug)] +struct MachineState { + accumulator: isize, + program_counter: usize, +} + +impl MachineState { + fn new() -> MachineState { + MachineState { + accumulator: 0, + program_counter: 0, + } + } +} + + +fn main() -> Result<()> { + let mut args = std::env::args(); + if args.len() != 2 { + eprintln!("Usage: advent input"); + } + let _ = args.next(); + let filename = args.next().unwrap(); + + let input = advent_lib::read_lines_file(&filename)?; + + let program = parse_program(&input)?; + + find_first_loop(&program); + + find_patch_to_terminate(&program); + + Ok(()) +} + + +fn parse_program(input: &Vec<String>) -> Result<Vec<Operation>> { + let mut program: Vec<Operation> = Vec::new(); + + for line in input { + let mut words = Vec::new(); + for word in line.split(' ') { + words.push(word); + } + + let operand = words[1].parse::<isize>()?; + match words[0] { + "acc" => program.push(Operation::Accumulator(operand)), + "jmp" => program.push(Operation::Jump(operand)), + "nop" => program.push(Operation::NoOp(operand)), + _ => panic!() + } + } + + Ok(program) +} + + +fn simulate_one(program: &Vec<Operation>, state: &MachineState) -> MachineState { + let mut new_state = state.clone(); + + match program[new_state.program_counter] { + Operation::Accumulator(operand) => { + new_state.accumulator += operand; + new_state.program_counter += 1; + }, + Operation::Jump(operand) => { + new_state.program_counter = usize::try_from( + isize::try_from(new_state.program_counter).unwrap() + + operand).unwrap(); + }, + Operation::NoOp(_) => { + new_state.program_counter += 1; + }, + } + + new_state +} + + +fn find_first_loop(program: &Vec<Operation>) -> () { + let mut visited_lines: BTreeSet<usize> = BTreeSet::new(); + let mut state = MachineState::new(); + + loop { + if visited_lines.contains(&state.program_counter) { + println!("{}", state.accumulator); + break; + } + + visited_lines.insert(state.program_counter); + state = simulate_one(&program, &state); + } +} + + +fn find_patch_to_terminate(program: &Vec<Operation>) -> () { + for i in 0..program.len() { + let mut patched_program = program.clone(); + + match patched_program[i] { + Operation::Accumulator(_) => { + continue; + }, + Operation::Jump(operand) => { + patched_program[i] = Operation::NoOp(operand); + }, + Operation::NoOp(operand) => { + patched_program[i] = Operation::Jump(operand); + }, + } + + let mut visited_lines: BTreeSet<usize> = BTreeSet::new(); + let mut state = MachineState::new(); + let mut normal_exit = false; + + loop { + if visited_lines.contains(&state.program_counter) { + break; + } + + if state.program_counter == patched_program.len() { + println!("normal exit {}", state.accumulator); + normal_exit = true; + break; + } + + visited_lines.insert(state.program_counter); + state = simulate_one(&patched_program, &state); + } + + if normal_exit { + break; + } + } +} + diff --git a/08/tests/main.rs b/08/tests/main.rs new file mode 100644 index 0000000..3761615 --- /dev/null +++ b/08/tests/main.rs @@ -0,0 +1,14 @@ +use assert_cmd::prelude::*; +use std::process::Command; + + +#[test] +fn personal_input() -> Result<(), Box<dyn std::error::Error>> { + let mut command = Command::cargo_bin("advent_08")?; + + command.arg("input"); + command.assert().success().stdout("1801\nnormal exit 2060\n"); + + Ok(()) +} + diff --git a/Cargo.lock b/Cargo.lock index 48da977..9a04392 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,6 +59,14 @@ dependencies = [ ] [[package]] +name = "advent_08" +version = "0.1.0" +dependencies = [ + "advent_lib", + "assert_cmd", +] + +[[package]] name = "advent_lib" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 48403e3..e72d2a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ members = [ "05", "06", "07", + "08", ] |