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>(filename: T) -> Result> { 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 { 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 { '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), } }