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 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:
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 +# 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)