Skip to content

Instantly share code, notes, and snippets.

@charmasaur
Created December 31, 2022 02:38
Show Gist options
  • Save charmasaur/1679b9fe5b84b18df072a1b70153263d to your computer and use it in GitHub Desktop.
Save charmasaur/1679b9fe5b84b18df072a1b70153263d to your computer and use it in GitHub Desktop.
AOC 2022 22
using AutoHashEquals
using LinearAlgebra
# Load and parse input
lines = open(readlines, "in.txt")
instructions = split(replace(lines[end], "R" => " R ", "L" => " L "))
grid_lines = lines[1:end-2]
R = length(grid_lines)
C = maximum(length.(grid_lines))
grid_lines = rpad.(grid_lines, C)
grid = [grid_lines[r][c] for r=1:R, c=1:C]
start = findfirst(x -> x == '.', grid[1, :])
# Utilities for 2D points
@auto_hash_equals struct Pos2D
pos::Vector{Int64}
dir::Int64
end
dirs = (
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
)
left(s::Pos2D) = Pos2D(s.pos, mod1(s.dir-1, 4))
right(s::Pos2D) = Pos2D(s.pos, mod1(s.dir+1, 4))
start2d = Pos2D([1, start], 1)
# Generic processing of instructions
function walk(pos, left, right, step, transform)
for i in instructions
if i == "L"
pos = left(pos)
continue
end
if i == "R"
pos = right(pos)
continue
end
for _ in 1:parse(Int, i)
npos = step(pos)
if grid[transform(npos).pos...] == '#'
break
end
pos = npos
end
end
p2d = transform(pos)
return 1000 * p2d.pos[1] + 4 * p2d.pos[2] + p2d.dir - 1
end
# Part 1
function step_wrap(pos::Pos2D)
np = pos.pos
while true
np = mod1.(np + dirs[pos.dir], (R, C))
if grid[np...] == ' '
continue
end
return Pos2D(np, pos.dir)
end
end
println(walk(start2d,
left,
right,
step_wrap,
p -> p))
# Part 2
S = 50
function step(s::Pos2D)
return Pos2D(s.pos + dirs[s.dir], s.dir)
end
@auto_hash_equals struct Pos3D
normal::Vector{Int64}
dir::Vector{Int64}
pos::Vector{Int64}
end
left(s::Pos3D) = Pos3D(s.normal, cross(s.normal, s.dir), s.pos)
right(s::Pos3D) = Pos3D(s.normal, -cross(s.normal, s.dir), s.pos)
function step(s::Pos3D)
npos = s.pos + s.dir
if minimum(npos) >= 1 && maximum(npos) <= S
return Pos3D(s.normal, s.dir, npos)
end
return Pos3D(s.dir, -s.normal, s.pos)
end
# Assume the origin is on the left side of the top row, with the x axis along the top row, y
# down the screen, and z into the screen.
start3d = Pos3D([0, 0, -1], [1, 0, 0], [mod1(start, S), 1, 1])
function create_transformation()
transformation = Dict{Pos3D, Pos2D}()
seen = Set{Pos2D}()
push!(seen, start2d)
q = Tuple{Pos2D, Pos3D}[]
push!(q, (start2d, start3d))
while !isempty(q)
p2d, p3d = pop!(q)
transformation[p3d] = p2d
for func in (left, right, step)
np2d = func(p2d)
if !checkbounds(Bool, grid, np2d.pos...) || grid[np2d.pos...] == ' ' || np2d in seen
continue
end
push!(seen, np2d)
push!(q, (np2d, func(p3d)))
end
end
return p3d -> transformation[p3d]
end
println(walk(start3d,
left,
right,
step,
create_transformation()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment