Advent of Code 2024 - Day 19
Mix.install([
{:req, "~> 0.5"},
{:benchee, "~> 1.3"}
])
Input
opts = [headers: [{"cookie", "session=#{System.fetch_env!("LB_AOC_SESSION")}"}]]
puzzle_input = Req.get!("https://adventofcode.com/2024/day/19/input", opts).body
[patterns | towels] = String.split(puzzle_input, "\n", trim: true)
patterns = String.split(patterns, ", ")
defmodule LinenLayout do
def init_cache do
if :ets.whereis(:towels_cache) != :undefined do
:ets.delete(:towels_cache)
end
:ets.new(:towels_cache, [:set, :public, :named_table])
end
def possibilities("" = _towel, _patterns), do: 1
def possibilities(towel, patterns) do
case :ets.lookup(:towels_cache, towel) do
[{_key, result}] ->
result
[] ->
Enum.reduce(patterns, 0, fn pattern, acc ->
case towel do
^pattern <> rest -> possibilities(rest, patterns) + acc
_other -> acc
end
end)
|> tap(fn result ->
:ets.insert(:towels_cache, {towel, result})
end)
end
end
end
Puzzle 1
puzzle_1 = fn ->
LinenLayout.init_cache()
towels
|> Task.async_stream(&LinenLayout.possibilities(&1, patterns))
|> Enum.reduce(0, fn {:ok, result}, acc ->
if result == 0, do: acc, else: acc + 1
end)
end
puzzle_1.()
puzzle_2 = fn ->
LinenLayout.init_cache()
towels
|> Task.async_stream(&LinenLayout.possibilities(&1, patterns))
|> Enum.reduce(0, fn {:ok, result}, acc ->
result + acc
end)
end
puzzle_2.()
Benchmarks
Benchee.run(
%{
"puzzle_1" => fn -> puzzle_1.() end,
"puzzle_2" => fn -> puzzle_2.() end
})
Name |
ips |
average |
deviation |
median |
99th % |
puzzle_1 |
7.38 |
135.52 ms |
±16.46% |
127.98 ms |
192.95 ms |
puzzle_2 |
5.88 |
170.21 ms |
±6.69% |
172.76 ms |
190.97 ms |