d19
Section
ExUnit.start()
defmodule D19 do
def start_link do
if :ets.whereis(:memo_table) == :undefined do
:ets.new(:memo_table, [:set, :public, :named_table])
else
:ok
end
end
def parse(input) do
[top, bottom] = String.split(input, "\n\n")
towels = String.split(top, ", ") |> Enum.map(&String.to_charlist/1)
designs = String.split(bottom, "\n", trim: true) |> Enum.map(&String.to_charlist/1)
{towels, designs}
end
def arrangements(towels, design) do
case :ets.lookup(:memo_table, {towels, design}) do
[] ->
result = arrangements_calc(towels, design)
:ets.insert(:memo_table, {{towels, design}, result})
result
[{_, result}] ->
result
end
end
defp arrangements_calc(_, []), do: 1
defp arrangements_calc(towels, design) do
Enum.map(towels, fn towel ->
{left, right} = Enum.split(design, Enum.count(towel))
if left == towel, do: arrangements(towels, right), else: 0
end)
|> Enum.sum()
end
def part1({towels, designs}) do
Enum.count(designs, fn design -> arrangements(towels, design) > 0 end)
end
def part2({towels, designs}) do
Enum.reduce(designs, 0, fn design, acc -> acc + arrangements(towels, design) end)
end
use ExUnit.Case
test "sample" do
input = "r, wr, b, g, bwu, rb, gb, br
brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb
"
assert 6 == D19.parse(input) |> D19.part1()
assert 16 == D19.parse(input) |> D19.part2()
end
end
D19.start_link()
ExUnit.run()
input = File.read!(__DIR__ <> "/input")
D19.parse(input) |> D19.part1()
D19.parse(input) |> D19.part2()