commit 74fb77374becc1820d19220bf8d28378e8bff3ef
parent 76957adbbe41092c3a00cb022c3ca865e6433bfd
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date: Wed, 14 Dec 2022 09:45:43 -0800
Solution to day 14, part 1.
Diffstat:
A | src/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
+# https://adventofcode.com/2022/day/14
+using AdventOfCode
+
+example = readlines(IOBuffer("""
+ 498,4 -> 498,6 -> 496,6
+ 503,4 -> 502,4 -> 502,9 -> 494,9"""))
+input = readlines("data/day_14.txt")
+
+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][1], lines[i][1])...,
+ step = 1)
+ yline = range(minmax(lines[i-1][2], lines[i][2])...,
+ 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[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
+ 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.
+ Updates mapstate.
+ """
+ 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)