40 lines
986 B
Elixir
40 lines
986 B
Elixir
defmodule Day7Part2 do
|
|
@bag_spec ~r/\A(\d) (\w+ \w+).*\z/
|
|
|
|
def run do
|
|
File.read!("input")
|
|
|> input_to_tree()
|
|
|> count_children("shiny gold")
|
|
|> IO.puts()
|
|
end
|
|
|
|
def count_children(tree, name) do
|
|
Enum.reduce(tree[name], 0, fn {size, child_name}, count ->
|
|
count + size + size * count_children(tree, child_name)
|
|
end)
|
|
end
|
|
|
|
def input_to_tree(input) do
|
|
input
|
|
|> String.trim(".\n")
|
|
|> String.split(".\n")
|
|
|> Enum.map(&String.split(&1, " bags contain "))
|
|
|> Map.new(fn [parent, child_spec] -> {parent, parse_children(child_spec)} end)
|
|
end
|
|
|
|
def parse_children(child_spec) when is_binary(child_spec) do
|
|
child_spec
|
|
|> String.split(", ")
|
|
|> parse_children()
|
|
end
|
|
|
|
def parse_children(["no other bags"]), do: []
|
|
|
|
def parse_children(list) do
|
|
list
|
|
|> Enum.map(&Regex.run(@bag_spec, &1, capture: :all_but_first))
|
|
|> Enum.map(fn [count, type] -> {String.to_integer(count), type} end)
|
|
end
|
|
end
|
|
|
|
Day7Part2.run()
|