From af0bf743e977285504f4d736ea710e5eee6e43f4 Mon Sep 17 00:00:00 2001 From: Alexander Seiler Date: Fri, 29 Dec 2023 02:52:31 +0100 Subject: [PATCH] [Day 24] Add solution --- README.md | 4 ++-- src/day24.jl | 41 +++++++++++++++++++++++++++++++---------- test/runtests.jl | 2 ++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 00d4b4d..e2bf8e0 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ This Julia package contains my solutions for [Advent of Code 2023](https://adven | 20 | [:white_check_mark:](https://adventofcode.com/2023/day/20) | 65.710 ms | 28.76 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day20.jl) | | 21 | [:white_check_mark:](https://adventofcode.com/2023/day/21) | 73.583 ms | 187.11 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day21.jl) | | 22 | [:white_check_mark:](https://adventofcode.com/2023/day/22) | 790.712 ms | 631.26 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day22.jl) | -| 23 | [:white_check_mark:](https://adventofcode.com/2023/day/23) | 2.136 s | 9.69 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day23.jl) | - +| 23 | [:white_check_mark:](https://adventofcode.com/2023/day/23) | 2.979 s | 9.69 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day23.jl) | +| 24 | [:white_check_mark:](https://adventofcode.com/2023/day/24) | 41.181 ms | 49.71 MiB | [:white_check_mark:](https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day24.jl) | diff --git a/src/day24.jl b/src/day24.jl index d506049..e8b8521 100644 --- a/src/day24.jl +++ b/src/day24.jl @@ -3,35 +3,36 @@ module Day24 using AdventOfCode2023 using LinearAlgebra -struct Hailstone +struct Line p::Vector{Int} v::Vector{Int} end +eval_at(h::Line, t::Number) = h.p + t * h.v function day24(input::String = readInput(joinpath(@__DIR__, "..", "data", "day24.txt"))) hailstones = parse_input(input) - part1(hailstones) + return [part1(hailstones), part2(hailstones)] end function parse_input(input::AbstractString) - data = Hailstone[] + data = Line[] for line ∈ eachsplit(rstrip(input), "\n") left, right = strip.(split(line, "@")) - push!(data, Hailstone(parse.(Int, split(left, ",")), parse.(Int, split(right, ",")))) + push!(data, Line(parse.(Int, split(left, ",")), parse.(Int, split(right, ",")))) end return data end -function part1(data::Vector{Hailstone}; leftbound::Int64=20_0000_000_000_000, rightbound::Int64=400_000_000_000_000) +function part1(lines::Vector{Line}; leftbound::Int64=20_0000_000_000_000, rightbound::Int64=400_000_000_000_000) c = 0 - for i ∈ firstindex(data):lastindex(data) - for j ∈ i + 1: lastindex(data) - A = hcat(data[i].v[1:2], -data[j].v[1:2]) - rhs = data[j].p[1:2] - data[i].p[1:2] + for i ∈ firstindex(lines):lastindex(lines) + for j ∈ i + 1: lastindex(lines) + A = hcat(lines[i].v[1:2], -lines[j].v[1:2]) + rhs = lines[j].p[1:2] - lines[i].p[1:2] A[1] * A[4] - A[2] * A[3] == 0 && continue # parallel t, s = A \ rhs - x, y = data[i].p[1:2] + t * data[i].v[1:2] + x, y = lines[i].p[1:2] + t * lines[i].v[1:2] if leftbound <= x <= rightbound && leftbound <= y <= rightbound && t >= 0 && s >= 0 c += 1 end @@ -40,4 +41,24 @@ function part1(data::Vector{Hailstone}; leftbound::Int64=20_0000_000_000_000, ri return c end +function part2(lines::Vector{Line}) + for lind=firstindex(lines):lastindex(lines)-3 + i, j, k = lind, lind + 1, lind + 2 + cij, sij = _coeffs_rhsscalar(lines[i], lines[j]) + cik, sik = _coeffs_rhsscalar(lines[i], lines[k]) + cjk, sjk = _coeffs_rhsscalar(lines[j], lines[k]) + A = vcat(cij', cik', cjk') + det(A) ≈ 0 && continue + rhs = [sij, sik, sjk] + w = round.(Int, A \ rhs) + A = hcat((lines[i].v - w)[1:2], (w - lines[j].v)[1:2]) + rhs = (lines[j].p - lines[i].p)[1:2] + t, _ = A \ rhs + return round.(Int, eval_at(Line(lines[i].p, lines[i].v - w), t)) |> sum + end +end + +_coeffs_rhsscalar(l1::Line, l2::Line) = (float(l1.p) - l2.p) × (float(l1.v) - l2.v), dot(float(l1.p) - l2.p, float(l1.v) × l2.v) + + end # module diff --git a/test/runtests.jl b/test/runtests.jl index 3ecd802..8b41c93 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -322,4 +322,6 @@ end "20, 19, 15 @ 1, -5, -3\n" hailstones_sample = AdventOfCode2023.Day24.parse_input(sample) @test AdventOfCode2023.Day24.part1(hailstones_sample; leftbound=7, rightbound=27) == 2 + @test AdventOfCode2023.Day24.part2(hailstones_sample) == 47 + @test AdventOfCode2023.Day24.day24() == [20336, 677656046662770] end