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

day_18.jl (3369B)


      1 #!/usr/bin/env julia
      2 # https://adventofcode.com/2022/day/18
      3 using AdventOfCode
      4 
      5 # I've been avoiding list comprehensions because, idk, I'm a nerd who tries to
      6 # use `map`. But I remembered how expressive comprehensions can be, so it was
      7 # nice to use them here!
      8 
      9 example = readlines(IOBuffer("""
     10     2,2,2
     11     1,2,2
     12     3,2,2
     13     2,1,2
     14     2,3,2
     15     2,2,1
     16     2,2,3
     17     2,2,4
     18     2,2,6
     19     1,2,5
     20     3,2,5
     21     2,1,5
     22     2,3,5"""))
     23 input = readlines("data/day_18.txt")
     24 
     25 Cube = Tuple{Int, Int, Int}
     26 
     27 """
     28 Read the puzzle input and return a map from cubes to exposed faces.
     29 
     30 We initialize each cube with six exposed faces and update them on a subsequent
     31 step.
     32 """
     33 function parse_input(input::Vector{<:AbstractString})
     34     Dict(Tuple(parse.(Int, split(x, ","))) => 6 for x in input)
     35 end
     36 
     37 """
     38 Return the six-connected neighborhood of the given cube.
     39 """
     40 function neighbors(cube::Cube)
     41     cubeneighbors = Set{Cube}()
     42     for ax = 1:3, Δ = (-1, 1)
     43         push!(cubeneighbors,
     44               Tuple(i==ax ? cube[i]+Δ : cube[i] for i = eachindex(cube)))
     45     end
     46     cubeneighbors
     47 end
     48 
     49 """
     50 Loop through the cubes to find the droplet surface area.
     51 
     52 This updates the dictionary of (exposed) surface area values and also returns
     53 it (for convenience).
     54 """
     55 function updatecubes!(cubemap::Dict{Cube, Int})
     56     cubes = Set(keys(cubemap))
     57     while !isempty(cubes)
     58         cube = pop!(cubes)
     59         for neighbor in neighbors(cube) ∩ cubes
     60             cubemap[cube] -= 1
     61             cubemap[neighbor] -= 1
     62         end
     63     end
     64     cubemap
     65 end
     66 
     67 function part_1(input)
     68     input |> parse_input |> updatecubes! |> values |> sum
     69 end
     70 @assert part_1(example) == 64
     71 @info part_1(input)
     72 
     73 """
     74 Recursively calculate the surface area of the lava droplet.
     75 
     76 Pretty different than the part 1 approach--where we started in the droplet and
     77 worked outward, this starts in the steam and works toward the droplet. This
     78 function returns the surface area touched by the given cube and all heretofore
     79 unexplored cubes.
     80 """
     81 function lavasurface!(steamarea::Dict{Cube, Int},
     82                       lavacubes::AbstractSet{Cube},
     83                       cube::Cube,
     84                       xrange::Tuple{Int, Int} = extrema(x -> x[1], lavacubes),
     85                       yrange::Tuple{Int, Int} = extrema(x -> x[2], lavacubes),
     86                       zrange::Tuple{Int, Int} = extrema(x -> x[3], lavacubes))
     87     @assert cube ∉ lavacubes
     88     @assert cube ∉ keys(steamarea)
     89     steamarea[cube] = 0
     90     for neighbor = neighbors(cube)
     91         if neighbor ∈ lavacubes
     92             steamarea[cube] += 1
     93         elseif neighbor ∉ keys(steamarea) &&
     94                xrange[1]-1 <= neighbor[1] <= xrange[2]+1 &&
     95                yrange[1]-1 <= neighbor[2] <= yrange[2]+1 &&
     96                zrange[1]-1 <= neighbor[3] <= zrange[2]+1
     97             steamarea[cube] += lavasurface!(steamarea, lavacubes, neighbor,
     98                                             xrange, yrange, zrange)
     99         end
    100     end
    101     steamarea[cube]
    102 end
    103 
    104 function part_2(input)
    105     steamarea = Dict{Cube, Int}()
    106     lavacubes = keys(parse_input(input))
    107 
    108     xrange = extrema(x -> x[1], lavacubes)
    109     yrange = extrema(x -> x[2], lavacubes)
    110     zrange = extrema(x -> x[3], lavacubes)
    111 
    112     lavasurface!(steamarea, lavacubes, (xrange[1]-1, yrange[1]-1, zrange[1]-1),
    113                  xrange, yrange, zrange)
    114 end
    115 @assert part_2(example) == 58
    116 @info part_2(input)