Mercurial > lbo > hg > aoc22
view 2022/15/15.jl @ 43:865325736c6f
Day 05 Part 1
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 05 Dec 2023 21:04:58 +0100 |
parents | 05ddc45b4210 |
children |
line wrap: on
line source
using ParserCombinator const Line = E"Sensor at x=" + PInt64() + E", y=" + PInt64() + E": closest beacon is at x=" + PInt64() + E", y=" + PInt64() + Eos(); struct Point x::Int y::Int end function distance(p::Point, q::Point)::Int abs(p.x-q.x) + abs(p.y-q.y) end struct Beacon sensor::Point beacon::Point dist::Int end function parse_line(s::String)::Beacon es = parse_one(s, Line); p, q = Point(es[1]::Int, es[2]::Int), Point(es[3]::Int, es[4]::Int) Beacon(p, q, distance(p, q)) end function parse_lines(f::String)::Vector{Beacon} v = Vector{Beacon}(); open(f; read=true) do fh for l in eachline(fh) push!(v, parse_line(l)); end end v end function point_is_within_closest(p::Point, b::Beacon)::Bool distance(p, b.sensor) <= b.dist && p != b.beacon end function point_is_beacon(p::Point, bs::Vector{Beacon})::Bool any(b -> b.beacon == p, bs) end function point_is_covered(p::Point, bs::Vector{Beacon}; ignorebeacon=false)::Bool any(b -> point_is_within_closest(p, b), bs) end function n_covered_points(bs::Vector{Beacon}, y::Int)::Int minx = minimum(min(b.sensor.x, b.beacon.x)-b.dist for b in bs); maxx = maximum(max(b.sensor.x, b.beacon.x)+b.dist for b in bs); count = sum(point_is_covered(Point(x, y), bs) for x = minx:maxx); count end function find_distress_beacon(bs::Vector{Beacon}, minc=0, maxc=20)::Set{Point} # Check borders of sensor's coverage area - as there is only one point to check, # it must be directly outside a sensor's coverage area. v = Set{Point}(); isvalid(p) = p.x >= minc && p.x <= maxc && p.y >= minc && p.y <= maxc; for b in bs @show b for x = b.sensor.x-b.dist:b.sensor.x+b.dist for dir = [-1, 1] y = dir*b.sensor.y + abs(b.dist - abs(b.sensor.x-x)); p = Point(x+sign(x-b.sensor.x), y); if isvalid(p) && !point_is_covered(p, bs) && !point_is_beacon(p, bs) push!(v, p); continue; end if x == b.sensor.x p = Point(x, y+dir); if isvalid(p) && !point_is_covered(p, bs) && !point_is_beacon(p, bs) push!(v, p); continue; end end end end end v end function tuning_frequency(p::Point)::Int p.x*4000000+p.y end bs = parse_lines("15/input.txt"); println(n_covered_points(bs, 2000000)); db = find_distress_beacon(bs, 0, 4000000); @show (db, map(tuning_frequency, collect(db))) bs = parse_lines("15/test_input.txt"); println(n_covered_points(bs, 10)); db = find_distress_beacon(bs); @show (db, map(tuning_frequency, collect(db)))