Skip to content

Commit

Permalink
Add solution for day 25
Browse files Browse the repository at this point in the history
  • Loading branch information
FrederikSchnack committed Dec 27, 2024
1 parent c2d507c commit 5ce8297
Show file tree
Hide file tree
Showing 10 changed files with 487 additions and 3 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@
| 16 | 3.564 s | 1061548| 1.53 GiB |
| 17 | 126.381 μs | 7897| 383.37 KiB |
| 18 | 29.729 ms | 38239| 3.09 MiB |
| 19 | 234.212 ms | 311732| 66.14 MiB |
| 19 | 234.212 ms | 311732| 66.14 MiB |
| 20 | 193.670 ms | 101404| 137.75 MiB |
| 21 | 247.048 μs | 9690| 293.26 KiB |
| 22 | 897.181 ms | 7148066| 383.11 MiB |
| 23 | 245.389 ms | 4917858| 345.13 MiB |
| 24 | 11.936 ms | 25796| 1.04 MiB |
| 25 | 9.693 ms | 327021| 12.20 MiB |
2 changes: 1 addition & 1 deletion inputs
2 changes: 1 addition & 1 deletion solutions/2024/src/AdventOfCode24.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module AdventOfCode24
readInput(day::Int) = AdventOfCode.readInput(day, year)
export readInput

solvedDays = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
solvedDays = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

# Include the source files:
for day in solvedDays
Expand Down
77 changes: 77 additions & 0 deletions solutions/2024/src/day20.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module Day20
using ..AdventOfCode24
using DataStructures

"""
day20()
Solves the two puzzles of day 20.
"""

function day20(input::String = readInput(20))
lines = split(input)
n,m = length(lines[1]), length(lines)
grid = [lines[i][j] for i in 2:n-1, j in 2:m-1]
S = findfirst(==('S'), grid)
E = findfirst(==('E'), grid)

s0, s1 = find_path(S, E, grid)

return [s0, s1]
end

const dir = (CartesianIndex(1, 0), CartesianIndex(0, 1), CartesianIndex(-1, 0), CartesianIndex(0, -1))
const cheating1 = 2 .* dir
const cheating2 = Tuple(CartesianIndex(x, y) for x in -20:20 for y in -20:20 if abs(x)+abs(y)<=20)


function find_path(start::CartesianIndex{2}, goal::CartesianIndex{2}, grid::Matrix{Char})

not_visited = Tuple{Int, CartesianIndex{2}}[(0, start)]
visited = Dict{CartesianIndex{2}, Int}()
cheats = Dict{CartesianIndex{2}, Vector{CartesianIndex{2}}}()
cheats2 = Dict{CartesianIndex{2}, Vector{CartesianIndex{2}}}()

while !isempty(not_visited)
s, curr = heappop!(not_visited)

haskey(visited, curr) && continue
visited[curr] = s

if curr == goal
break
end


cheats[curr] = [curr + d for d in cheating1 if get(grid, curr+d, '#') in ".E"]
cheats2[curr] = [curr + d for d in cheating2 if get(grid, curr+d, '#') in ".E"]

for d in dir
next = curr + d
!checkbounds(Bool, grid, next) && continue
grid[next] == '#' && continue
heappush!(not_visited, (s+1, next))
end

end


s0 = calculate_save(cheats, visited)
s1 = calculate_save(cheats2, visited)

return [s0, s1]
end


function calculate_save(cheats::Dict{CartesianIndex{2}, Vector{CartesianIndex{2}}}, visited::Dict{CartesianIndex{2}, Int})
s = 0
for (c,d) in cheats
for dd in d
dif = (visited[dd] - visited[c]) - sum(abs, (c-dd).I)
dif >= 100 && (s+=1)
end
end
return s
end

end
118 changes: 118 additions & 0 deletions solutions/2024/src/day21.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
module Day21
using ..AdventOfCode24
using Memoize

"""
day21()
Solves the two puzzles of day 21.
"""

struct keypad
grid::Matrix{Char}
coords::Dict{Char, CartesianIndex{2}}

keypad(grid::Matrix{Char}) =
new(grid, Dict(grid[x] => x for x in eachindex(IndexCartesian(), grid)))
end


const numpad = keypad(['7' '8' '9'; '4' '5' '6'; '1' '2' '3'; ' ' '0' 'A'])
const dirpad = keypad([' ' '^' 'A'; '<' 'v' '>'])

function day21(input::String = readInput(21))
s0 = 0
s1 = 0

for l in split(input)
v = parse(Int, l[1:end-1])

code = decode(numpad, l)

cl0 = minimum( count_level(2, c) for c in code)
cl1 = minimum( count_level(25, c) for c in code)

s0 += v * cl0
s1 += v * cl1
end

return [s0, s1]

end


function paths(a::CartesianIndex{2}, b::CartesianIndex{2}, grid::Matrix{Char})::Vector{String}
a == b && return ["A"]

a1, a2 = a.I
b1, b2 = b.I

d1 = b1-a1
d2 = b2-a2

d2 > 0 ? (cx = '>') : (cx = '<')
d1 > 0 ? (cy = 'v') : (cy = '^')

nx = abs(d2)
ny = abs(d1)

if size(grid) == (4,3)
if b2 == 1 && a1 == 4
return [cy^ny * cx^nx * 'A']
elseif a2 == 1 && b1 == 4
return [cx^ny * cy^nx * 'A']
end
elseif size(grid) == (2,3)
if b2 == 1 && a1 == 1
return [cy^ny * cx^nx * 'A']
elseif a2 == 1 && b1 == 1
return [cx^nx * cy^ny * 'A']
end
end

nx == 0 && return [cy^ny * 'A']
ny == 0 && return [cx^nx * 'A']

return [cy^ny * cx^nx * 'A', cx^nx * cy^ny * 'A']
end


function decode(pad::keypad, code::AbstractString, pos::CartesianIndex{2}=CartesianIndex{2}(0,0), path::String = "")::Vector{String}
iszero(pos) && (pos = pad.coords['A'])
isempty(code) && return [path]

target = pad.coords[code[1]]

res = String[]
for p in paths(pos, target, pad.grid)
append!(res, decode(pad, code[2:end], target, path*p))
end

return res

end

@memoize function count_level(level, code)::Int
level == 0 && (return length(code))

minlength = 0
start = 'A'

for key in code
len = Inf

for path in paths(dirpad.coords[start], dirpad.coords[key], dirpad.grid)

l = count_level(level-1, path)
l < len && (len = l)

end

start = key
minlength += len
end

return minlength
end

end
59 changes: 59 additions & 0 deletions solutions/2024/src/day22.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Day22
using ..AdventOfCode24

"""
day22()
Solves the two puzzles of day 22.
"""

function day22(input::String = readInput(22))
s0 = 0
n = 2000

offer = Dict{Vector{Int}, Int}()
seen = Set{Vector{Int}}()

for l in split(input)
secret = parse(Int, l)

seq = zeros(Int, n+1)
seq[1] = secret % 10

d = zeros(Int, n)

for i in 2:n+1
secret = step(secret)
seq[i] = secret % 10
d[i-1] = seq[i-1] - seq[i]
end

s0 += secret

empty!(seen)

for i in 4:n
dd = d[i-3:i]

dd in seen && continue

offer[dd] = get(offer, dd, 0) + seq[i+1]
push!(seen, dd)

end

end

s1 = maximum(values(offer))

return [s0, s1]
end

mix(x::Int, y::Int) = xor(x, y)
prune(x::Int) = mod(x, 16777216)
step1(x::Int) = prune(mix(64*x, x))
step2(x::Int) = prune(mix(floor(Int, x/32),x))
step3(x::Int) = prune(mix(x * 2048, x))
step(x::Int) = step3(step2(step1(x)))

end
56 changes: 56 additions & 0 deletions solutions/2024/src/day23.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module Day23
using ..AdventOfCode24

"""
day23()
Solves the two puzzles of day 23.
"""

function day23(input::String = readInput(23))

connections = Dict{String, Set{String}}()
r = r"(\w+)\-(\w+)\n?"
for l in eachmatch(r, input)
c1, c2 = string.(l.captures)
push!(get!(connections, c1, Set{String}()), c2)
push!(get!(connections, c2, Set{String}()), c1)
end

ic = Set{NTuple{3, String}}()
for l in eachmatch(r, input)
c1, c2 = l.captures
for c in intersect(connections[c1], connections[c2])
push!(ic, Tuple(sort([c1, c2, c])))
end
end

s0 = filter!(t -> any(t[k][1] == 't' for k in 1:3), ic) |> length

l = BronKerbosch(Set{String}(), Set(keys(connections)) , Set{String}(), connections) |> collect |> sort |> (x -> x .* ",") |> prod
s1 = l[1:end-1]

return [s0, s1]
end

function BronKerbosch(R::Set{String}, P::Set{String}, X::Set{String}, connections::Dict{String, Set{String}})::Set{String}

(isempty(P) && isempty(X)) && (return R)

res = Set{String}()

for v in P
nbs = get(connections, v, Set{String}())
clique = BronKerbosch(R Set{String}([v]), P nbs, X nbs, connections)
if length(clique) > length(res)
res = clique
end

delete!(P, v)
push!(X, v)
end

return res
end
end

Loading

0 comments on commit 5ce8297

Please sign in to comment.