parent
96a9ea7702
commit
aa33f42935
@ -0,0 +1,11 @@ |
||||
[package] |
||||
name = "day08" |
||||
version = "0.1.0" |
||||
authors = ["inga-lovinde <52715130+inga-lovinde@users.noreply.github.com>"] |
||||
edition = "2018" |
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
||||
[dependencies] |
||||
lazy_static = "1.4.0" |
||||
regex = "1" |
@ -0,0 +1,120 @@ |
||||
use std::collections::HashSet; |
||||
use std::io::{self, BufRead}; |
||||
use std::error::Error; |
||||
use std::str::FromStr; |
||||
|
||||
#[macro_use] extern crate lazy_static; |
||||
use regex::Regex; |
||||
|
||||
#[derive(Clone, Copy)] |
||||
enum Instruction { |
||||
Accumulate(i64), |
||||
Jump(i64), |
||||
NoOp(i64), |
||||
} |
||||
|
||||
impl FromStr for Instruction { |
||||
type Err = Box<dyn Error>; |
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> { |
||||
lazy_static! { |
||||
static ref LINE_RE: Regex = Regex::new(r"^(\w+)\s+([+-]?\d+)$").unwrap(); |
||||
} |
||||
|
||||
match LINE_RE.captures(s) { |
||||
Some(captures) => { |
||||
match captures[1].as_ref() { |
||||
"acc" => Ok(Self::Accumulate(captures[2].parse()?)), |
||||
"jmp" => Ok(Self::Jump(captures[2].parse()?)), |
||||
"nop" => Ok(Self::NoOp(captures[2].parse()?)), |
||||
_ => Err(Box::from("wrong command")), |
||||
} |
||||
}, |
||||
_ => Err(Box::from("wrong string format")) |
||||
} |
||||
} |
||||
} |
||||
|
||||
enum ProgramResult { |
||||
Terminated(i64), |
||||
Looped(i64), |
||||
} |
||||
|
||||
struct Program<'a> { |
||||
instructions: &'a[Instruction], |
||||
override_index: i64, |
||||
} |
||||
|
||||
impl<'a> Program<'a> { |
||||
pub fn new(instructions: &'a [Instruction], override_index: i64) -> Self { |
||||
Program { |
||||
instructions, |
||||
override_index, |
||||
} |
||||
} |
||||
|
||||
fn get_instruction(&self, index: i64) -> Option<Instruction> { |
||||
if index < 0 || (index as usize) >= self.instructions.len() { |
||||
return None; |
||||
} |
||||
|
||||
if index != self.override_index { |
||||
return Some(self.instructions[index as usize]); |
||||
} |
||||
|
||||
match self.instructions[index as usize] { |
||||
Instruction::Accumulate(value) => Some(Instruction::Accumulate(value)), |
||||
Instruction::Jump(ignore) => Some(Instruction::NoOp(ignore)), |
||||
Instruction::NoOp(offset) => Some(Instruction::Jump(offset)), |
||||
} |
||||
} |
||||
|
||||
pub fn run(&self) -> ProgramResult { |
||||
let mut current_instruction_index = 0; |
||||
let mut visited_instructions = HashSet::new(); |
||||
let mut accumulator = 0; |
||||
loop { |
||||
if visited_instructions.contains(¤t_instruction_index) { |
||||
return ProgramResult::Looped(accumulator); |
||||
} |
||||
|
||||
visited_instructions.insert(current_instruction_index); |
||||
|
||||
match self.get_instruction(current_instruction_index) { |
||||
Some(Instruction::Accumulate(value)) => { |
||||
accumulator += value; |
||||
}, |
||||
Some(Instruction::Jump(offset)) => { |
||||
current_instruction_index += offset-1; |
||||
} |
||||
Some(Instruction::NoOp(_)) => {}, |
||||
None => { |
||||
return ProgramResult::Terminated(accumulator); |
||||
} |
||||
} |
||||
|
||||
current_instruction_index += 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
fn main() { |
||||
let stdin = io::stdin(); |
||||
let instructions: Vec<_> = stdin.lock().lines().into_iter() |
||||
.map(|line| line.unwrap().parse::<Instruction>().unwrap()) |
||||
.collect(); |
||||
|
||||
let program = Program::new(&instructions, -1); |
||||
match program.run() { |
||||
ProgramResult::Looped(accumulator) => println!("Original program looped: {}", accumulator), |
||||
ProgramResult::Terminated(accumulator) => println!("Original program terminated: {}", accumulator), |
||||
} |
||||
|
||||
for i in 0..instructions.len() { |
||||
let program = Program::new(&instructions, i as i64); |
||||
match program.run() { |
||||
ProgramResult::Looped(_) => {}, |
||||
ProgramResult::Terminated(accumulator) => println!("Program #{} terminated: {}", i, accumulator), |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue