Day 10 part 2

This commit is contained in:
RingOfStorms (Joshua Bell) 2023-12-10 23:13:51 -06:00
parent c8d4d12648
commit cb2d876e94

View file

@ -2,7 +2,7 @@ use aoc23::prelude::*;
use derive_builder::Builder; use derive_builder::Builder;
use itertools::Itertools; use itertools::Itertools;
use rayon::prelude::*; use rayon::prelude::*;
use std::{str::FromStr, time::Instant}; use std::{collections::HashSet, str::FromStr, time::Instant};
static DAY: u8 = 10; static DAY: u8 = 10;
@ -18,12 +18,26 @@ enum PipeDirection {
Ground, Ground,
} }
impl PipeDirection {
fn is_north(&self) -> bool {
matches!(self, PipeDirection::NorthEast | PipeDirection::NorthWest)
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Pipe { struct Pipe {
position: (usize, usize), position: (usize, usize),
direction: PipeDirection, direction: PipeDirection,
} }
impl Eq for Pipe {}
impl PartialEq for Pipe {
fn eq(&self, other: &Self) -> bool {
self.position == other.position
}
}
impl Pipe { impl Pipe {
fn for_char(c: char, position: (usize, usize)) -> Self { fn for_char(c: char, position: (usize, usize)) -> Self {
match c { match c {
@ -230,25 +244,85 @@ fn part2(input: String) -> Result<usize> {
// algo // algo
let a_start = Instant::now(); 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 { loop {
// reached end let previous = path.get(path.len() - 2).unwrap();
if paths[0].1.position.0 == paths[1].1.position.0 let next = path
&& paths[0].1.position.1 == paths[1].1.position.1 .last()
{ .unwrap()
break; .connects_to()
} .into_iter()
answer += 1; .filter(|pipe| pipe.0 != previous.position.0 || pipe.1 != previous.position.1)
for path in paths.iter_mut() { .next()
let next = path .map(|pos| pipes.get(&pos))
.1 .unwrap();
.connects_to() match next.direction {
.into_iter() PipeDirection::Start => {
.filter(|pipe| pipe.0 != path.0.position.0 || pipe.1 != path.0.position.1) break;
.next() }
.map(|pos| pipes.get(&pos)) _ => {
.unwrap(); path.push(next);
*path = (path.1, 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(); let algo_time = a_start.elapsed();
@ -266,8 +340,7 @@ async fn main() -> Result<()> {
println!("====="); println!("=====");
let input = utils::aoc::get_puzzle_input(DAY).await?; let input = utils::aoc::get_puzzle_input(DAY).await?;
part1(input.clone())?; part1(input.clone())?;
part2(input.clone())?;
// part2(input.clone())?;
Ok(()) Ok(())
} }
@ -292,7 +365,27 @@ LJ..."
} }
#[test] #[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!( assert_eq!(
part2( part2(
".F----7F7F7F7F-7.... ".F----7F7F7F7F-7....
@ -309,6 +402,11 @@ L--J.L7...LJS7F-7L7.
)?, )?,
8 8
); );
Ok(())
}
#[test]
fn test_part_2_hard() -> Result<()> {
assert_eq!( assert_eq!(
part2( part2(
"FF7FSF7F7F7F7F7F---7 "FF7FSF7F7F7F7F7F---7