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

```commit 74fb77374becc1820d19220bf8d28378e8bff3ef
Date:   Wed, 14 Dec 2022 09:45:43 -0800

Solution to day 14, part 1.

Diffstat:
Asrc/day_14.jl | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
```1 file changed, 108 insertions(+), 0 deletions(-)
diff --git a/src/day_14.jl b/src/day_14.jl
@@ -0,0 +1,108 @@
+#!/usr/bin/env julia
+
+	498,4 -> 498,6 -> 496,6
+	503,4 -> 502,4 -> 502,9 -> 494,9"""))
+
+module Maps
+    # Let's see if we can solve this by just making a Set of filled blocks.
+    # Could be too slow or memory hungry, IDK.
+    struct MapState
+       filled_blocks::Set{Tuple{Int,Int}}
+       lowest_row::Int
+    end
+
+    function MapState(input::Vector{<:AbstractString})
+        filled_blocks = Set{Tuple{Int,Int}}()
+        lowest_row = -Inf
+        for path = input
+            lines = map(x -> parse.(Int, split(x, ",")), split(path, " -> "))
+            for i = 2:length(lines)
+                xline = range(minmax(lines[i-1], lines[i])...,
+                              step = 1)
+                yline = range(minmax(lines[i-1], lines[i])...,
+                              step = 1)
+                for x = xline, y = yline
+                    push!(filled_blocks, (x, y))
+                    lowest_row = max(lowest_row, y)
+                end
+            end
+        end
+        MapState(filled_blocks, lowest_row)
+    end
+
+    # I'm going to try to keep these function signatures implementation-neutral
+    # in case I need to change my approach. Ideally I can leave the basic
+    # sand-filling algorithm alone and only change the underlying
+    # datastructures and methods (if necessary).
+    """
+    Return true IFF sand at the given coordinate is destined to fall forever.
+    """
+    function isfallingforever(mapstate::MapState, coord::Tuple{Int,Int})
+        coord > mapstate.lowest_row
+    end
+
+    """
+    Return true IFF the given coordinate is filled with sand or stone.
+    """
+    function isfilled(mapstate::MapState, coord::Tuple{Int,Int})
+        coord in mapstate.filled_blocks
+    end
+
+    """
+    Fill the given block with sand.
+    """
+    function fillblock!(mapstate::MapState, coord::Tuple{Int,Int})
+        push!(mapstate.filled_blocks, coord)
+    end
+
+    """
+    Drop a block from (500, 0) until it comes to rest or falls forever.
+
+    Returns true if the block comes to rest and false if it falls forever.
+    """
+    function dropblock!(mapstate::MapState)
+        coord = (500, 0)
+        while !isfallingforever(mapstate, coord)
+            if !isfilled(mapstate, coord .+ (0, 1))
+                coord = coord .+ (0, 1)
+            elseif !isfilled(mapstate, coord .+ (-1, 1))
+                coord = coord .+ (-1, 1)
+            elseif !isfilled(mapstate, coord .+ (1, 1))
+                coord = coord .+ (1, 1)
+            else
+                fillblock!(mapstate, coord)
+                return true
+            end
+        end
+        return false
+    end
+
+    """
+    Fill the map with sand until all sand will fall forever.
+
+    Return the number of blocks that came to rest
+    """
+    function fillmap!(mapstate::MapState)
+        blocks_at_rest = 0
+        while dropblock!(mapstate)
+            blocks_at_rest += 1
+        end
+        blocks_at_rest
+    end
+end
+
+function part_1(input)
+    Maps.fillmap!(Maps.MapState(input))
+end
+@assert part_1(example) == 24
+@info part_1(input)
+
+function part_2(input)
+    nothing
+end
+@info part_2(input)
```