From cb2d876e943fdd4148a3aade93e7f611c42e67c7 Mon Sep 17 00:00:00 2001 From: "RingOfStorms (Joshua Bell)" Date: Sun, 10 Dec 2023 23:13:51 -0600 Subject: [PATCH] Day 10 part 2 --- src/bin/day10.rs | 142 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 120 insertions(+), 22 deletions(-) diff --git a/src/bin/day10.rs b/src/bin/day10.rs index 8053867..ac7b28d 100644 --- a/src/bin/day10.rs +++ b/src/bin/day10.rs @@ -2,7 +2,7 @@ use aoc23::prelude::*; use derive_builder::Builder; use itertools::Itertools; use rayon::prelude::*; -use std::{str::FromStr, time::Instant}; +use std::{collections::HashSet, str::FromStr, time::Instant}; static DAY: u8 = 10; @@ -18,12 +18,26 @@ enum PipeDirection { Ground, } +impl PipeDirection { + fn is_north(&self) -> bool { + matches!(self, PipeDirection::NorthEast | PipeDirection::NorthWest) + } +} + #[derive(Debug, Clone)] struct Pipe { position: (usize, usize), direction: PipeDirection, } +impl Eq for Pipe {} + +impl PartialEq for Pipe { + fn eq(&self, other: &Self) -> bool { + self.position == other.position + } +} + impl Pipe { fn for_char(c: char, position: (usize, usize)) -> Self { match c { @@ -230,25 +244,85 @@ fn part2(input: String) -> Result { // algo let a_start = Instant::now(); - let mut path = vec![]; + let mut path = vec![ + &pipes.start, + pipes + .start + .connects_to() + .into_iter() + .next() + .map(|pos| pipes.get(&pos)) + .unwrap(), + ]; loop { - // reached end - if paths[0].1.position.0 == paths[1].1.position.0 - && paths[0].1.position.1 == paths[1].1.position.1 - { - break; - } - answer += 1; - for path in paths.iter_mut() { - let next = path - .1 - .connects_to() - .into_iter() - .filter(|pipe| pipe.0 != path.0.position.0 || pipe.1 != path.0.position.1) - .next() - .map(|pos| pipes.get(&pos)) - .unwrap(); - *path = (path.1, next); + let previous = path.get(path.len() - 2).unwrap(); + let next = path + .last() + .unwrap() + .connects_to() + .into_iter() + .filter(|pipe| pipe.0 != previous.position.0 || pipe.1 != previous.position.1) + .next() + .map(|pos| pipes.get(&pos)) + .unwrap(); + match next.direction { + PipeDirection::Start => { + break; + } + _ => { + path.push(next); + } + }; + } + let mut answer = 0; + for (ri, row) in pipes.grid.iter().enumerate() { + for (idx, pipe) in row.iter().enumerate() { + if !path.contains(&pipe) { + // println!("Pipe check, {}, {}", ri, idx); + let (intersections, _) = row + .iter() + // Start at current non path pipe we are checking + .skip(idx + 1) + // Add fake pipe at the end so we can match on pipes on the right edge of the Grid + // .chain(std::iter::once(&Pipe { position: (0, 0), direction: + // PipeDirection::Ground, })) + .fold( + (0, None), + |(i_count, intersecting_dir): (usize, Option<&PipeDirection>), pipe| { + if path.contains(&pipe) { + return match pipe.direction { + PipeDirection::Vertical => (i_count + 1, None), + PipeDirection::NorthWest + | PipeDirection::NorthEast + | PipeDirection::SouthEast + | PipeDirection::SouthWest => match intersecting_dir { + Some(last_direction) => { + match ( + last_direction.is_north(), + pipe.direction.is_north(), + ) { + (true, true) | (false, false) => (i_count, None), + (true, false) | (false, true) => { + (i_count + 1, None) + } + } + } + None => (i_count, Some(&pipe.direction)), + }, + PipeDirection::Horizontal => (i_count, intersecting_dir), + _ => (i_count, None), + }; + } + return (i_count, None); + }, + ); + + // println!( "\t\tPipe check, {}, {} intersections: {} | {}", ri, idx, + // intersections, (intersections > 0 && intersections % 2 == 1) ); + if intersections > 0 && intersections % 2 == 1 { + answer += 1; + } + } } } let algo_time = a_start.elapsed(); @@ -266,8 +340,7 @@ async fn main() -> Result<()> { println!("====="); let input = utils::aoc::get_puzzle_input(DAY).await?; part1(input.clone())?; - - // part2(input.clone())?; + part2(input.clone())?; Ok(()) } @@ -292,7 +365,27 @@ LJ..." } #[test] - fn test_part_2() -> Result<()> { + fn test_part_2_small() -> Result<()> { + assert_eq!( + part2( + "........... +.S-------7. +.|F-----7|. +.||.....||. +.||.....||. +.|L-7.F-J|. +.|..|.|..|. +.L--J.L--J. +..........." + .to_owned(), + )?, + 4 + ); + Ok(()) + } + + #[test] + fn test_part_2_med() -> Result<()> { assert_eq!( part2( ".F----7F7F7F7F-7.... @@ -309,6 +402,11 @@ L--J.L7...LJS7F-7L7. )?, 8 ); + Ok(()) + } + + #[test] + fn test_part_2_hard() -> Result<()> { assert_eq!( part2( "FF7FSF7F7F7F7F7F---7