My (attempted) solutions to the 2022 Advent of Code
Log | Files | Refs | README

```commit 314b8485bf5fd474f161cf3a034319547a190c22
parent 8c90478f7cbf04c3583a5dda6fc4020b069765a4
Date:   Mon,  9 Jan 2023 15:48:48 -0800

Solution to day 18, part 2.

Diffstat:
Msrc/day_18.jl | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
```
```1 file changed, 54 insertions(+), 5 deletions(-)
diff --git a/src/day_18.jl b/src/day_18.jl
@@ -34,20 +34,29 @@ function parse_input(input::Vector{<:AbstractString})
Dict(Tuple(parse.(Int, split(x, ","))) => 6 for x in input)
end

-function neighbors(cube::Cube, cubes::Set{Cube})
+"""
+Return the six-connected neighborhood of the given cube.
+"""
+function neighbors(cube::Cube)
cubeneighbors = Set{Cube}()
for ax = 1:3, Δ = (-1, 1)
-        cube₂ = Tuple(i==ax ? cube[i]+Δ : cube[i] for i in eachindex(cube))
-        cube₂ ∈ cubes && push!(cubeneighbors, cube₂)
+        push!(cubeneighbors,
+              Tuple(i==ax ? cube[i]+Δ : cube[i] for i = eachindex(cube)))
end
cubeneighbors
end

+"""
+Loop through the cubes to find the droplet surface area.
+
+This updates the dictionary of (exposed) surface area values and also returns
+it (for convenience).
+"""
function updatecubes!(cubemap::Dict{Cube, Int})
cubes = Set(keys(cubemap))
while !isempty(cubes)
cube = pop!(cubes)
-        for neighbor in neighbors(cube, cubes)
+        for neighbor in neighbors(cube) ∩ cubes
cubemap[cube] -= 1
cubemap[neighbor] -= 1
end
@@ -61,7 +70,47 @@ end
@assert part_1(example) == 64
@info part_1(input)

+"""
+Recursively calculate the surface area of the lava droplet.
+
+Pretty different than the part 1 approach--where we started in the droplet and
+worked outward, this starts in the steam and works toward the droplet. This
+function returns the surface area touched by the given cube and all heretofore
+unexplored cubes.
+"""
+function lavasurface!(steamarea::Dict{Cube, Int},
+                      lavacubes::AbstractSet{Cube},
+                      cube::Cube,
+                      xrange::Tuple{Int, Int} = extrema(x -> x[1], lavacubes),
+                      yrange::Tuple{Int, Int} = extrema(x -> x[2], lavacubes),
+                      zrange::Tuple{Int, Int} = extrema(x -> x[3], lavacubes))
+    @assert cube ∉ lavacubes
+    @assert cube ∉ keys(steamarea)
+    steamarea[cube] = 0
+    for neighbor = neighbors(cube)
+        if neighbor ∈ lavacubes
+            steamarea[cube] += 1
+        elseif neighbor ∉ keys(steamarea) &&
+               xrange[1]-1 <= neighbor[1] <= xrange[2]+1 &&
+               yrange[1]-1 <= neighbor[2] <= yrange[2]+1 &&
+               zrange[1]-1 <= neighbor[3] <= zrange[2]+1
+            steamarea[cube] += lavasurface!(steamarea, lavacubes, neighbor,
+                                            xrange, yrange, zrange)
+        end
+    end
+    steamarea[cube]
+end
+
function part_2(input)
-    nothing
+    steamarea = Dict{Cube, Int}()
+    lavacubes = keys(parse_input(input))
+
+    xrange = extrema(x -> x[1], lavacubes)
+    yrange = extrema(x -> x[2], lavacubes)
+    zrange = extrema(x -> x[3], lavacubes)
+
+    lavasurface!(steamarea, lavacubes, (xrange[1]-1, yrange[1]-1, zrange[1]-1),
+                 xrange, yrange, zrange)
end
+@assert part_2(example) == 58
@info part_2(input)
```