summaryrefslogtreecommitdiffstats
path: root/src/bin/2023/day10.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/2023/day10.rs')
-rw-r--r--src/bin/2023/day10.rs95
1 files changed, 77 insertions, 18 deletions
diff --git a/src/bin/2023/day10.rs b/src/bin/2023/day10.rs
index ef055e5..07e9741 100644
--- a/src/bin/2023/day10.rs
+++ b/src/bin/2023/day10.rs
@@ -68,21 +68,7 @@ impl Tile {
}
}
-pub fn parse(fh: File) -> Result<Grid<Tile>> {
- Ok(parse::grid(parse::raw_lines(fh), |c, _, _| match c {
- b'.' => Tile::Floor,
- b'S' => Tile::Start,
- b'|' => Tile::UpDown,
- b'-' => Tile::LeftRight,
- b'L' => Tile::UpRight,
- b'J' => Tile::UpLeft,
- b'F' => Tile::DownRight,
- b'7' => Tile::DownLeft,
- _ => panic!("bad tile {c}"),
- }))
-}
-
-pub fn part1(map: Grid<Tile>) -> Result<i64> {
+fn find_loop(map: &Grid<Tile>) -> (Vec<(Row, Col)>, Tile) {
let mut cur = map
.indexed_cells()
.find_map(|(pos, tile)| {
@@ -111,11 +97,84 @@ pub fn part1(map: Grid<Tile>) -> Result<i64> {
}
}
}
- Ok(i64::try_from(pipe_loop.len() - 1).unwrap() / 2)
+ pipe_loop.pop();
+ let start_tile = match (
+ pipe_loop[0].0.cmp(&pipe_loop[1].0),
+ pipe_loop[0].1.cmp(&pipe_loop[1].1),
+ pipe_loop[0].0.cmp(&pipe_loop[pipe_loop.len() - 1].0),
+ pipe_loop[0].1.cmp(&pipe_loop[pipe_loop.len() - 1].1),
+ ) {
+ (Ordering::Less, _, Ordering::Greater, _)
+ | (Ordering::Greater, _, Ordering::Less, _) => Tile::UpDown,
+ (_, Ordering::Less, _, Ordering::Greater)
+ | (_, Ordering::Greater, _, Ordering::Less) => Tile::LeftRight,
+ (Ordering::Greater, _, _, Ordering::Greater)
+ | (_, Ordering::Greater, Ordering::Greater, _) => Tile::UpLeft,
+ (Ordering::Greater, _, _, Ordering::Less)
+ | (_, Ordering::Less, Ordering::Greater, _) => Tile::UpRight,
+ (Ordering::Less, _, _, Ordering::Greater)
+ | (_, Ordering::Greater, Ordering::Less, _) => Tile::DownLeft,
+ (Ordering::Less, _, _, Ordering::Less)
+ | (_, Ordering::Less, Ordering::Less, _) => Tile::DownRight,
+ _ => unreachable!(),
+ };
+ (pipe_loop, start_tile)
}
-pub fn part2(_: Grid<Tile>) -> Result<i64> {
- todo!()
+pub fn parse(fh: File) -> Result<Grid<Tile>> {
+ Ok(parse::grid(parse::raw_lines(fh), |c, _, _| match c {
+ b'.' => Tile::Floor,
+ b'S' => Tile::Start,
+ b'|' => Tile::UpDown,
+ b'-' => Tile::LeftRight,
+ b'L' => Tile::UpRight,
+ b'J' => Tile::UpLeft,
+ b'F' => Tile::DownRight,
+ b'7' => Tile::DownLeft,
+ _ => panic!("bad tile {c}"),
+ }))
+}
+
+pub fn part1(map: Grid<Tile>) -> Result<i64> {
+ Ok(i64::try_from(find_loop(&map).0.len()).unwrap() / 2)
+}
+
+pub fn part2(map: Grid<Tile>) -> Result<i64> {
+ let (pipe_loop, start_tile) = find_loop(&map);
+ let pipe_loop: HashSet<_> = pipe_loop.into_iter().collect();
+ let mut total = 0;
+ for ((row, col), tile) in map.indexed_cells() {
+ if pipe_loop.contains(&(row, col)) {
+ continue;
+ }
+ let mut count = 0;
+ for offset in 0..=(row.0.min(col.0)) {
+ let check_row = row - offset;
+ let check_col = col - offset;
+ if !pipe_loop.contains(&(check_row, check_col)) {
+ continue;
+ }
+ let check_tile = map[check_row][check_col];
+ let check_tile = if matches!(check_tile, Tile::Start) {
+ start_tile
+ } else {
+ check_tile
+ };
+ if matches!(
+ check_tile,
+ Tile::UpDown
+ | Tile::LeftRight
+ | Tile::UpLeft
+ | Tile::DownRight
+ ) {
+ count += 1;
+ }
+ }
+ if count % 2 == 1 {
+ total += 1;
+ }
+ }
+ Ok(total)
}
#[test]