Day03 - part2
authorGrégory Burri <gregory.burri@matisa.ch>
Thu, 5 Dec 2019 12:07:44 +0000 (13:07 +0100)
committerGrégory Burri <gregory.burri@matisa.ch>
Thu, 5 Dec 2019 12:07:44 +0000 (13:07 +0100)
src/day03.rs
src/main.rs

index a35ce3f..808f6f9 100644 (file)
@@ -1,37 +1,56 @@
 use std::iter::Iterator;\r
+use std::iter::FromIterator;\r
 use std::collections::HashSet;\r
+use std::collections::HashMap;\r
 \r
 pub fn split_movements(movements: &str) -> Vec<&str> {\r
     movements.split(',').collect()\r
 }\r
 \r
-pub fn manhattan_distance_from_cross_to_port(wire1: &[&str], wire2: &[&str]) -> i32 {\r
-    fn positions(wire: &[&str]) -> HashSet<(i32, i32)> {\r
-        let (mut x, mut y) = (0, 0);\r
-        let mut pos = HashSet::<(i32, i32)>::new();\r
-        for mov in wire {\r
-            let distance = mov[1..].parse::<i32>().unwrap();\r
-            match mov.chars().nth(0).unwrap() {\r
-                'U'      => { for y2 in y+1 ..= y + distance { pos.insert((x, y2)); } y += distance },\r
-                'D'      => { for y2 in y - distance .. y    { pos.insert((x, y2)); } y -= distance },\r
-                'R'      => { for x2 in x+1 ..= x + distance { pos.insert((x2, y)); } x += distance },\r
-                'L' | _  => { for x2 in x - distance .. x    { pos.insert((x2, y)); } x -= distance },\r
-            }\r
+fn positions(wire: &[&str]) -> Vec<(i32, i32)> {\r
+    let (mut x, mut y) = (0, 0);\r
+    let mut pos = Vec::<(i32, i32)>::new();\r
+    for mov in wire {\r
+        let distance = mov[1..].parse::<i32>().unwrap();\r
+        match mov.chars().nth(0).unwrap() {\r
+            'U'      => { for y2 in  y+1 ..= y + distance     { pos.push((x, y2)); } y += distance },\r
+            'D'      => { for y2 in (y - distance .. y).rev() { pos.push((x, y2)); } y -= distance },\r
+            'R'      => { for x2 in  x+1 ..= x + distance     { pos.push((x2, y)); } x += distance },\r
+            'L' | _  => { for x2 in (x - distance .. x).rev() { pos.push((x2, y)); } x -= distance },\r
         }\r
-        pos\r
     }\r
+    pos\r
+}\r
 \r
-    let (positions_wire1, positions_wire2) = (positions(wire1), positions(wire2));\r
+pub fn manhattan_distance_from_cross_to_port(wire1: &[&str], wire2: &[&str]) -> i32 {\r
+    let positions_wire1: HashSet<(i32, i32)> = HashSet::from_iter(positions(wire1));\r
+    let positions_wire2: HashSet<(i32, i32)> = HashSet::from_iter(positions(wire2));\r
     let cross: HashSet<_> = positions_wire1.intersection(&positions_wire2).collect();\r
     cross.iter().map(|(x, y)| x.abs() + y.abs()).min().unwrap()\r
 }\r
 \r
+pub fn first_cross_sum_of_lengths(wire1: &[&str], wire2: &[&str]) -> usize {\r
+    let positions_wire1 = positions(wire1);\r
+    let positions_wire1_indexed: HashMap<&(i32, i32), usize> = HashMap::from_iter(positions_wire1.iter().enumerate().map(|(i, pos)| (pos, i)).rev());\r
+\r
+    positions(wire2)\r
+        .iter().enumerate().filter_map(\r
+            |(j, pos2)| {\r
+                if let Some (i) = positions_wire1_indexed.get(pos2) {\r
+                    Some (j + i + 2)\r
+                } else {\r
+                    None\r
+                }\r
+            }\r
+        ).min().unwrap()\r
+}\r
+\r
 #[cfg(test)]\r
 mod tests {\r
     use super::*;\r
 \r
     #[test]\r
-    fn simple_cases() {\r
+    fn part1() {\r
         assert_eq!(\r
             manhattan_distance_from_cross_to_port(\r
                 &split_movements("R8,U5,L5,D3"),\r
@@ -56,4 +75,31 @@ mod tests {
             135\r
         );\r
     }\r
+\r
+    #[test]\r
+    fn part2() {\r
+        assert_eq!(\r
+            first_cross_sum_of_lengths(\r
+                &split_movements("R8,U5,L5,D3"),\r
+                &split_movements("U7,R6,D4,L5")\r
+            ),\r
+            30\r
+        );\r
+\r
+        assert_eq!(\r
+            first_cross_sum_of_lengths(\r
+                &split_movements("R75,D30,R83,U83,L12,D49,R71,U7,L72"),\r
+                &split_movements("U62,R66,U55,R34,D71,R55,D58,R83")\r
+            ),\r
+            610\r
+        );\r
+\r
+        assert_eq!(\r
+            first_cross_sum_of_lengths(\r
+                &split_movements("R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51"),\r
+                &split_movements("U98,R91,D20,R16,D67,R40,U7,R15,U6,R7")\r
+            ),\r
+            410\r
+        );\r
+    }\r
 }
\ No newline at end of file
index eff33ed..b508728 100644 (file)
@@ -21,8 +21,9 @@ fn day03() -> String {
     let file_content = fs::read_to_string("data/day03.input").unwrap();
     let movements: Vec<&str> = file_content.lines().collect();
     format!(
-        "part1: {}",
-        day03::manhattan_distance_from_cross_to_port(&day03::split_movements(&movements[0]), &day03::split_movements(&movements[1]))
+        "part1: {}, part2: {}",
+        day03::manhattan_distance_from_cross_to_port(&day03::split_movements(&movements[0]), &day03::split_movements(&movements[1])),
+        day03::first_cross_sum_of_lengths(&day03::split_movements(&movements[0]), &day03::split_movements(&movements[1]))
     )
 }