Mercurial > lbo > hg > aoc22
view 2022/14/14.jl @ 63:f2355e1a8e8c
Day 12 Part 1
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 23 Dec 2023 14:14:45 +0100 |
parents | 05ddc45b4210 |
children |
line wrap: on
line source
mutable struct PS s::String pos::Int end function initialize(s::String)::PS PS(s, 1) end function parse_coord(ps::PS)::Tuple{Int,Int} e = findfirst((==)(','), ps.s[ps.pos:end]) x = parse(Int, ps.s[ps.pos:ps.pos+e-2]); ps.pos = ps.pos + e; e = something(findfirst((==)(' '), ps.s[ps.pos:end]), length(ps.s)-ps.pos+2); y = parse(Int, ps.s[ps.pos:ps.pos+e-2]); ps.pos = ps.pos + e - 1; (x, y) end function parse_sep(ps::PS)::Bool if ps.pos >= length(ps.s) false else @assert ps.s[ps.pos:ps.pos+3] == " -> " ps.pos += 4; true end end function parse_coords(ps::PS)::Vector{Tuple{Int,Int}} poss = Vector{Tuple{Int,Int}}(); while true push!(poss, parse_coord(ps)); if !parse_sep(ps) break end end poss end function parse_all_coords(fh::IOStream)::Vector{Vector{Tuple{Int,Int}}} vs = Vector{Vector{Tuple{Int,Int}}}(); for l in eachline(fh) push!(vs, parse_coords(initialize(l))); end vs end const EMPTY = 0; const ROCK = 1; const SAND = 2; function run_matrix_2(v::Vector{Vector{Tuple{Int,Int}}}) SAND_POINT = (500,0) minx = min(SAND_POINT[1], minimum(minimum(t[1] for t in vv) for vv in v)); maxx = max(SAND_POINT[1], maximum(maximum(t[1] for t in vv) for vv in v)); miny = min(SAND_POINT[2], minimum(minimum(t[2] for t in vv) for vv in v)); maxy = max(SAND_POINT[2], maximum(maximum(t[2] for t in vv) for vv in v)); maxx += div((maxy-miny)+1, 1); minx -= div((maxy-miny)+1, 1); m = zeros(Int8, maxx-minx+1, maxy-miny+1+2); m[begin:end, end] .= ROCK; for line in v last = line[1]; for p in @view line[2:end] a, b = CartesianIndex(last .- (minx-1, miny-1)), CartesianIndex(p .- (minx-1, miny-1)); @assert abs(last[1]-p[1]) == 0 || abs(last[2]-p[2]) == 0 if a > b a, b = b, a; end m[a:b] .= ROCK; last = p; end end show_cave(m); # part 2 println(" === PART 2 === "); pos0 = SAND_POINT .- (minx-1, miny-1); down, left, right = (0,1), (-1,1), (1,1); X, Y = size(m); isvalid(pos) = 0 < pos[1] && pos[1] <= X && 0 < pos[2] && pos[2] <= Y count = 0; pos = pos0; while true if m[CartesianIndex(pos .+ down)] == EMPTY pos = pos .+ down; continue; elseif m[CartesianIndex(pos .+ left)] == EMPTY pos = pos .+ left; continue elseif m[CartesianIndex(pos .+ right)] == EMPTY pos = pos .+ right; continue; else count += 1; if pos == pos0 break; end m[CartesianIndex(pos)] = SAND; println(" ==== $count ==== "); pos = pos0; continue; end end show_cave(m); @show count; end function run_matrix(v::Vector{Vector{Tuple{Int,Int}}}) # Not very efficient... SAND_POINT = (500,0) minx = min(SAND_POINT[1], minimum(minimum(t[1] for t in vv) for vv in v)); maxx = max(SAND_POINT[1], maximum(maximum(t[1] for t in vv) for vv in v)); miny = min(SAND_POINT[2], minimum(minimum(t[2] for t in vv) for vv in v)); maxy = max(SAND_POINT[2], maximum(maximum(t[2] for t in vv) for vv in v)); m = zeros(Int8, maxx-minx+1, maxy-miny+1); for line in v last = line[1]; for p in @view line[2:end] a, b = CartesianIndex(last .- (minx-1, miny-1)), CartesianIndex(p .- (minx-1, miny-1)); @assert abs(last[1]-p[1]) == 0 || abs(last[2]-p[2]) == 0 if a > b a, b = b, a; end m[a:b] .= ROCK; last = p; end end M0 = copy(m); down, left, right = (0,1), (-1,1), (1,1); X, Y = size(m); isvalid(pos) = 0 < pos[1] && pos[1] <= X && 0 < pos[2] && pos[2] <= Y count = 0; pos0 = SAND_POINT .- (minx-1, miny-1); pos = pos0; while true if !isvalid(pos .+ down) break; elseif m[CartesianIndex(pos .+ down)] == EMPTY pos = pos .+ down; continue; elseif !isvalid(pos .+ left) break; elseif m[CartesianIndex(pos .+ left)] == EMPTY pos = pos .+ left; continue elseif !isvalid(pos .+ right) break; elseif m[CartesianIndex(pos .+ right)] == EMPTY pos = pos .+ right; continue; else count += 1; m[CartesianIndex(pos)] = SAND; println(" ==== $count ==== "); pos = pos0; continue; end end show_cave(m); @show count; end function show_cave(m::Matrix{Int8}) for r in eachrow(m') println(r); end end open("14/test_input.txt"; read=true) do fh ac = (parse_all_coords(fh)); run_matrix(ac); run_matrix_2(ac); end