summaryrefslogtreecommitdiff
path: root/2020/rust/day08/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '2020/rust/day08/src/main.rs')
-rw-r--r--2020/rust/day08/src/main.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/2020/rust/day08/src/main.rs b/2020/rust/day08/src/main.rs
new file mode 100644
index 0000000..884ba54
--- /dev/null
+++ b/2020/rust/day08/src/main.rs
@@ -0,0 +1,97 @@
+use anyhow::Result;
+use std::convert::TryFrom;
+use std::env::args;
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+use std::path::Path;
+
+use day08::intcode::{Instruction, Intcode};
+use day08::intcode;
+
+fn read_input<T: AsRef<Path>>(filename: T) -> Result<Vec<Instruction>> {
+ let f = File::open(filename)?;
+ let reader = BufReader::new(f);
+
+ reader.lines()
+ .map(|v| Ok(Instruction::try_from(v?)?))
+ .collect()
+}
+
+fn part1(program: &[Instruction]) -> Result<intcode::Wordsize> {
+ let mut visited = vec![];
+ let mut intcode = Intcode::new();
+ intcode.load(program);
+
+ loop {
+ let registers = intcode.regdump();
+ if visited.contains(&registers.ip) {
+ return Ok(registers.accumulator);
+ }
+ visited.push(registers.ip);
+ intcode.step()?
+ }
+}
+
+fn part2(program: &[Instruction]) -> Option<intcode::Wordsize> {
+ 'reset: for i in 0..program.len() {
+ let mut modified = program.to_vec();
+ match modified.get_mut(i) {
+ Some(instruction) => match instruction {
+ Instruction::Jmp(arg) => *instruction = Instruction::Nop(*arg),
+ Instruction::Nop(arg) => *instruction = Instruction::Jmp(*arg),
+ _ => {},
+ },
+ None => panic!("Invalid loop index"),
+ }
+
+ let mut visited = vec![];
+ let mut intcode = Intcode::new();
+ intcode.load(&modified);
+
+ loop {
+ let registers = intcode.regdump();
+ if visited.contains(&registers.ip) {
+ continue 'reset;
+ }
+ visited.push(registers.ip);
+ match intcode.step() {
+ Ok(_) => {},
+ Err(_) => {
+ // Weird as it might seem, Error is Success in this aoc case.
+ let registers = intcode.regdump();
+ return Some(registers.accumulator);
+ }
+ }
+ }
+ }
+ None
+}
+
+fn main() {
+ let (do_part_1, do_part_2) = aoc::do_parts();
+
+ let filename = match args().nth(1) {
+ Some(f) => f,
+ None => {
+ eprintln!("Missing input filename");
+ std::process::exit(1);
+ },
+ };
+ match read_input(filename) {
+ Ok(input) => {
+ if do_part_1 {
+ match part1(&input) {
+ Ok(solution) => println!("Part1, {}", solution),
+ Err(err) => eprintln!("Part1, {}", err),
+ }
+ }
+ if do_part_2 {
+ match part2(&input) {
+ Some(solution) => println!("Part2, {}", solution),
+ None => eprintln!("Part2, no solution found"),
+ }
+ }
+ },
+ Err(err) => eprintln!("Could not read input: {}", err),
+ }
+}