Day 19
file:test/Day19Spec.jl
# add tests
file:src/Day19.jl
module Day19
function read_input(io::IO)
= readlines(io) |> collect
lines = split(lines[1], ", ")
patterns = lines[3:end]
designs return patterns, designs
end
mutable struct Tree{T}
::Bool
isleaf::Dict{T, Tree{T}}
branchesend
Tree{T}() where {T} = Tree{T}(false, Dict{T, Tree{T}}())
add_path!(t::Tree{T}, it::I) where {T, I} =
_add_path_helper!(t, it, iterate(it))
add_path!(t::Tree{T}, it::I, state::S) where {T, I, S} =
_add_path_helper!(t, it, iterate(it, state))
function _add_path_helper!(t::Tree{T}, it::I, item::Nothing) where {T, I}
= true
t.isleaf return t
end
function _add_path_helper!(t::Tree{T}, it::I, item::Tuple{T, S}) where {T, I, S}
= item
value, state
if value ∉ keys(t.branches)
= Tree(false, Dict{T, Tree{T}}())
t.branches[value] end
add_path!(t.branches[value], it, state)
end
function pattern_tree(pat::Vector{S}) where {S<:AbstractString}
= Tree{Char}()
t for p in pat
add_path!(t, p)
end
return t
end
Base.match(p::Tree{Char}) = s -> match(p, s, Dict{String, Int}())
function Base.match(p::Tree{Char}, s::T, cache::Dict{String,Int}) where {T <: AbstractString}
∈ keys(cache) && return cache[s]
s
function compute()
isempty(s) && return 1
1] ∉ keys(p.branches) && return 0
s[
= T[]
remainders partial_match(p.branches[s[1]], s[2:end], remainders)
sum(r->match(p, r, cache), remainders; init=0)
end
return cache[s] = compute()
end
function partial_match(p::Tree{Char}, s::T, out::Vector{T}) where {T <: AbstractString}
if p.isleaf
push!(out, s)
end
if isempty(s) || s[1] ∉ keys(p.branches)
return
end
partial_match(p.branches[s[1]], s[2:end], out)
end
function main(io::IO)
= read_input(io)
patterns, designs = pattern_tree(patterns)
ptree = map(match(ptree), designs)
counts = sum(counts .> 0)
part1 = sum(counts)
part2
part1, part2end
end