summaryrefslogtreecommitdiff
path: root/src/bin/day_8.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/day_8.rs')
-rw-r--r--src/bin/day_8.rs153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/bin/day_8.rs b/src/bin/day_8.rs
new file mode 100644
index 0000000..c7df9f5
--- /dev/null
+++ b/src/bin/day_8.rs
@@ -0,0 +1,153 @@
+use bevy::{app::AppExit, prelude::*};
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+use std::{collections::BTreeMap, convert::TryFrom};
+
+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<Op>,
+}
+#[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(BTreeMap<i32, usize>);
+
+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<Op> = 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<LineTracker>,
+ computer: &Computer,
+ unaltered: Option<&UnalteredProgram>,
+) {
+ *line_tracker.0.entry(computer.program_counter).or_insert(0) += 1;
+ if *line_tracker.0.get(&computer.program_counter).unwrap() > 1 {
+ if unaltered.is_some() {
+ println!(
+ "About to execute a line for the second time! Line {}. Accumulator: {}",
+ computer.program_counter, computer.accumulator
+ );
+ }
+ commands.despawn(entity);
+ }
+}
+
+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<Computer>, program: &Program) {
+ computer.exec(program);
+}
+
+fn exit(mut exit_events: ResMut<Events<AppExit>>, computers: Query<&Computer>) {
+ if computers.iter().len() == 0 {
+ exit_events.send(AppExit);
+ }
+}