diff --git a/Cargo.lock b/Cargo.lock index 560f82a..baa76d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,6 @@ version = "0.1.0" dependencies = [ "lazy_static", "regex", - "usize_cast", ] [[package]] @@ -56,9 +55,3 @@ checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ "lazy_static", ] - -[[package]] -name = "usize_cast" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810f3a98a85147e3ad2a1331aa6dac66490e802d65fa0ab283c383058e3f9751" diff --git a/Cargo.toml b/Cargo.toml index 09b49b5..434f5d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,4 @@ edition = "2018" [dependencies] regex = "1" -lazy_static = "1.4.0" -usize_cast = "1.0.0" \ No newline at end of file +lazy_static = "1.4.0" \ No newline at end of file diff --git a/input/day12.txt b/input/day12.txt new file mode 100644 index 0000000..6c04736 --- /dev/null +++ b/input/day12.txt @@ -0,0 +1,795 @@ +N5 +W1 +F61 +W2 +R90 +F50 +N2 +F40 +E4 +F48 +R180 +F17 +W4 +N5 +F3 +W3 +F1 +R90 +S2 +F23 +L90 +S3 +W3 +S4 +E4 +L90 +W3 +S3 +E4 +N2 +F28 +S2 +W2 +L180 +E3 +R90 +E3 +F83 +W5 +S4 +W3 +N2 +W5 +F90 +N2 +F82 +N2 +F2 +S4 +L90 +N3 +L90 +S2 +F12 +S3 +F40 +L90 +F56 +N1 +F29 +W2 +S2 +R270 +S4 +F14 +E4 +R90 +E2 +S2 +E2 +F82 +L90 +N3 +R180 +R90 +S1 +W1 +L90 +S2 +F78 +W2 +F52 +N4 +W5 +F38 +L90 +W2 +S2 +L90 +F66 +R90 +F62 +E3 +S5 +L90 +F99 +F2 +E4 +R90 +N3 +W4 +N1 +F71 +E2 +N3 +N2 +R90 +E2 +F66 +S4 +R90 +E5 +F29 +E5 +L90 +W2 +N2 +E3 +F18 +L180 +F17 +W1 +R90 +W3 +S5 +R90 +S3 +R180 +N5 +F69 +W1 +W3 +L180 +F72 +W5 +N1 +R180 +W3 +W4 +F85 +W4 +L90 +E4 +N5 +F73 +R90 +F70 +E4 +F79 +S5 +R180 +E2 +F35 +E4 +L270 +W2 +L90 +N5 +R90 +N4 +F64 +W2 +R270 +F33 +N5 +E4 +F94 +W1 +N1 +R90 +F79 +F46 +E1 +R180 +S3 +W3 +F72 +E1 +W4 +F95 +W2 +L90 +N3 +L90 +F85 +W3 +W1 +F54 +N3 +E1 +N4 +E5 +L90 +F61 +W2 +F7 +L180 +F87 +N4 +W1 +F87 +F3 +E3 +F63 +R90 +S4 +R180 +S4 +R180 +R90 +R90 +E5 +N4 +E2 +F86 +S3 +F98 +N4 +F70 +L90 +E4 +F26 +W4 +F19 +L90 +S4 +W4 +F84 +N1 +E4 +L180 +S2 +F74 +S1 +F86 +R90 +S2 +F78 +N4 +S2 +W1 +N5 +E2 +F38 +W4 +N1 +F75 +S1 +E1 +N3 +S1 +F54 +N3 +F88 +N5 +L180 +F15 +S2 +S2 +E2 +N3 +F97 +S3 +N3 +E3 +N5 +E3 +R90 +F87 +L90 +F15 +L90 +E5 +R90 +F70 +N3 +W2 +F47 +W2 +W3 +F17 +R90 +F95 +E4 +F28 +W4 +R90 +E2 +R180 +N4 +R180 +W4 +R270 +F73 +W1 +N2 +L90 +S1 +F65 +E1 +F42 +N2 +F74 +R90 +F21 +W5 +S1 +N5 +R90 +E4 +N5 +S5 +F99 +W4 +L180 +W1 +F83 +N2 +W2 +F87 +E2 +S3 +W1 +L180 +F89 +S1 +W2 +E2 +L90 +S2 +W1 +S5 +R180 +E5 +N1 +F82 +S3 +F7 +L90 +F31 +L90 +N3 +F84 +W3 +N4 +F100 +N1 +E2 +R90 +F90 +N3 +F43 +R90 +F2 +W4 +L90 +F87 +L90 +E3 +F71 +L180 +N1 +L90 +E4 +N3 +F31 +W1 +F80 +R270 +N1 +E4 +N1 +F22 +N4 +E1 +F57 +R90 +N3 +W2 +L180 +N3 +L180 +W4 +F59 +S4 +F10 +N5 +L90 +S3 +L90 +E1 +F96 +E4 +N3 +F54 +L180 +F47 +W1 +N4 +E1 +S4 +R180 +L90 +N1 +R90 +N3 +R90 +N4 +R90 +S3 +F59 +N5 +L90 +E4 +F72 +W4 +F76 +R90 +E3 +F70 +L180 +N3 +W2 +R90 +F65 +L90 +F71 +S3 +F43 +R90 +W2 +N2 +R90 +W1 +R90 +S4 +R180 +S1 +E3 +F72 +L90 +F61 +L90 +F75 +S1 +S5 +F15 +R90 +E3 +N2 +L270 +F48 +N1 +R180 +W2 +F69 +E4 +R90 +R90 +W1 +S5 +W5 +R90 +S4 +S3 +F51 +F43 +E2 +N5 +L180 +F89 +W1 +R90 +F59 +R90 +E2 +F51 +R90 +F91 +W4 +S5 +E4 +L90 +S5 +R90 +F44 +F47 +E4 +W1 +F77 +S5 +R90 +N2 +F87 +N4 +R90 +W5 +R90 +W5 +F89 +L90 +F61 +E2 +F29 +N4 +R90 +F31 +S1 +L90 +E5 +N2 +F7 +L180 +S4 +F63 +W4 +N5 +S2 +N1 +E5 +F87 +S5 +R180 +F14 +W4 +R180 +E1 +L90 +F67 +E2 +L90 +E5 +S2 +L90 +W2 +R90 +F94 +W4 +R90 +W3 +S3 +R90 +N5 +F55 +L90 +F43 +L90 +N5 +F16 +E4 +N2 +L270 +W3 +E1 +N2 +R180 +F51 +N5 +N1 +F36 +W4 +F38 +N5 +W1 +F29 +R180 +L90 +N1 +W3 +E1 +F78 +E1 +N1 +E2 +F57 +E4 +F83 +W5 +F32 +N3 +W4 +F36 +N2 +E3 +F74 +N4 +F54 +W5 +L90 +S1 +F42 +W4 +S5 +E3 +F64 +W2 +R180 +S2 +E1 +N2 +R90 +W3 +F36 +N3 +R90 +S2 +F53 +W2 +F85 +E5 +N2 +F9 +E1 +F83 +L90 +E5 +F44 +L90 +F92 +W5 +R270 +E4 +S1 +F6 +L90 +F96 +R90 +N1 +E4 +N1 +W3 +S2 +S4 +F39 +E1 +S1 +F82 +S3 +F78 +L90 +N4 +E1 +N2 +R90 +F63 +S3 +L180 +F52 +W2 +F49 +W2 +L270 +N1 +R180 +E3 +F79 +F73 +N1 +R90 +N3 +R180 +S2 +F35 +S1 +F43 +S1 +R90 +S4 +W4 +F12 +S1 +F2 +N3 +E4 +L90 +F51 +R90 +N4 +F90 +R90 +F99 +E3 +N1 +R90 +S3 +L270 +W5 +L90 +R270 +F50 +N5 +F33 +S3 +F18 +L90 +E4 +L180 +W4 +R90 +F21 +W4 +F24 +W2 +E5 +N3 +W1 +R90 +W3 +S3 +F82 +W1 +S1 +F12 +N3 +L90 +F37 +R180 +F36 +F27 +E3 +S3 +F36 +W4 +S1 +F6 +R90 +F59 +S1 +E1 +R180 +S2 +W3 +L90 +F45 +R90 +E1 +F29 +S5 +W3 +S5 +W4 +L270 +S2 +F13 +E4 +F28 +R90 +F80 +S4 +E1 +S2 +F62 +R90 +F26 +L180 +F19 +W2 +L180 +W5 +F15 +N1 +F68 +E4 +F75 +S2 +F58 +S4 +R180 +E3 +N1 +L90 +S2 +F12 +R90 +E5 +S5 +W4 +N5 +W1 +R180 +S1 +F70 +R90 +F97 +L90 +E3 +S3 +L270 +E1 +F51 +N4 +L180 +N1 +R90 +F42 \ No newline at end of file diff --git a/input/day12_example.txt b/input/day12_example.txt new file mode 100644 index 0000000..48c2a50 --- /dev/null +++ b/input/day12_example.txt @@ -0,0 +1,5 @@ +F10 +N3 +F7 +R90 +F11 \ No newline at end of file diff --git a/src/day12.rs b/src/day12.rs new file mode 100644 index 0000000..48889a2 --- /dev/null +++ b/src/day12.rs @@ -0,0 +1,174 @@ +use super::util; +use crate::day12::Heading::{North, East, South, West}; +use std::mem::swap; + +pub fn solve() +{ + let lines = util::read_file("input/day12.txt"); + let instructions = lines.iter().map(|s| Instruction::parse(s)).collect::>(); + + let ship_state = execute(&instructions); + let part1 = ship_state.manhattan_distance(); + println!("Day 12 Part 1: {}", part1); + + let ship_state2 = execute_with_waypoint(&instructions); + let part2 = ship_state2.manhattan_distance(); + println!("Day 12 Part 2: {}", part2); +} + +fn execute(instructions: &Vec) -> ShipState { + + let mut res = ShipState { position_n: 0, position_e: 0, heading: East }; + + for instruction in instructions { + res.apply(&instruction); + } + + return res; +} + +fn execute_with_waypoint(instructions: &Vec) -> ShipState { + + let mut ship = ShipState { position_n: 0, position_e: 0, heading: East }; + let mut waypoint = WaypointState { position_n: 1, position_e: 10 }; + + for instruction in instructions { + // println!("Instruction: {}{}", instruction.action, instruction.amount); + + if instruction.action == 'F' { + ship.position_n += waypoint.position_n * instruction.amount as i32; + ship.position_e += waypoint.position_e * instruction.amount as i32; + } else { + waypoint.apply(instruction); + } + // println!("Ship: {:?}, Waypoint: {:?}", ship, waypoint); + } + + return ship; + +} + +#[derive(Debug)] +struct ShipState { + position_n: i32, + position_e: i32, + heading: Heading, +} + +impl ShipState { + fn manhattan_distance(&self) -> i32 { + return self.position_n.abs() + self.position_e.abs(); + } + + fn apply(&mut self, instruction: &Instruction) { + + match instruction.action { + 'N'=> self.position_n += instruction.amount as i32, + 'S' => self.position_n -= instruction.amount as i32, + 'E' => self.position_e += instruction.amount as i32, + 'W' => self.position_e -= instruction.amount as i32, + 'L' => self.turn_left(instruction.amount), + 'R' => self.turn_left(360 - (instruction.amount % 360)), + 'F' => self.move_forward(instruction.amount), + _ => panic!("Unknown instruction: {}", instruction.action) + } + + } + + fn move_forward(&mut self, amount: u32) { + match self.heading { + North => self.position_n += amount as i32, + East => self.position_e += amount as i32, + South => self.position_n -= amount as i32, + West => self.position_e -= amount as i32, + } + } + + fn turn_left(&mut self, amount: u32) { + + assert_eq!(amount % 90, 0, "Only rotations of (multiples of) 90 degrees are supported"); + + let count = amount / 90; + for _ in 0..count { + self.heading = self.heading.turn_left(); + } + } +} + +#[derive(Debug)] +struct WaypointState { + position_n: i32, + position_e: i32, +} + +impl WaypointState { + + fn apply(&mut self, instruction: &Instruction) { + + match instruction.action { + 'N'=> self.position_n += instruction.amount as i32, + 'S' => self.position_n -= instruction.amount as i32, + 'E' => self.position_e += instruction.amount as i32, + 'W' => self.position_e -= instruction.amount as i32, + 'L' => self.rotate_left_around_origin(instruction.amount), + 'R' => self.rotate_left_around_origin(360 - instruction.amount), + _ => panic!("Unknown instruction: {}", instruction.action) + } + } + + fn rotate_left_around_origin(&mut self , amount: u32) { + assert_eq!(amount % 90, 0, "Only rotations of (multiples of) 90 degrees are supported"); + + if amount % 360 == 0 { return; } + + match amount % 360 { + 90 => { + swap(&mut self.position_n, &mut self.position_e); + self.position_e *= -1; + } + 180 => { + self.position_n *= -1; + self.position_e *= -1; + } + 270 => { + swap(&mut self.position_n, &mut self.position_e); + self.position_n *= -1; + } + _ => panic!("Unsupported amount of degrees") + } + } +} + +#[derive(Debug)] +struct Instruction { + action: char, + amount: u32, +} + +#[derive(Debug)] +enum Heading { + North, East, South, West +} + +impl Heading { + + fn turn_left(&self) -> Heading { + return match self { + North => West, + West => South, + South => East, + East => North + }; + } +} + +impl Instruction { + + fn parse(line: &String) -> Instruction { + + return Instruction { + action: line.chars().next().unwrap(), + amount: line[1..].parse::().unwrap(), + } + } +} \ No newline at end of file diff --git a/src/dayX.rs b/src/dayX.rs index c0de2aa..9f532cb 100644 --- a/src/dayX.rs +++ b/src/dayX.rs @@ -2,4 +2,12 @@ use super::util; pub fn solve() { let lines = util::read_file("input/dayX.txt"); + + + let part1 = 0; + println!("Day X Part 1: {}", part1); + + + let part2 = 0; + println!("Day X Part 2: {}", part2); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index bd87e0a..dc9dc91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,8 +13,9 @@ mod day8; mod day9; mod day10; mod day11; +mod day12; -const MAX_DAY: u8 = 11; +const MAX_DAY: u8 = 12; const BENCHMARK_AMOUNT: u32 = 100; fn solve(day: u8) { @@ -30,6 +31,7 @@ fn solve(day: u8) { 9 => day9::solve(), 10 => day10::solve(), 11 => day11::solve(), + 12 => day12::solve(), _ => println!("This day is not yet implemented") } }