use std::error::Error; use std::fs::File; use std::io::{self, BufRead}; #[derive(PartialEq, Copy, Clone)] enum Movement { North(u32), South(u32), East(u32), West(u32), Forward(u32), TurnLeft(u32), TurnRight(u32), } fn line_to_movement(line: &str) -> Movement { let cmd = line.get(0..1).unwrap(); let arg: u32 = line.get(1..).unwrap().parse().unwrap(); match cmd { "N" => Movement::North(arg), "S" => Movement::South(arg), "W" => Movement::West(arg), "E" => Movement::East(arg), "F" => Movement::Forward(arg), "R" => Movement::TurnRight(arg), "L" => Movement::TurnLeft(arg), _ => panic!("Unkown command: {}", line), } } #[derive(PartialEq, Copy, Clone)] enum Direction { North, South, East, West, } struct Ship { x: i32, y: i32, direction: Direction, } impl Ship { fn new() -> Ship { Ship { x: 0, y: 0, direction: Direction::East, } } fn get_manhattan_distance(&self) -> u32 { self.x.abs() as u32 + self.y.abs() as u32 } fn do_turn_left(&mut self, arg: u32) { for _ in 0..(arg / 90) { self.direction = match self.direction { Direction::North => Direction::West, Direction::South => Direction::East, Direction::West => Direction::South, Direction::East => Direction::North, } } } fn do_turn_right(&mut self, arg: u32) { for _ in 0..(arg / 90) { self.direction = match self.direction { Direction::North => Direction::East, Direction::South => Direction::West, Direction::West => Direction::North, Direction::East => Direction::South, }; } } fn do_move(&mut self, m: Movement) { match m { Movement::North(d) => self.y -= d as i32, Movement::South(d) => self.y += d as i32, Movement::West(d) => self.x -= d as i32, Movement::East(d) => self.x += d as i32, Movement::Forward(d) => match self.direction { Direction::North => self.y -= d as i32, Direction::South => self.y += d as i32, Direction::West => self.x -= d as i32, Direction::East => self.x += d as i32, }, Movement::TurnLeft(arg) => self.do_turn_left(arg), Movement::TurnRight(arg) => self.do_turn_right(arg), }; } } fn main() -> Result<(), Box> { let file = File::open("inputs/day12.txt")?; let lines = io::BufReader::new(file).lines().map(|l| l.unwrap()); let moves = lines.map(|l| line_to_movement(&l)); let ship = moves.fold(Ship::new(), |mut s, m| { s.do_move(m); s }); println!("Distance: {}", ship.get_manhattan_distance()); Ok(()) }