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.
1
9
use crate :: util:: iter:: * ;
2
10
use crate :: util:: parse:: * ;
3
11
4
12
const SIZE : usize = 22 ;
5
13
6
14
pub fn parse ( input : & str ) -> Vec < u32 > {
7
15
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.
8
18
input. iter_unsigned ( ) . chunk :: < 3 > ( ) . for_each ( |[ x, y, z] : [ usize ; 3 ] | {
9
19
cube[ ( x + 1 ) * SIZE * SIZE + ( y + 1 ) * SIZE + ( z + 1 ) ] = 1 ;
10
20
} ) ;
11
21
cube
12
22
}
13
23
14
24
pub fn part1 ( input : & [ u32 ] ) -> u32 {
25
+ // The exposed surface area is the 6 faces of the cubes minus any neighbors.
15
26
count ( input, |x| 6 - x)
16
27
}
17
28
18
29
pub fn part2 ( input : & [ u32 ] ) -> u32 {
19
30
let mut cube = input. to_vec ( ) ;
31
+ // "Paint" the outside of the cube with water drops.
20
32
flood_fill ( & mut cube, 0 ) ;
33
+ // Divide by 8 so that we only count water cubes.
21
34
count ( & cube, |x| x >> 3 )
22
35
}
23
36
@@ -26,6 +39,7 @@ fn count(cube: &[u32], adjust: fn(u32) -> u32) -> u32 {
26
39
27
40
for i in 0 ..cube. len ( ) {
28
41
if cube[ i] == 1 {
42
+ // No need for boundary checks as all cubes are at least 1 away from the edge.
29
43
total += adjust (
30
44
cube[ i - 1 ]
31
45
+ cube[ i + 1 ]
@@ -42,7 +56,9 @@ fn count(cube: &[u32], adjust: fn(u32) -> u32) -> u32 {
42
56
43
57
fn flood_fill ( cube : & mut [ u32 ] , i : usize ) {
44
58
if cube. get ( i) == Some ( & 0 ) {
59
+ // Use 8 as the nearest power of two greater than 6.
45
60
cube[ i] = 8 ;
61
+ // We may wrap around to an opposite edge but that will also be water.
46
62
flood_fill ( cube, i. saturating_sub ( 1 ) ) ;
47
63
flood_fill ( cube, i + 1 ) ;
48
64
flood_fill ( cube, i. saturating_sub ( SIZE ) ) ;
0 commit comments