Day 10 part 2
This commit is contained in:
parent
c8d4d12648
commit
cb2d876e94
1 changed files with 120 additions and 22 deletions
142
src/bin/day10.rs
142
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<usize> {
|
|||
|
||||
// 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue