Day 12 solution
[?]
Mar 16, 2021, 1:07 AM
OCUJJOPFOAAVUXKRNYTFNNTOYL2TZR2QG2CYSC57GGK2V6UL5IIQCDependencies
- [2]
B527MN66Solve day 1 for 2020
Change contents
- file addition: day12.rs[2.17]
use std::str::FromStr;#[derive(Clone,Copy,PartialEq,Eq)]enum Cardinal {N,S,E,W}#[derive(Clone,Copy,PartialEq,Eq)]enum Direction {C(Cardinal,u16),T(i8),F(u16),}#[derive(Debug)]enum ParseDirectionError {I(std::num::ParseIntError),D(char),Z,}impl From<std::num::ParseIntError> for ParseDirectionError {fn from(src: std::num::ParseIntError) -> Self {Self::I(src)}}impl std::fmt::Display for ParseDirectionError {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {match self {ParseDirectionError::I(e) => e.fmt(f),ParseDirectionError::D(c) => write!(f, "Unrecognised direction code: {}", c),ParseDirectionError::Z => write!(f, "Empty string"),}}}impl FromStr for Direction {type Err = ParseDirectionError;fn from_str(s: &str) -> Result<Self, Self::Err> {if s.len() == 0 {Err(Self::Err::Z)?;};let (c,ns) = s.split_at(1);match c {"N" => {let d = ns.parse::<u16>()?;Ok(Direction::C(Cardinal::N,d))},"S" => {let d = ns.parse::<u16>()?;Ok(Direction::C(Cardinal::S,d))},"E" => {let d = ns.parse::<u16>()?;Ok(Direction::C(Cardinal::E,d))},"W" => {let d = ns.parse::<u16>()?;Ok(Direction::C(Cardinal::W,d))},"L" => {let d = ns.parse::<i16>()?;Ok(Direction::T(((4 - (d / 90)) % 4) as i8))},"R" => {let d = ns.parse::<i16>()?;Ok(Direction::T(((d / 90) % 4) as i8))},"F" => {let d = ns.parse::<u16>()?;Ok(Direction::F(d))},_ => Err(ParseDirectionError::D(c.chars().next().unwrap())),}}}#[derive(Clone,Copy,PartialEq,Eq)]struct Ship {x: i32,y: i32,bearing: Cardinal,waypoint_x: i32,waypoint_y: i32,}impl Ship {fn new() -> Self {Ship {x: 0, y: 0, bearing: Cardinal::E, waypoint_x: 10, waypoint_y: -1 }}fn step(&mut self, dir: Direction, revised: bool) {if revised {match dir {Direction::C(c,d) => match c {Cardinal::N => { self.waypoint_y -= d as i32; },Cardinal::S => { self.waypoint_y += d as i32; },Cardinal::E => { self.waypoint_x += d as i32; },Cardinal::W => { self.waypoint_x -= d as i32; },},Direction::T(qt) => match qt % 4 {0 => {},1 => {let (x,y) = (self.waypoint_x, self.waypoint_y);self.waypoint_x = -y;self.waypoint_y = x;},2 => {let (x,y) = (self.waypoint_x, self.waypoint_y);self.waypoint_x = -x;self.waypoint_y = -y;},3 => {let (x,y) = (self.waypoint_x, self.waypoint_y);self.waypoint_x = y;self.waypoint_y = -x;},_ => panic!("_ % 4 >= 4 !???"),},Direction::F(d) => {self.x += self.waypoint_x * d as i32;self.y += self.waypoint_y * d as i32;},}} else {match dir {Direction::C(c,d) => match c {Cardinal::N => { self.y -= d as i32; },Cardinal::S => { self.y += d as i32; },Cardinal::E => { self.x += d as i32; },Cardinal::W => { self.x -= d as i32; },},Direction::T(qt) => {let sqt: i8 = match self.bearing {Cardinal::N => 8,Cardinal::S => 10,Cardinal::E => 9,Cardinal::W => 11,};self.bearing = match (sqt + qt) % 4 {0 => Cardinal::N,1 => Cardinal::E,2 => Cardinal::S,3 => Cardinal::W,_ => panic!("_ % 4 >= 4 !???"),};},Direction::F(d) => self.step(Direction::C(self.bearing, d), false),}}}}fn main() {use std::io::BufRead;let args: Vec<_> = std::env::args().collect();let mut ship = Ship::new();let file = std::io::BufReader::new(std::fs::File::open(<String as AsRef<std::path::Path>>::as_ref(&args[1])).unwrap());let revised = match args[2].as_ref() {"1" => false,"2" => true,_ => panic!("Version number (1 or 2) expected")};for line in file.lines() {ship.step(line.unwrap().parse().unwrap(), revised);}println!("{}", ship.x.abs() + ship.y.abs());}