diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:33:11 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:33:11 +0200 |
commit | 2a939b5e97604d3129b888f15c9876ffd3a7fe5a (patch) | |
tree | d4ae8114a9527a2e46464ce32b80476a5831fdbb /2020/src/bin/day_12.rs | |
parent | 2410e500560a1989399c8ad0c23fe7aa9827576d (diff) | |
parent | 6a5b143c0fd0a90979d9315b50be2387facb752f (diff) |
Merge branch '2020-main'
Diffstat (limited to '2020/src/bin/day_12.rs')
-rw-r--r-- | 2020/src/bin/day_12.rs | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/2020/src/bin/day_12.rs b/2020/src/bin/day_12.rs new file mode 100644 index 0000000..489cdca --- /dev/null +++ b/2020/src/bin/day_12.rs @@ -0,0 +1,233 @@ +use bevy::prelude::*; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::ops::Deref; + +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_system(move_normal_ship.system()) + .add_system(move_waypoint_ship.system()) + .add_plugins(DefaultPlugins) + .run(); +} + +fn setup_camera(mut commands: Commands) { + commands.spawn(Camera2dComponents::default()); +} + +#[derive(PartialEq, Eq, Clone, Copy)] +struct Position { + x: i64, + y: i64, +} +impl Position { + fn manhattan_distance(&self, other: &Position) -> i64 { + (self.x - other.x).abs() + (self.y - other.y).abs() + } +} +impl std::ops::Add<&Position> for &Position { + type Output = Position; + fn add(self, other: &Position) -> Self::Output { + Position { + x: self.x + other.x, + y: self.y + other.y, + } + } +} +impl std::ops::Mul<i64> for Position { + type Output = Position; + fn mul(self, other: i64) -> Self::Output { + Position { + x: self.x * other, + y: self.y * other, + } + } +} + +enum Facing { + North, + South, + East, + West, +} +impl Facing { + fn right(&mut self) { + use Facing::*; + *self = match self { + North => East, + East => South, + South => West, + West => North, + } + } + + fn reverse(&mut self) { + self.right(); + self.right(); + } + + fn left(&mut self) { + self.reverse(); + self.right(); + } +} + +struct Instructions(Vec<Instruction>); +#[derive(Clone)] +enum Instruction { + North(i64), + South(i64), + East(i64), + West(i64), + Left(i64), + Right(i64), + Forward(i64), +} + +struct InstructionPointer(usize); + +struct Waypoint(Position); + +fn read_input_file(mut commands: Commands) { + let f = File::open("./inputs/day_12.txt").unwrap(); + + let instructions: Vec<Instruction> = BufReader::new(f) + .lines() + .map(|line| { + let line = line.unwrap(); + let line = line.trim(); + + let val: i64 = line[1..].parse().unwrap(); + let instruction = match line.chars().next().unwrap() { + 'N' => Instruction::North(val), + 'S' => Instruction::South(val), + 'E' => Instruction::East(val), + 'W' => Instruction::West(val), + 'L' => Instruction::Left(val), + 'R' => Instruction::Right(val), + 'F' => Instruction::Forward(val), + other => panic!("Unknown instruction: {}", other), + }; + instruction + }) + .collect(); + + commands.spawn(( + Instructions(instructions.clone()), + InstructionPointer(0), + Facing::East, + Position { x: 0, y: 0 }, + )); + + commands.spawn(( + Waypoint(Position { x: 10, y: 1 }), + Instructions(instructions), + InstructionPointer(0), + Position { x: 0, y: 0 }, + )); +} + +fn move_normal_ship( + mut q: Query< + Without< + Waypoint, + ( + &Instructions, + &mut InstructionPointer, + &mut Facing, + &mut Position, + ), + >, + >, +) { + for (instructions, mut instruction_pointer, mut facing, mut position) in q.iter_mut() { + if let Some(instruction) = instructions.0.get(instruction_pointer.0) { + use Instruction::*; + match instruction { + North(val) => position.y += val, + South(val) => position.y -= val, + East(val) => position.x += val, + West(val) => position.x -= val, + Left(90) | Right(270) => facing.left(), + Left(180) | Right(180) => facing.reverse(), + Left(270) | Right(90) => facing.right(), + Left(val) | Right(val) => panic!("Unknown left/right val: {}", val), + Forward(val) => match facing.deref() { + Facing::North => position.y += val, + Facing::South => position.y -= val, + Facing::East => position.x += val, + Facing::West => position.x -= val, + }, + }; + + instruction_pointer.0 += 1; + } else { + println!( + "Normal Ship at destination: {} x {}, Manhattan distance: {}", + position.x, + position.y, + position.manhattan_distance(&Position { x: 0, y: 0 }) + ); + } + } +} + +fn move_waypoint_ship( + instructions: &Instructions, + mut waypoint: Mut<Waypoint>, + mut instruction_pointer: Mut<InstructionPointer>, + mut position: Mut<Position>, +) { + if let Some(instruction) = instructions.0.get(instruction_pointer.0) { + use Instruction::*; + match instruction { + North(val) => waypoint.0.y += val, + South(val) => waypoint.0.y -= val, + East(val) => waypoint.0.x += val, + West(val) => waypoint.0.x -= val, + Left(90) | Right(270) => { + waypoint.0 = Position { + x: -waypoint.0.y, + y: waypoint.0.x, + } + } + Left(180) | Right(180) => { + waypoint.0 = Position { + x: -waypoint.0.x, + y: -waypoint.0.y, + } + } + Left(270) | Right(90) => { + waypoint.0 = Position { + x: waypoint.0.y, + y: -waypoint.0.x, + } + } + Left(val) | Right(val) => panic!("Unknown left/right val: {}", val), + Forward(val) => *position = position.deref() + &(waypoint.0 * *val), + }; + + // println!( + // "Position: {} x {}. Waypoint: {} x {}", + // position.x, position.y, waypoint.0.x, waypoint.0.y + // ); + + instruction_pointer.0 += 1; + } else { + println!( + "Waypoint Ship at destination: {} x {}, Manhattan distance: {}", + position.x, + position.y, + position.manhattan_distance(&Position { x: 0, y: 0 }) + ); + } +} |