mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implementation day 8
This commit is contained in:
123
2020/src/day08.rs
Normal file
123
2020/src/day08.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use std::convert::Infallible;
|
||||
use std::io::Read;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::common::from_lines;
|
||||
use crate::Solution;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum Instruction {
|
||||
Acc(i32),
|
||||
Jmp(i32),
|
||||
Nop(i32),
|
||||
}
|
||||
|
||||
impl FromStr for Instruction {
|
||||
type Err = Infallible;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut split = s.split(' ');
|
||||
|
||||
let command = split.next().unwrap();
|
||||
let argument: i32 = split.next().unwrap().parse().unwrap();
|
||||
|
||||
let instruction = match command {
|
||||
"nop" => Instruction::Nop(argument),
|
||||
"acc" => Instruction::Acc(argument),
|
||||
"jmp" => Instruction::Jmp(argument),
|
||||
_ => panic!("Unknown command '{}'", command),
|
||||
};
|
||||
|
||||
Ok(instruction)
|
||||
}
|
||||
}
|
||||
|
||||
fn run_program(program: &[Instruction]) -> (i32, usize) {
|
||||
let mut accumulator = 0;
|
||||
let mut pc = 0;
|
||||
let mut visited = vec![false; program.len()];
|
||||
|
||||
while pc < program.len() {
|
||||
if visited[pc] {
|
||||
return (accumulator, pc);
|
||||
}
|
||||
|
||||
visited[pc] = true;
|
||||
|
||||
match program[pc] {
|
||||
Instruction::Acc(n) => accumulator += n,
|
||||
Instruction::Jmp(n) => {
|
||||
if n > 0 {
|
||||
pc += n as usize;
|
||||
} else {
|
||||
pc -= (-n) as usize;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Instruction::Nop(_) => {}
|
||||
}
|
||||
|
||||
pc += 1;
|
||||
}
|
||||
|
||||
(accumulator, pc)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Day08;
|
||||
|
||||
impl Solution for Day08 {
|
||||
fn part1(&mut self, input: &mut dyn Read) -> String {
|
||||
let program: Vec<Instruction> = from_lines(input);
|
||||
run_program(&program).0.to_string()
|
||||
}
|
||||
|
||||
fn part2(&mut self, input: &mut dyn Read) -> String {
|
||||
let mut program: Vec<Instruction> = from_lines(input);
|
||||
|
||||
for i in 0..program.len() {
|
||||
if let Instruction::Nop(n) = program[i] {
|
||||
program[i] = Instruction::Jmp(n);
|
||||
|
||||
let (acc, pc) = run_program(&program);
|
||||
|
||||
if pc == program.len() {
|
||||
return acc.to_string();
|
||||
}
|
||||
|
||||
program[i] = Instruction::Nop(n);
|
||||
} else if let Instruction::Jmp(n) = program[i] {
|
||||
program[i] = Instruction::Nop(n);
|
||||
|
||||
let (acc, pc) = run_program(&program);
|
||||
|
||||
if pc == program.len() {
|
||||
return acc.to_string();
|
||||
}
|
||||
|
||||
program[i] = Instruction::Jmp(n);
|
||||
}
|
||||
}
|
||||
|
||||
panic!("No solution found")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::test_implementation;
|
||||
|
||||
use super::*;
|
||||
|
||||
const SAMPLE: &[u8] = include_bytes!("../samples/08.txt");
|
||||
|
||||
#[test]
|
||||
fn sample_part1() {
|
||||
test_implementation!(Day08, 1, SAMPLE, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_part2() {
|
||||
test_implementation!(Day08, 2, SAMPLE, 8);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ mod day04;
|
||||
mod day05;
|
||||
mod day06;
|
||||
mod day07;
|
||||
mod day08;
|
||||
|
||||
pub trait Solution {
|
||||
fn part1(&mut self, input: &mut dyn Read) -> String;
|
||||
@@ -26,6 +27,7 @@ pub fn get_implementation(day: usize) -> Box<dyn Solution> {
|
||||
5 => Box::new(day05::Day05::default()),
|
||||
6 => Box::new(day06::Day06::default()),
|
||||
7 => Box::new(day07::Day07::default()),
|
||||
8 => Box::new(day08::Day08::default()),
|
||||
_ => panic!("Unsupported day {}", day),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user