From bc4b69a40aa8a5e3d27a4826221bd059f119622d Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Sat, 12 Dec 2020 19:12:07 +0100 Subject: [PATCH] Solution for day 12 --- day12-hard/Cargo.toml | 9 +++ day12-hard/src/main.rs | 130 +++++++++++++++++++++++++++++++++++++++++ day12/Cargo.toml | 9 +++ day12/src/main.rs | 126 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 day12-hard/Cargo.toml create mode 100644 day12-hard/src/main.rs create mode 100644 day12/Cargo.toml create mode 100644 day12/src/main.rs diff --git a/day12-hard/Cargo.toml b/day12-hard/Cargo.toml new file mode 100644 index 0000000..e6ad9fa --- /dev/null +++ b/day12-hard/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day12-hard" +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] diff --git a/day12-hard/src/main.rs b/day12-hard/src/main.rs new file mode 100644 index 0000000..67adda0 --- /dev/null +++ b/day12-hard/src/main.rs @@ -0,0 +1,130 @@ +use std::io::{self, BufRead}; +use std::error::Error; +use std::str::FromStr; + +enum Command { + East(i64), + West(i64), + North(i64), + South(i64), + Left(i64), + Right(i64), + Forward(i64), +} + +impl FromStr for Command { + type Err = Box; + + fn from_str(s: &str) -> Result { + let first_char = match s.chars().next() { + Some(ch) => ch, + _ => { + return Err(Box::from("string is empty")); + } + }; + + let remainder: String = s.chars().skip(1).collect(); + let value: i64 = remainder.parse()?; + + Ok(match first_char { + 'E' => Self::East(value), + 'W' => Self::West(value), + 'N' => Self::North(value), + 'S' => Self::South(value), + 'L' => Self::Left(value), + 'R' => Self::Right(value), + 'F' => Self::Forward(value), + _ => { + return Err(Box::from("unsupported first character")); + } + }) + } +} + +struct State { + ship_offset_north: i64, + ship_offset_east: i64, + waypoint_ship_offset_north: i64, + waypoint_ship_offset_east: i64, +} + +impl State { + fn get_angle_cos(angle: i64) -> i64 { + match angle { + 0 => 1, + 90 => 0, + 180 => -1, + 270 => 0, + _ => panic!("Unsupported angle"), + } + } + + fn get_angle_sin(angle: i64) -> i64 { + match angle { + 0 => 0, + 90 => 1, + 180 => 0, + 270 => -1, + _ => panic!("Unsupported angle"), + } + } + + pub fn new() -> Self { + Self { + ship_offset_north: 0, + ship_offset_east: 0, + waypoint_ship_offset_north: 1, + waypoint_ship_offset_east: 10, + } + } + + pub fn apply_command(&self, command: Command) -> Self { + match command { + Command::East(distance) => Self { + waypoint_ship_offset_east: self.waypoint_ship_offset_east + distance, + ..*self + }, + Command::West(distance) => Self { + waypoint_ship_offset_east: self.waypoint_ship_offset_east - distance, + ..*self + }, + Command::North(distance) => Self { + waypoint_ship_offset_north: self.waypoint_ship_offset_north + distance, + ..*self + }, + Command::South(distance) => Self { + waypoint_ship_offset_north: self.waypoint_ship_offset_north - distance, + ..*self + }, + Command::Left(angle) => Self { + waypoint_ship_offset_east: self.waypoint_ship_offset_east * Self::get_angle_cos(angle) - self.waypoint_ship_offset_north * Self::get_angle_sin(angle), + waypoint_ship_offset_north: self.waypoint_ship_offset_east * Self::get_angle_sin(angle) + self.waypoint_ship_offset_north * Self::get_angle_cos(angle), + ..*self + }, + Command::Right(angle) => Self { + waypoint_ship_offset_east: self.waypoint_ship_offset_east * Self::get_angle_cos(angle) + self.waypoint_ship_offset_north * Self::get_angle_sin(angle), + waypoint_ship_offset_north: -self.waypoint_ship_offset_east * Self::get_angle_sin(angle) + self.waypoint_ship_offset_north * Self::get_angle_cos(angle), + ..*self + }, + Command::Forward(times) => Self { + ship_offset_east: self.ship_offset_east + self.waypoint_ship_offset_east * times, + ship_offset_north: self.ship_offset_north + self.waypoint_ship_offset_north * times, + ..*self + }, + } + } + + pub fn get_manhattan_norm(&self) -> i64 { + self.ship_offset_east.abs() + self.ship_offset_north.abs() + } +} + +fn main() { + let stdin = io::stdin(); + let mut state = State::new(); + for line in stdin.lock().lines() { + state = state.apply_command(line.unwrap().parse().unwrap()); + } + + println!("{}", state.get_manhattan_norm()); +} diff --git a/day12/Cargo.toml b/day12/Cargo.toml new file mode 100644 index 0000000..12fb8d7 --- /dev/null +++ b/day12/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day12" +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] diff --git a/day12/src/main.rs b/day12/src/main.rs new file mode 100644 index 0000000..2b5ed74 --- /dev/null +++ b/day12/src/main.rs @@ -0,0 +1,126 @@ +use std::io::{self, BufRead}; +use std::error::Error; +use std::str::FromStr; + +enum Command { + East(i64), + West(i64), + North(i64), + South(i64), + Left(i64), + Right(i64), + Forward(i64), +} + +impl FromStr for Command { + type Err = Box; + + fn from_str(s: &str) -> Result { + let first_char = match s.chars().next() { + Some(ch) => ch, + _ => { + return Err(Box::from("string is empty")); + } + }; + + let remainder: String = s.chars().skip(1).collect(); + let value: i64 = remainder.parse()?; + + Ok(match first_char { + 'E' => Self::East(value), + 'W' => Self::West(value), + 'N' => Self::North(value), + 'S' => Self::South(value), + 'L' => Self::Left(value), + 'R' => Self::Right(value), + 'F' => Self::Forward(value), + _ => { + return Err(Box::from("unsupported first character")); + } + }) + } +} + +struct State { + offset_north: i64, + offset_east: i64, + angle: i64, +} + +impl State { + fn get_angle_cos(&self) -> i64 { + match self.angle { + 0 => 1, + 90 => 0, + 180 => -1, + 270 => 0, + _ => panic!("Unsupported angle"), + } + } + + fn get_angle_sin(&self) -> i64 { + match self.angle { + 0 => 0, + 90 => 1, + 180 => 0, + 270 => -1, + _ => panic!("Unsupported angle"), + } + } + + pub fn new() -> Self { + Self { + offset_north: 0, + offset_east: 0, + angle: 0 + } + } + + pub fn apply_command(&self, command: Command) -> Self { + match command { + Command::East(distance) => Self { + offset_east: self.offset_east + distance, + ..*self + }, + Command::West(distance) => Self { + offset_east: self.offset_east - distance, + ..*self + }, + Command::North(distance) => Self { + offset_north: self.offset_north + distance, + ..*self + }, + Command::South(distance) => Self { + offset_north: self.offset_north - distance, + ..*self + }, + Command::Left(angle) => Self { + angle: (self.angle + angle).rem_euclid(360), + ..*self + }, + Command::Right(angle) => Self { + angle: (self.angle - angle).rem_euclid(360), + ..*self + }, + Command::Forward(distance) => Self { + offset_east: self.offset_east + self.get_angle_cos() * distance, + offset_north: self.offset_north + self.get_angle_sin() * distance, + ..*self + }, + } + } + + pub fn get_manhattan_norm(&self) -> i64 { + self.offset_east.abs() + self.offset_north.abs() + } +} + +fn main() { + let stdin = io::stdin(); + let mut state = State::new(); + for line in stdin.lock().lines() { + state = state.apply_command(line.unwrap().parse().unwrap()); + } + + println!("{}", state.get_manhattan_norm()); +}