Browse Source

Completed day 13 part 2

Tyler Hallada 4 years ago
parent
commit
3872264523
2 changed files with 51 additions and 11 deletions
  1. 49 11
      src/day13.rs
  2. 2 0
      src/main.rs

+ 49 - 11
src/day13.rs

@@ -48,6 +48,12 @@ struct Track {
48 48
     intersections: HashSet<Vector>,
49 49
 }
50 50
 
51
+#[derive(Debug, PartialEq)]
52
+struct Collision {
53
+    position: Vector,
54
+    cart_indices: (usize, usize),
55
+}
56
+
51 57
 impl FromStr for Track {
52 58
     type Err = Box<Error>;
53 59
 
@@ -87,7 +93,7 @@ impl FromStr for Track {
87 93
                     },
88 94
                     (col_index, '/') => match bottom_start {
89 95
                         Some(start) => match incomplete_circuits.remove(&(start, col_index)) {
90
-                            Some(top_row) => {
96
+                            Some(_) => {
91 97
                                 turns.insert(
92 98
                                     Vector {
93 99
                                         x: col_index,
@@ -210,13 +216,18 @@ impl Cart {
210 216
 }
211 217
 
212 218
 impl Track {
213
-    fn run_tick(&mut self) -> Option<Vector> {
214
-        let mut cart_positions: HashSet<Vector> = HashSet::new();
215
-        for cart in self.carts.iter() {
216
-            cart_positions.insert(cart.position);
219
+    fn run_tick(&mut self, find_final_cart: bool) -> Option<Vector> {
220
+        let mut collided_cart_indices = HashSet::new();
221
+        let mut cart_positions: HashMap<Vector, usize> = HashMap::new();
222
+        for (index, cart) in self.carts.iter().enumerate() {
223
+            cart_positions.insert(cart.position, index);
217 224
         }
218 225
 
219
-        for cart in self.carts.iter_mut() {
226
+        for (index, cart) in self.carts.iter_mut().enumerate() {
227
+            if collided_cart_indices.contains(&index) {
228
+                continue;
229
+            }
230
+
220 231
             let Vector { x, y } = cart.position;
221 232
             cart_positions.remove(&cart.position);
222 233
             cart.position = match cart.direction {
@@ -235,12 +246,27 @@ impl Track {
235 246
                 cart.next_turn = (cart.next_turn + 1) % INTER_SEQ.len() as u8;
236 247
             }
237 248
 
238
-            if cart_positions.contains(&cart.position) {
239
-                return Some(cart.position);
249
+            if let Some(colliding_cart) = cart_positions.get(&cart.position) {
250
+                if find_final_cart {
251
+                    collided_cart_indices.insert(index);
252
+                    collided_cart_indices.insert(*colliding_cart);
253
+                    cart_positions.remove(&cart.position);
254
+                    continue;
255
+                } else {
256
+                    return Some(cart.position);
257
+                }
240 258
             }
241 259
 
242
-            cart_positions.insert(cart.position);
260
+            cart_positions.insert(cart.position, index);
243 261
         }
262
+
263
+        self.carts = self
264
+            .carts
265
+            .drain(..)
266
+            .enumerate()
267
+            .filter(|(i, _)| !collided_cart_indices.contains(i))
268
+            .map(|(_, cart)| cart)
269
+            .collect();
244 270
         self.carts.sort_unstable();
245 271
         None
246 272
     }
@@ -248,10 +274,17 @@ impl Track {
248 274
     fn find_first_collision(&mut self) -> Vector {
249 275
         let mut collision: Option<Vector> = None;
250 276
         while collision.is_none() {
251
-            collision = self.run_tick();
277
+            collision = self.run_tick(false);
252 278
         }
253 279
         collision.unwrap()
254 280
     }
281
+
282
+    fn find_last_cart(&mut self) -> &Cart {
283
+        while self.carts.len() != 1 {
284
+            self.run_tick(true);
285
+        }
286
+        &self.carts[0]
287
+    }
255 288
 }
256 289
 
257 290
 fn read_track(filename: &str) -> Result<Track> {
@@ -264,6 +297,11 @@ pub fn solve_part1() -> Result<Vector> {
264 297
     Ok(track.find_first_collision())
265 298
 }
266 299
 
300
+pub fn solve_part2() -> Result<Vector> {
301
+    let mut track = read_track(INPUT)?;
302
+    Ok(track.find_last_cart().position)
303
+}
304
+
267 305
 #[cfg(test)]
268 306
 mod tests {
269 307
     use super::*;
@@ -326,7 +364,7 @@ mod tests {
326 364
         track_after.carts[1].direction = Direction::East;
327 365
         track_after.carts[1].next_turn = 1;
328 366
         let mut track = test_track();
329
-        track.run_tick();
367
+        track.run_tick(false);
330 368
         assert_eq!(track, track_after);
331 369
     }
332 370
 

+ 2 - 0
src/main.rs

@@ -60,4 +60,6 @@ fn main() {
60 60
     println!("Day 13");
61 61
     let part1 = day13::solve_part1().unwrap();
62 62
     println!("{},{}", part1.x, part1.y);
63
+    let part2 = day13::solve_part2().unwrap();
64
+    println!("{},{}", part2.x, part2.y);
63 65
 }