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 2d2c3b50224a67ec8b52aa871246c7672fd7c088
parent 9411152faa02ad1b7a725723db3403a1cfc5cba7
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date:   Wed, 14 Dec 2022 21:51:26 -0800

Solution to day 15, part 1.

Diffstat:
Asrc/day_15.jl | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+), 0 deletions(-)

diff --git a/src/day_15.jl b/src/day_15.jl @@ -0,0 +1,71 @@ +#!/usr/bin/env julia +# https://adventofcode.com/2022/day/15 +using AdventOfCode + +example = readlines(IOBuffer(""" + Sensor at x=2, y=18: closest beacon is at x=-2, y=15 + Sensor at x=9, y=16: closest beacon is at x=10, y=16 + Sensor at x=13, y=2: closest beacon is at x=15, y=3 + Sensor at x=12, y=14: closest beacon is at x=10, y=16 + Sensor at x=10, y=20: closest beacon is at x=10, y=16 + Sensor at x=14, y=17: closest beacon is at x=10, y=16 + Sensor at x=8, y=7: closest beacon is at x=2, y=10 + Sensor at x=2, y=0: closest beacon is at x=2, y=10 + Sensor at x=0, y=11: closest beacon is at x=2, y=10 + Sensor at x=20, y=14: closest beacon is at x=25, y=17 + Sensor at x=17, y=20: closest beacon is at x=21, y=22 + Sensor at x=16, y=7: closest beacon is at x=15, y=3 + Sensor at x=14, y=3: closest beacon is at x=15, y=3 + Sensor at x=20, y=1: closest beacon is at x=15, y=3""")) +input = readlines("data/day_15.txt") + +function parse_input(input) + pattern = r"Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+)" + matches = map(x->match(pattern, x), input) + @assert !any(map(isnothing, matches)) + parse.( + Int, + permutedims(hcat(map(Base.Fix2(getfield, :captures), matches)...)) + ) +end + +function beacon_distance(sensors::AbstractMatrix{Int}) + abs.(sensors[:,1]-sensors[:,3]) + abs.(sensors[:,2]-sensors[:,4]) +end + +""" +Scan a row and count spaces where a beacon cannot be. +""" +function scan_row(sensors::AbstractMatrix{Int}, row::Int) + # This tells us how far away each beacon is from the sensor that detects + # it. Any space closer than this to the sensor necessarily has no beacon. + # One effect of this is that we don't need to worry about scanners that are + # more than this distance from the row. + maxdist = beacon_distance(sensors) + sensoridx = findall(abs.(sensors[:,2] .- row) .< maxdist) + + # Each sensor contributes a range of values that cannot be occupied on a + # given row. These ranges can overlap but we'll deal with that in the next + # step. For now, track the ranges. + beaconfree = Vector{UnitRange{Int}}() + for s_i = sensoridx + offset = maxdist[s_i]-abs(sensors[s_i,2] - row) + push!(beaconfree, + (sensors[s_i,1]-offset):(sensors[s_i,1]+offset)) + end + + # Deal with the overlap and actual beacons on the row + setdiff(reduce(union, beaconfree), + unique(sensors[sensoridx[sensors[sensoridx, 4] .== row], 3])) +end + +function part_1(input, row) + length(scan_row(parse_input(input), row)) +end +@assert part_1(example, 10) == 26 +@info part_1(input, 2000000) + +function part_2(input) + nothing +end +@info part_2(input)