use super::util; pub fn solve() { let lines = util::read_file("input/day8.txt"); let program = lines.iter().map(|s| Instruction::parse(s)).collect::>(); let part1 = execute(&program); println!("Day 8 Part 1: {}", part1.unwrap_err().0); let part2 = solve_part2(&program); println!("Day 8 Part 2: {}", part2); } fn solve_part2(program: &Vec) -> i32 { for i in 0..program.len() { let ins = &program[i]; if ins.op == Operation::ACC { // No flip needed continue; } let mut new_program = program.to_vec(); new_program[i] = Instruction { op: if ins.op == Operation::JMP { Operation::NOP } else { Operation::JMP }, arg: ins.arg }; let res = execute(&new_program); if res.is_ok() { return res.unwrap(); } } panic!("Couldn't find solution!"); } fn execute(instructions: &[Instruction]) -> Result { let mut acc = 0; let mut p = 0; let mut visited = vec![false; instructions.len()]; loop { if p == instructions.len() { return Result::Ok(acc); } else if p > instructions.len() { return Result::Err((acc, String::from("Out of bounds"))); } else if visited[p] { return Result::Err((acc, String::from("Infinite loop"))); } let ins = &instructions[p]; visited[p] = true; match ins.op { Operation::JMP => p = ((p as i32) + ins.arg) as usize, Operation::ACC => acc += ins.arg, _ => ()/* Nothing to do here */, } if ins.op != Operation::JMP { p += 1; } } } #[derive(Debug, Clone)] struct Instruction { op: Operation, arg: i32 } impl Instruction { fn parse(line: &str) -> Instruction { let split = line.split_ascii_whitespace().collect::>(); let op; match &split.get(0).unwrap()[..] { "acc" => op = Operation::ACC, "jmp" => op = Operation::JMP, "nop" => op = Operation::NOP, _ => panic!("Unknown instruction: {}", split.get(0).unwrap()) } return Instruction { op, arg: split.get(1).map(|x| x.parse::().unwrap()).unwrap_or(0) } } } #[derive(Debug, PartialEq, Clone)] enum Operation { NOP, ACC, JMP }