From 6a5b143c0fd0a90979d9315b50be2387facb752f Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 19 Apr 2022 20:27:05 +0200 Subject: Refile for merging repos --- 2020/src/bin/day_8.rs | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 2020/src/bin/day_8.rs (limited to '2020/src/bin/day_8.rs') diff --git a/2020/src/bin/day_8.rs b/2020/src/bin/day_8.rs new file mode 100644 index 0000000..2c0c227 --- /dev/null +++ b/2020/src/bin/day_8.rs @@ -0,0 +1,154 @@ +use bevy::{app::AppExit, prelude::*}; +use std::convert::TryFrom; +use std::io::{BufRead, BufReader}; +use std::{collections::BTreeSet, fs::File}; + +fn main() { + App::build() + .add_resource(WindowDescriptor { + title: "Advent of Code".to_string(), + width: 1920, + height: 1080, + ..Default::default() + }) + .add_resource(ClearColor(Color::rgb(0., 0., 0.))) + .add_startup_system(setup_camera.system()) + .add_startup_system(read_input_file.system()) + .add_stage("check_line") + .add_system_to_stage("check_line", track_program_line_execution.system()) + .add_system_to_stage("check_line", track_program_termination.system()) + .add_stage("exec") + .add_system_to_stage("exec", tick_computer.system()) + .add_system_to_stage("exec", exit.system()) + .add_plugins(DefaultPlugins) + .run(); +} + +fn setup_camera(mut commands: Commands) { + commands.spawn(Camera2dComponents::default()); +} + +struct Program { + ops: Vec, +} +#[derive(Clone)] +enum Op { + Acc(i32), + Jmp(i32), + Nop(i32), +} +struct UnalteredProgram; +#[derive(Default)] +struct Computer { + program_counter: i32, + accumulator: i32, + termiated: bool, +} +#[derive(Default)] +struct LineTracker(BTreeSet); + +impl Computer { + fn exec(&mut self, program: &Program) { + if self.termiated { + return; + } + + let x = usize::try_from(self.program_counter).ok(); + match x.and_then(|x| program.ops.get(x)) { + None => {} + Some(Op::Acc(val)) => { + self.accumulator += val; + self.program_counter += 1; + } + Some(Op::Jmp(val)) => { + self.program_counter += val; + } + Some(Op::Nop(_)) => { + self.program_counter += 1; + } + } + if self.program_counter >= program.ops.len() as i32 { + self.termiated = true; + } + } +} + +fn read_input_file(mut commands: Commands) { + let f = File::open("./inputs/day_8.txt").unwrap(); + + let ops: Vec = BufReader::new(f) + .lines() + .map(|line| { + let line = line.unwrap(); + let line = line.trim(); + + let mut line_parts = line.split_whitespace(); + let opcode = line_parts.next().unwrap(); + let val: i32 = line_parts.next().unwrap().parse().unwrap(); + let op = match opcode { + "acc" => Op::Acc(val), + "jmp" => Op::Jmp(val), + "nop" => Op::Nop(val), + _ => panic!("Invalid opcode"), + }; + op + }) + .collect(); + commands.spawn(( + UnalteredProgram, + Program { ops: ops.clone() }, + Computer::default(), + LineTracker::default(), + )); + + for i in 0..ops.len() { + let mut ops = ops.clone(); + ops[i] = match ops[i] { + Op::Nop(v) => Op::Jmp(v), + Op::Jmp(v) => Op::Nop(v), + Op::Acc(v) => Op::Acc(v), + }; + commands.spawn(( + Program { ops: ops.clone() }, + Computer::default(), + LineTracker::default(), + )); + } +} + +fn track_program_line_execution( + mut commands: Commands, + entity: Entity, + mut line_tracker: Mut, + computer: &Computer, + unaltered: Option<&UnalteredProgram>, +) { + if line_tracker.0.contains(&computer.program_counter) { + if unaltered.is_some() { + println!( + "About to execute a line for the second time! Line {}. Accumulator: {}", + computer.program_counter, computer.accumulator + ); + } + commands.despawn(entity); + } else { + line_tracker.0.insert(computer.program_counter); + } +} + +fn track_program_termination(mut commands: Commands, entity: Entity, computer: &Computer) { + if computer.termiated { + println!("Program terminated! Accumulator: {}", computer.accumulator); + commands.despawn(entity); + } +} + +fn tick_computer(mut computer: Mut, program: &Program) { + computer.exec(program); +} + +fn exit(mut exit_events: ResMut>, computers: Query<&Computer>) { + if computers.iter().len() == 0 { + exit_events.send(AppExit); + } +} -- cgit v1.2.3