Files
advent-of-code-2020-rust/src/day8.rs
2020-12-08 11:28:22 +01:00

96 lines
2.4 KiB
Rust

use super::util;
pub fn solve() {
let lines = util::read_file("input/day8.txt");
let program = lines.iter().map(|s| Instruction::parse(s)).collect::<Vec<_>>();
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<Instruction>) -> 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<i32, (i32, String)> {
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::<Vec<_>>();
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::<i32>().unwrap()).unwrap_or(0)
}
}
}
#[derive(Debug, PartialEq, Clone)]
enum Operation {
NOP, ACC, JMP
}