Day 19 Part 2
This commit is contained in:
parent
d1ccd00ca3
commit
db18ed3281
1 changed files with 147 additions and 28 deletions
|
|
@ -4,8 +4,14 @@ defmodule RBNF do
|
||||||
|> Enum.into(%{}, fn [name, rbnf] ->
|
|> Enum.into(%{}, fn [name, rbnf] ->
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
|
make_rule(rbnf)
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_rule(str) do
|
||||||
{:alt,
|
{:alt,
|
||||||
String.split(rbnf, " | ")
|
String.split(str, " | ")
|
||||||
|> Enum.map(fn text ->
|
|> Enum.map(fn text ->
|
||||||
seq =
|
seq =
|
||||||
String.split(text, " ")
|
String.split(text, " ")
|
||||||
|
|
@ -18,8 +24,6 @@ defmodule RBNF do
|
||||||
|
|
||||||
{:seq, seq}
|
{:seq, seq}
|
||||||
end)}
|
end)}
|
||||||
}
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns {matched_text, remaining_text}
|
# Returns {matched_text, remaining_text}
|
||||||
|
|
@ -43,7 +47,7 @@ defmodule RBNF do
|
||||||
{nil, nil}
|
{nil, nil}
|
||||||
else
|
else
|
||||||
case parse(grammar, rule, buffer) do
|
case parse(grammar, rule, buffer) do
|
||||||
{nil, extra} -> {nil, nil}
|
{nil, _} -> {nil, nil}
|
||||||
{matched, rest} -> {matched, rest}
|
{matched, rest} -> {matched, rest}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -69,6 +73,59 @@ defmodule RBNF do
|
||||||
nil -> {nil, text}
|
nil -> {nil, text}
|
||||||
{matched, rest} -> {matched, rest}
|
{matched, rest} -> {matched, rest}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
{:plus, repeated} ->
|
||||||
|
case parse(grammar, repeated, text) do
|
||||||
|
{nil, _} -> {nil, text}
|
||||||
|
{matched, rest} -> star_iter(grammar, repeated, matched, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
{:paired, r1, r2} ->
|
||||||
|
{count, prefix, rest} = count_iter(grammar, r1, "", 0, text)
|
||||||
|
|
||||||
|
if count == 0 do
|
||||||
|
{nil, text}
|
||||||
|
else
|
||||||
|
new_rule = {:seq, List.duplicate(r2, count)}
|
||||||
|
|
||||||
|
case parse(grammar, new_rule, rest) do
|
||||||
|
{nil, _} -> {nil, text}
|
||||||
|
{suffix, remaining} -> {prefix <> suffix, remaining}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
{:left_sided, left, right} ->
|
||||||
|
{count, prefix, rest} = count_iter(grammar, left, "", 0, text)
|
||||||
|
|
||||||
|
if count < 2 do
|
||||||
|
# No extra lefts to match with
|
||||||
|
{nil, text}
|
||||||
|
else
|
||||||
|
new_rule = {:at_most, right, count - 1}
|
||||||
|
|
||||||
|
case parse(grammar, new_rule, rest) do
|
||||||
|
{nil, _} -> {nil, text}
|
||||||
|
{suffix, remaining} -> {prefix <> suffix, remaining}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
{:at_most, r, count} ->
|
||||||
|
new_rule = {:alt, Enum.map(count..1, &{:seq, List.duplicate(r, &1)})}
|
||||||
|
parse(grammar, new_rule, text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp star_iter(grammar, rule, prefix, text) do
|
||||||
|
case parse(grammar, rule, text) do
|
||||||
|
{nil, _} -> {prefix, text}
|
||||||
|
{matched, rest} -> star_iter(grammar, rule, prefix <> matched, rest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp count_iter(grammar, rule, prefix, count, text) do
|
||||||
|
case parse(grammar, rule, text) do
|
||||||
|
{nil, _} -> {count, prefix, text}
|
||||||
|
{matched, rest} -> count_iter(grammar, rule, prefix <> matched, count + 1, rest)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -81,18 +138,53 @@ defmodule Day19 do
|
||||||
|
|
||||||
defp test_input do
|
defp test_input do
|
||||||
"""
|
"""
|
||||||
0: 4 1 5
|
42: 9 14 | 10 1
|
||||||
1: 2 3 | 3 2
|
9: 14 27 | 1 26
|
||||||
2: 4 4 | 5 5
|
10: 23 14 | 28 1
|
||||||
3: 4 5 | 5 4
|
1: "a"
|
||||||
4: "a"
|
11: 42 31
|
||||||
5: "b"
|
5: 1 14 | 15 1
|
||||||
|
19: 14 1 | 14 14
|
||||||
|
12: 24 14 | 19 1
|
||||||
|
16: 15 1 | 14 14
|
||||||
|
31: 14 17 | 1 13
|
||||||
|
6: 14 14 | 1 14
|
||||||
|
2: 1 24 | 14 4
|
||||||
|
0: 8 11
|
||||||
|
13: 14 3 | 1 12
|
||||||
|
15: 1 | 14
|
||||||
|
17: 14 2 | 1 7
|
||||||
|
23: 25 1 | 22 14
|
||||||
|
28: 16 1
|
||||||
|
4: 1 1
|
||||||
|
20: 14 14 | 1 15
|
||||||
|
3: 5 14 | 16 1
|
||||||
|
27: 1 6 | 14 18
|
||||||
|
14: "b"
|
||||||
|
21: 14 1 | 1 14
|
||||||
|
25: 1 1 | 1 14
|
||||||
|
22: 14 14
|
||||||
|
8: 42
|
||||||
|
26: 14 22 | 1 20
|
||||||
|
18: 15 15
|
||||||
|
7: 14 5 | 1 21
|
||||||
|
24: 14 1
|
||||||
|
|
||||||
ababbb
|
abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
|
||||||
bababa
|
bbabbbbaabaabba
|
||||||
abbbab
|
babbbbaabbbbbabbbbbbaabaaabaaa
|
||||||
aaabbb
|
aaabbbbbbaaaabaababaabababbabaaabbababababaaa
|
||||||
aaaabbb
|
bbbbbbbaaaabbbbaaabbabaaa
|
||||||
|
bbbababbbbaaaaaaaabbababaaababaabab
|
||||||
|
ababaaaaaabaaab
|
||||||
|
ababaaaaabbbaba
|
||||||
|
baabbaaaabbaaaababbaababb
|
||||||
|
abbbbabbbbaaaababbbbbbaaaababb
|
||||||
|
aaaaabbaabaaaaababaa
|
||||||
|
aaaabbaaaabbaaa
|
||||||
|
aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
|
||||||
|
babaaabbbaaabaababbaabababaaab
|
||||||
|
aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -116,7 +208,33 @@ defmodule Day19 do
|
||||||
|
|
||||||
Enum.count(messages, fn msg ->
|
Enum.count(messages, fn msg ->
|
||||||
case RBNF.parse(grammar, {:ref, "0"}, msg) do
|
case RBNF.parse(grammar, {:ref, "0"}, msg) do
|
||||||
{msg, ""} -> true
|
{_, ""} -> true
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def part2 do
|
||||||
|
{rules, messages} = read_input() |> parse_input()
|
||||||
|
|
||||||
|
grammar =
|
||||||
|
RBNF.build_grammar(rules)
|
||||||
|
# 8: 42 | 42 8 = 42+
|
||||||
|
|> Map.put("8", {:plus, {:ref, "42"}})
|
||||||
|
# 11: 42 31 | 42 11 31 = same number of 42 and 31 (at least one pair)
|
||||||
|
|> Map.put(
|
||||||
|
"11",
|
||||||
|
{:paired, {:ref, "42"}, {:ref, "31"}}
|
||||||
|
)
|
||||||
|
# 0: 8 11 = 42+ (matched 42 31) = 42 42{N} 31{1,N-1} = 42{M} 31{1,M-1}
|
||||||
|
|> Map.put(
|
||||||
|
"0",
|
||||||
|
{:left_sided, {:ref, "42"}, {:ref, "31"}}
|
||||||
|
)
|
||||||
|
|
||||||
|
Enum.count(messages, fn msg ->
|
||||||
|
case RBNF.parse(grammar, {:ref, "0"}, msg) do
|
||||||
|
{_, ""} -> true
|
||||||
_ -> false
|
_ -> false
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
@ -124,3 +242,4 @@ defmodule Day19 do
|
||||||
end
|
end
|
||||||
|
|
||||||
Day19.part1() |> IO.inspect()
|
Day19.part1() |> IO.inspect()
|
||||||
|
Day19.part2() |> IO.inspect()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue