-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c2d507c
commit 5ce8297
Showing
10 changed files
with
487 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule inputs
updated
from 5e9a18 to 9a2acc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
Oops, something went wrong.