advent_of_code_2022

My (attempted) solutions to the 2022 Advent of Code
git clone https://git.eamoncaddigan.net/advent_of_code_2022.git
Log | Files | Refs | README

commit 314b8485bf5fd474f161cf3a034319547a190c22
parent 8c90478f7cbf04c3583a5dda6fc4020b069765a4
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
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)