commit 68a681fe37b7d4d877442c0140b8c9767656ff71
parent 74fb77374becc1820d19220bf8d28378e8bff3ef
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date:   Wed, 14 Dec 2022 10:38:01 -0800
Solution to day 14, part 2.
I was so emotionally prepared for my implementation to completely fall
apart for part 2, but it turns out that I only needed to make some minor
changes, lol. I will confess to you, stranger who actually reads these
commit messages, that I had a couple infinite loop bugs to track down
before this actually worked. But it was overall straightforward and
satisfying.
Diffstat:
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/day_14.jl b/src/day_14.jl
@@ -13,9 +13,11 @@ module Maps
     struct MapState
        filled_blocks::Set{Tuple{Int,Int}}
        lowest_row::Int
+       has_floor::Bool
     end
 
-    function MapState(input::Vector{<:AbstractString})
+    function MapState(input::Vector{<:AbstractString},
+                      add_floor = false)
         filled_blocks = Set{Tuple{Int,Int}}()
         lowest_row = -Inf
         for path = input
@@ -31,7 +33,7 @@ module Maps
                 end
             end
         end
-        MapState(filled_blocks, lowest_row)
+        MapState(filled_blocks, lowest_row, add_floor)
     end
 
     # I'm going to try to keep these function signatures implementation-neutral
@@ -42,14 +44,15 @@ module Maps
     Return true IFF sand at the given coordinate is destined to fall forever.
     """
     function isfallingforever(mapstate::MapState, coord::Tuple{Int,Int})
-        coord[2] > mapstate.lowest_row
+        !mapstate.has_floor && coord[2] > 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
+        (mapstate.has_floor && coord[2] >= mapstate.lowest_row + 2) ||
+            coord in mapstate.filled_blocks
     end
 
     """
@@ -62,12 +65,12 @@ module Maps
     """
     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.
-    Updates mapstate.
+    Returns true if the block comes to rest and false if it falls forever or
+    the map is "full". Updates mapstate.
     """
     function dropblock!(mapstate::MapState)
         coord = (500, 0)
-        while !isfallingforever(mapstate, coord)
+        while !isfallingforever(mapstate, coord) && !isfilled(mapstate, coord)
             if !isfilled(mapstate, coord .+ (0, 1))
                 coord = coord .+ (0, 1)
             elseif !isfilled(mapstate, coord .+ (-1, 1))
@@ -83,7 +86,7 @@ module Maps
     end
 
     """
-    Fill the map with sand until all sand will fall forever.
+    Fill the map with sand until all sand will fall forever or the source is filled.
 
     Return the number of blocks that came to rest
     """
@@ -103,6 +106,7 @@ end
 @info part_1(input)
 
 function part_2(input)
-    nothing
+    Maps.fillmap!(Maps.MapState(input, true))
 end
+@assert part_2(example) == 93
 @info part_2(input)