diff options
Diffstat (limited to '2020/rust/day08/src/main.rs')
-rw-r--r-- | 2020/rust/day08/src/main.rs | 97 |
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(®isters.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(®isters.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), + } +} |