Skip to content

Commit 0614b3b

Browse files
committed
Document Year 2022 Day 18
1 parent 4f164fa commit 0614b3b

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

src/year2022/day18.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
1+
//! # Boiling Boulders
2+
//!
3+
//! The lava droplet is a fixed size so we can use a one dimensional fixed size array to store the
4+
//! cube data for speed.
5+
//!
6+
//! For part two we use the [flood fill](https://en.wikipedia.org/wiki/Flood_fill) algorithm
7+
//! starting from any corner to fill the outside space with water. We then use the same exposed
8+
//! edge counting approach as part one, but only considering faces that touch a water drop.
19
use crate::util::iter::*;
210
use crate::util::parse::*;
311

412
const SIZE: usize = 22;
513

614
pub fn parse(input: &str) -> Vec<u32> {
715
let mut cube = vec![0; SIZE * SIZE * SIZE];
16+
// Leave a 1 layer boundary around the outside for the part two flood fill
17+
// and also so that we don't have to use boundary checks when checking neighbors.
818
input.iter_unsigned().chunk::<3>().for_each(|[x, y, z]: [usize; 3]| {
919
cube[(x + 1) * SIZE * SIZE + (y + 1) * SIZE + (z + 1)] = 1;
1020
});
1121
cube
1222
}
1323

1424
pub fn part1(input: &[u32]) -> u32 {
25+
// The exposed surface area is the 6 faces of the cubes minus any neighbors.
1526
count(input, |x| 6 - x)
1627
}
1728

1829
pub fn part2(input: &[u32]) -> u32 {
1930
let mut cube = input.to_vec();
31+
// "Paint" the outside of the cube with water drops.
2032
flood_fill(&mut cube, 0);
33+
// Divide by 8 so that we only count water cubes.
2134
count(&cube, |x| x >> 3)
2235
}
2336

@@ -26,6 +39,7 @@ fn count(cube: &[u32], adjust: fn(u32) -> u32) -> u32 {
2639

2740
for i in 0..cube.len() {
2841
if cube[i] == 1 {
42+
// No need for boundary checks as all cubes are at least 1 away from the edge.
2943
total += adjust(
3044
cube[i - 1]
3145
+ cube[i + 1]
@@ -42,7 +56,9 @@ fn count(cube: &[u32], adjust: fn(u32) -> u32) -> u32 {
4256

4357
fn flood_fill(cube: &mut [u32], i: usize) {
4458
if cube.get(i) == Some(&0) {
59+
// Use 8 as the nearest power of two greater than 6.
4560
cube[i] = 8;
61+
// We may wrap around to an opposite edge but that will also be water.
4662
flood_fill(cube, i.saturating_sub(1));
4763
flood_fill(cube, i + 1);
4864
flood_fill(cube, i.saturating_sub(SIZE));

0 commit comments

Comments
 (0)