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), } } struct Ship { x: i32, y: i32, waypoint_x: i32, waypoint_y: i32, } impl Ship { fn new() -> Ship { Ship { x: 0, y: 0, waypoint_x: 10, waypoint_y: -1, } } 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) { let wp_x = self.waypoint_x; let wp_y = self.waypoint_y; self.waypoint_x = wp_y; self.waypoint_y = -wp_x; } } fn do_turn_right(&mut self, arg: u32) { for _ in 0..(arg / 90) { let wp_x = self.waypoint_x; let wp_y = self.waypoint_y; self.waypoint_x = -wp_y; self.waypoint_y = wp_x; } } fn do_move(&mut self, m: Movement) { match m { Movement::North(d) => self.waypoint_y -= d as i32, Movement::South(d) => self.waypoint_y += d as i32, Movement::West(d) => self.waypoint_x -= d as i32, Movement::East(d) => self.waypoint_x += d as i32, Movement::Forward(d) => { self.x += self.waypoint_x * d as i32; self.y += self.waypoint_y * 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(()) }