Added AOC 2020 day 03 - 14
This commit is contained in:
167
www/statics/aoc/2020/08_solution.rs
Normal file
167
www/statics/aoc/2020/08_solution.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
use crate::common::AdventOfCodeDay;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct HGCProgramm {
|
||||
code: Vec<HGCCommand>,
|
||||
}
|
||||
|
||||
impl HGCProgramm {
|
||||
fn parse_program(codestr: String) -> HGCProgramm {
|
||||
HGCProgramm {
|
||||
code: codestr.lines().map(HGCCommand::parse).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct HGCCommand {
|
||||
cmdtype: HGCCommandType,
|
||||
argument: i32,
|
||||
}
|
||||
|
||||
impl HGCCommand {
|
||||
fn parse(line: &str) -> HGCCommand {
|
||||
let (str_cmd, str_arg) = line.split(' ').collect_tuple::<(_, _)>().unwrap();
|
||||
HGCCommand {
|
||||
cmdtype: HGCCommandType::parse(str_cmd),
|
||||
argument: str_arg.parse::<i32>().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum HGCCommandType {
|
||||
NOP,
|
||||
ACC,
|
||||
JMP,
|
||||
}
|
||||
|
||||
impl HGCCommandType {
|
||||
fn parse(val: &str) -> HGCCommandType {
|
||||
match val {
|
||||
"acc" => HGCCommandType::ACC,
|
||||
"jmp" => HGCCommandType::JMP,
|
||||
"nop" => HGCCommandType::NOP,
|
||||
_ => panic!("not a cmd")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for HGCCommandType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct HGCMachineState {
|
||||
trace: bool,
|
||||
|
||||
acc: i32,
|
||||
ip: usize,
|
||||
}
|
||||
|
||||
impl HGCMachineState {
|
||||
fn new() -> HGCMachineState {
|
||||
HGCMachineState {
|
||||
trace: is_verbose!(),
|
||||
|
||||
acc: 0,
|
||||
ip: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_step(&mut self, prog: &HGCProgramm) {
|
||||
self.exec_single(&prog.code[self.ip])
|
||||
}
|
||||
|
||||
fn exec_single(&mut self, cmd: &HGCCommand) {
|
||||
if self.trace {
|
||||
verboseln!("ip: {: <4} || cmd:[{}({: <5})] (acc: {})", self.ip, cmd.cmdtype, cmd.argument, self.acc)
|
||||
}
|
||||
|
||||
if cmd.cmdtype == HGCCommandType::NOP {
|
||||
self.ip += 1;
|
||||
} else if cmd.cmdtype == HGCCommandType::JMP {
|
||||
self.ip = (self.ip as i32 + cmd.argument) as usize;
|
||||
} else if cmd.cmdtype == HGCCommandType::ACC {
|
||||
self.acc += cmd.argument;
|
||||
self.ip += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Day08 {
|
||||
input: HGCProgramm,
|
||||
}
|
||||
|
||||
impl Day08 {
|
||||
pub fn new() -> Self {
|
||||
let input_bytes = include_bytes!("../res/08_input.txt");
|
||||
let input_str = String::from_utf8_lossy(input_bytes);
|
||||
|
||||
Self {
|
||||
input: HGCProgramm::parse_program(input_str.to_owned().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn find_loop(prog: &HGCProgramm) -> (i32, bool) {
|
||||
let mut vm = HGCMachineState::new();
|
||||
|
||||
let mut visited: HashSet<usize> = HashSet::new();
|
||||
visited.insert(vm.ip);
|
||||
|
||||
loop {
|
||||
vm.exec_step(prog);
|
||||
if visited.contains(&vm.ip) {
|
||||
return (vm.acc, false);
|
||||
}
|
||||
visited.insert(vm.ip);
|
||||
|
||||
if vm.ip == prog.code.len() {
|
||||
return (vm.acc, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AdventOfCodeDay for Day08 {
|
||||
|
||||
fn task_1(&self) -> String {
|
||||
return Day08::find_loop(&self.input).0.to_string();
|
||||
}
|
||||
|
||||
fn task_2(&self) -> String {
|
||||
for i in 0..self.input.code.len() {
|
||||
if self.input.code[i].cmdtype == HGCCommandType::ACC {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut progclone = self.input.clone();
|
||||
|
||||
if self.input.code[i].cmdtype == HGCCommandType::JMP {
|
||||
progclone.code[i] = HGCCommand {
|
||||
cmdtype: HGCCommandType::NOP,
|
||||
argument: self.input.code[i].argument,
|
||||
}
|
||||
} else if self.input.code[i].cmdtype == HGCCommandType::NOP {
|
||||
progclone.code[i] = HGCCommand {
|
||||
cmdtype: HGCCommandType::JMP,
|
||||
argument: self.input.code[i].argument,
|
||||
}
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
|
||||
if let (acc, true) = Day08::find_loop(&progclone) {
|
||||
return acc.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user