const grid = [ collect(line) for line in readlines("input/8") ] const size = length(grid) const Coords = Tuple{Int,Int} ants::Dict{Char,Vector{Coords}} = Dict() for (y,row) in enumerate(grid) for (x,c) in enumerate(row) if c != '.' get!(ants, c, []) .= push!(ants[c], (x, y)) end end end isOnMap(n) = 1 <= n[1] <= size && 1 <= n[2] <= size partOneGrid = deepcopy(grid) partOneSet, partTwoSet = Set(), Set() for (freq,coords) in ants for (a,b) in Iterators.filter((x) -> x[1] != x[2], ( sort([a, b]) for a in coords, b in coords )) local diff = a .- b for n in (a .+ diff, b .- diff) if isOnMap(n) push!(partOneSet, n) end end for (n,fn) in ((a,.-), (b,.+)) while isOnMap(n) n = fn(n, diff) if isOnMap(n) push!(partTwoSet, n) end end end end end const partOne, partTwo = length(partOneSet), length(partTwoSet) @show partOne, partTwo