This commit is contained in:
Daniel S. 2020-12-08 12:10:22 +01:00
parent d1c0ec56de
commit 703d330980
3 changed files with 120 additions and 1 deletions

View file

@ -1,5 +1,5 @@
use aoc_runner_derive::{aoc, aoc_generator};
use std::collections::{HashMap, HashSet, VecDeque};
use std::collections::{HashMap, VecDeque};
pub struct Data {
fwd: HashMap<String, Vec<(usize, String)>>,

118
src/day8.rs Normal file
View file

@ -0,0 +1,118 @@
use aoc_runner_derive::{aoc, aoc_generator};
use std::collections::HashSet;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)]
pub enum Inst {
Acc { value: i64 },
Jmp { offset: i64 },
Nop { unused: i64 },
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
pub struct CPU {
ip: usize,
program: Vec<Inst>,
acc: i64,
}
impl From<&str> for Inst {
fn from(inst: &str) -> Self {
let mut inst = inst.split_whitespace();
let (inst, arg) = (
inst.next().unwrap(),
inst.next().map(|v| v.parse::<i64>().unwrap()),
);
match inst {
"jmp" => Inst::Jmp {
offset: arg.unwrap(),
},
"acc" => Inst::Acc {
value: arg.unwrap(),
},
"nop" => Inst::Nop {
unused: arg.unwrap(),
},
other => panic!("Invalid instruction: {}", other),
}
}
}
impl CPU {
fn new(pgm: &Vec<Inst>) -> Self {
Self {
ip: 0,
program: pgm.clone(),
acc: 0,
}
}
fn flip(&mut self, idx: usize) {
if let Some(new_inst) = match &self.program[idx] {
Inst::Jmp { offset } => Some(Inst::Nop { unused: *offset }),
Inst::Nop { unused } => Some(Inst::Jmp { offset: *unused }),
_ => None,
} {
self.program[idx] = new_inst;
};
}
fn step(&mut self) -> bool {
// println!("{}: {:?} [Acc: {}]",self.ip,inst, self.acc);
match self.program.get(self.ip) {
Some(Inst::Acc { value }) => {
self.acc += value;
}
Some(Inst::Jmp { offset }) => {
self.ip = ((self.ip as i64) + (offset - 1)) as usize;
}
Some(Inst::Nop { .. }) => (),
None => {
return false;
}
}
self.ip += 1;
return true;
}
}
#[aoc_generator(day8)]
pub fn input_generator(input: &str) -> Vec<Inst> {
input.trim().lines().map(|l| Inst::from(l.trim())).collect()
}
#[aoc(day8, part1)]
pub fn solve_part1(input: &Vec<Inst>) -> usize {
let mut seen = HashSet::new();
let mut cpu = CPU::new(input);
loop {
seen.insert(cpu.ip);
cpu.step();
if seen.contains(&cpu.ip) {
break;
}
}
return cpu.acc as usize;
}
#[aoc(day8, part2)]
pub fn solve_part2(input: &Vec<Inst>) -> usize {
for (idx, inst) in input.iter().enumerate() {
match inst {
Inst::Nop { .. } | Inst::Jmp { .. } => {
let mut seen = HashSet::new();
let mut cpu = CPU::new(input);
cpu.flip(idx);
loop {
seen.insert(cpu.ip);
if !cpu.step() {
return cpu.acc as usize;
};
if seen.contains(&cpu.ip) {
break;
}
}
}
_ => (),
}
}
panic!("Failed to solve part 2");
}

View file

@ -6,4 +6,5 @@ pub mod day4;
pub mod day5;
pub mod day6;
pub mod day7;
pub mod day8;
aoc_lib! { year = 2020 }