96 lines
2.4 KiB
Rust
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
|
|
}
|