Monster Messages
defmodule Aoc2020.Day19 do
@moduledoc "Monster Messages"
def run() do
part_1()
end
def part_1() do
{rules, messages} = parse_input()
rule_zero = eval_rule(rules, Keyword.fetch!(rules, :"0"))
IO.inspect(rule_zero, label: "Rule 0")
flatten_variants(rule_zero, [[]])
end
def part_2() do
parse_input()
end
def parse_input() do
# File.read!("priv/inputs/2020/day19.txt")
test_input()
|> String.trim()
|> String.split("\n\n", parts: 2)
|> (fn [rules_str, messages_str] ->
{parse_rules(rules_str), parse_messages(messages_str)}
end).()
end
def parse_rules(str) do
str
|> String.split("\n")
|> Enum.map(&parse_rule/1)
end
def parse_rule(line) do
[index, sub_rules] = String.split(line, ": ")
rule =
case String.contains?(sub_rules, " | ") do
true -> Enum.map(String.split(sub_rules, " | "), &parse_sub_rule/1)
false -> parse_sub_rule(sub_rules)
end
{String.to_atom(index), rule}
end
def parse_sub_rule(<<"\"", letter, "\"">>), do: <<letter>>
def parse_sub_rule(str) do
String.split(str, " ") |> Enum.map(&String.to_atom/1)
end
def parse_messages(str), do: String.split(str, "\n")
def test_input() do
"0: 4 1 5\n1: 2 3 | 3 2\n2: 4 4 | 5 5\n3: 4 5 | 5 4\n4: \"a\"\n5: \"b\"\n\nababbb\nbababa\nabbbab\naaabbb\naaaabbb"
end
def eval_rule(_, []), do: []
def eval_rule(rules, [head | rest]) do
case Keyword.fetch!(rules, head) do
letter when is_binary(letter) -> [letter | eval_rule(rules, rest)]
lst when is_list(lst) -> [Enum.map(lst, &eval_rule(rules, &1)) | eval_rule(rules, rest)]
end
end
def flatten_variants([], acc), do: Enum.map(acc, &Enum.reverse/1)
def flatten_variants([value | rest], acc) when is_binary(value) do
Enum.map(acc, &[flatten_variants(rest, acc) | [value | &1]])
end
def flatten_variants([[branchA, branchB] | rest], acc) do
IO.inspect([branchA | rest], label: "Branch A")
Enum.map(acc, &flatten_variants([branchA | rest], &1)) ++
Enum.map(acc, &flatten_variants([branchB | rest], &1))
end
end