Day 8
This commit is contained in:
parent
d1c0ec56de
commit
703d330980
3 changed files with 120 additions and 1 deletions
|
@ -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
118
src/day8.rs
Normal 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");
|
||||
}
|
|
@ -6,4 +6,5 @@ pub mod day4;
|
|||
pub mod day5;
|
||||
pub mod day6;
|
||||
pub mod day7;
|
||||
pub mod day8;
|
||||
aoc_lib! { year = 2020 }
|
||||
|
|
Loading…
Reference in a new issue