diff --git a/2023/src/day10.rs b/2023/src/day10.rs index faabb87..99ab529 100644 --- a/2023/src/day10.rs +++ b/2023/src/day10.rs @@ -22,14 +22,15 @@ fn get_connections(c: u8) -> u8 { } } -pub fn part1(input: &[u8]) -> anyhow::Result { - let map = Grid::new(input)?; +fn find_cycle(map: &Grid<'_>) -> anyhow::Result<(usize, bool, IndexSet)> { let (start_x, start_y) = map.find(b'S').context("Couldn't find starting point")?; let mut visited = IndexSet::with_capacity(map.width() * map.height()); let mut todo = VecDeque::new(); visited.insert(start_y * map.width() + start_x); + let mut start_up = false; + if start_x > 0 && (get_connections(map[start_y][start_x - 1]) & RIGHT) != 0 { todo.push_back((1, (start_x - 1, start_y))); visited.insert(start_y * map.width() + start_x - 1); @@ -43,6 +44,7 @@ pub fn part1(input: &[u8]) -> anyhow::Result { if start_y > 0 && (get_connections(map[start_y - 1][start_x]) & DOWN) != 0 { todo.push_back((1, (start_x, start_y - 1))); visited.insert((start_y - 1) * map.width() + start_x); + start_up = true; } if start_y + 1 < map.height() && (get_connections(map[start_y + 1][start_x]) & DOWN) != 0 { @@ -80,21 +82,63 @@ pub fn part1(input: &[u8]) -> anyhow::Result { } } - Ok(max_dist.to_string()) + Ok((max_dist, start_up, visited)) } -pub fn part2(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +pub fn part1(input: &[u8]) -> anyhow::Result { + let map = Grid::new(input)?; + + find_cycle(&map).map(|(max_dist, _, _)| max_dist.to_string()) +} + +pub fn part2(input: &[u8]) -> anyhow::Result { + let map = Grid::new(input)?; + let (_, s_up, visited) = find_cycle(&map)?; + + let mut inside = 0; + + for (y, row) in map.rows().enumerate() { + let y_offset = y * map.width(); + let mut pipes = 0; + + for (x, &c) in row.iter().enumerate() { + if visited.contains(y_offset + x) { + let is_up = match c { + b'|' | b'J' | b'L' => true, + b'S' => s_up, + _ => false, + }; + + if is_up { + pipes += 1; + } + } else { + inside += pipes % 2; + } + } + } + + Ok(inside.to_string()) } #[cfg(test)] mod tests { use super::*; - const SAMPLE: &[u8] = include_bytes!("samples/10.txt"); + const SAMPLE: &[u8] = include_bytes!("samples/10.1.txt"); + const SAMPLE2: &[u8] = include_bytes!("samples/10.2.txt"); + const SAMPLE3: &[u8] = include_bytes!("samples/10.3.txt"); + const SAMPLE4: &[u8] = include_bytes!("samples/10.4.txt"); #[test] fn sample_part1() { assert_eq!("8", part1(SAMPLE).unwrap()); } + + #[test] + fn sample_part2() { + assert_eq!("4", part2(SAMPLE2).unwrap()); + assert_eq!("8", part2(SAMPLE3).unwrap()); + assert_eq!("10", part2(SAMPLE4).unwrap()); + } } diff --git a/2023/src/samples/10.txt b/2023/src/samples/10.1.txt similarity index 100% rename from 2023/src/samples/10.txt rename to 2023/src/samples/10.1.txt diff --git a/2023/src/samples/10.2.txt b/2023/src/samples/10.2.txt new file mode 100644 index 0000000..bd9cdf5 --- /dev/null +++ b/2023/src/samples/10.2.txt @@ -0,0 +1,9 @@ +........... +.S-------7. +.|F-----7|. +.||.....||. +.||.....||. +.|L-7.F-J|. +.|..|.|..|. +.L--J.L--J. +........... diff --git a/2023/src/samples/10.3.txt b/2023/src/samples/10.3.txt new file mode 100644 index 0000000..adaae96 --- /dev/null +++ b/2023/src/samples/10.3.txt @@ -0,0 +1,10 @@ +.F----7F7F7F7F-7.... +.|F--7||||||||FJ.... +.||.FJ||||||||L7.... +FJL7L7LJLJ||LJ.L-7.. +L--J.L7...LJS7F-7L7. +....F-J..F7FJ|L7L7L7 +....L7.F7||L7|.L7L7| +.....|FJLJ|FJ|F7|.LJ +....FJL-7.||.||||... +....L---J.LJ.LJLJ... diff --git a/2023/src/samples/10.4.txt b/2023/src/samples/10.4.txt new file mode 100644 index 0000000..8f950ae --- /dev/null +++ b/2023/src/samples/10.4.txt @@ -0,0 +1,10 @@ +FF7FSF7F7F7F7F7F---7 +L|LJ||||||||||||F--J +FL-7LJLJ||||||LJL-77 +F--JF--7||LJLJ7F7FJ- +L---JF-JLJ.||-FJLJJ7 +|F|F-JF---7F7-L7L|7| +|FFJF7L7F-JF7|JL---7 +7-L-JL7||F7|L7F-7F7| +L.L7LFJ|||||FJL7||LJ +L7JLJL-JLJLJL--JLJ.L