Advent of code day 19
Mix.install([
{:kino, "~> 0.5.0"}
])
Setup input
example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")
[patterns, words] = example |> Kino.Input.read() |> String.split("\n\n")
patterns = patterns |> String.split(", ", trim: true) |> Enum.into(MapSet.new())
words = words |> String.split("\n", trim: true)
defmodule SimpleCache do
@moduledoc """
A simple ETS based cache for expensive function calls.
"""
def init_cache() do
if :ets.whereis(:simple_cache) != :undefined do
:ets.delete(:simple_cache)
end
:ets.new(:simple_cache, [:set, :public, :named_table])
end
@doc """
Retrieve a cached value or apply the given function caching and returning
the result.
"""
def get(mod, fun, args, opts \\ []) do
case lookup(mod, fun, args) do
nil ->
ttl = Keyword.get(opts, :ttl, 3600)
cache_apply(mod, fun, args, ttl)
result ->
result
end
end
defp lookup(mod, fun, args) do
case :ets.lookup(:simple_cache, [mod, fun, args]) do
[result | _] -> check_freshness(result)
[] -> nil
end
end
defp check_freshness({_mfa, result, expiration}) do
cond do
expiration > :os.system_time(:seconds) -> result
:else -> nil
end
end
defp cache_apply(mod, fun, args, ttl) do
result = apply(mod, fun, args)
expiration = :os.system_time(:seconds) + ttl
:ets.insert(:simple_cache, {[mod, fun, args], result, expiration})
result
end
end
defmodule Solver do
def possible?(word, patterns) do
case word do
"" ->
1
word ->
Enum.reduce(patterns, 0, fn pattern, acc ->
case String.starts_with?(word, pattern) do
true ->
acc +
SimpleCache.get(Solver, :possible?, [
String.replace_prefix(word, pattern, ""),
patterns
])
_ ->
acc
end
end)
end
end
end
SimpleCache.init_cache()
Part 01
Enum.reduce(words, 0, fn word, acc ->
case Solver.possible?(word, patterns) do
0 -> acc
_x -> acc + 1
end
end)
Part 02
Enum.reduce(words, 0, fn word, acc ->
case Solver.possible?(word, patterns) do
0 -> acc
x -> acc + x
end
end)