parent
6daf2f69ff
commit
bc4b69a40a
@ -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] |
@ -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<dyn Error>; |
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> { |
||||||
|
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()); |
||||||
|
} |
@ -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] |
@ -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<dyn Error>; |
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> { |
||||||
|
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()); |
||||||
|
} |
Loading…
Reference in new issue