Day 10
Setup
input =
File.read!("aoc2021/day10/input.txt")
|> String.split("\n", trim: true)
|> Enum.map(&String.to_charlist/1)
lookup_table = %{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
symbol_pairs =
'[]{}()<>'
|> to_charlist()
|> Enum.chunk_every(2)
|> Enum.map(fn row ->
{Enum.at(row, 0), Enum.at(row, 1)}
end)
[{91, 93}, {123, 125}, {40, 41}, {60, 62}]
defmodule Recursion do
def is_expected_symbol(symbol_list, index, symbol_pairs, stack)
when length(symbol_list) > index do
symbol = Enum.at(symbol_list, index)
{start, pend} =
Enum.find(symbol_pairs, nil, fn pair ->
{start, pend} = pair
start == symbol or pend == symbol
end)
cond do
start == symbol ->
Recursion.is_expected_symbol(symbol_list, index + 1, symbol_pairs, stack ++ [symbol])
pend == symbol and start == Enum.at(stack, length(stack) - 1) ->
{_, newstack} = List.pop_at(stack, -1)
Recursion.is_expected_symbol(symbol_list, index + 1, symbol_pairs, newstack)
true ->
{:corrupted, symbol_list, stack, symbol}
end
end
def is_expected_symbol(symbol_list, index, _, stack) when length(symbol_list) <= index do
{:incomplete, symbol_list, stack, nil}
end
end
{:module, Recursion, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:is_expected_symbol, 4}}
Part 1
# take to_char
# if start then push
# if end then check if last push was start
# if last push was not the start we want then return the this symbol as bad
#
walked_symbols =
input
|> Enum.map(fn symbol_list ->
Recursion.is_expected_symbol(symbol_list, 0, symbol_pairs, [])
end)
walked_symbols
|> Enum.filter(fn result ->
case result do
{:corrupted, _, _, _} -> true
_ -> false
end
end)
|> Enum.reduce(0, fn result, acc ->
{_, _, _, inval_char} = result
acc + lookup_table[inval_char]
end)
311895
Part 2
points_lookup = %{
?) => 1,
?] => 2,
?} => 3,
?> => 4
}
completed_score =
walked_symbols
|> Enum.filter(fn result ->
case result do
{:incomplete, _, _, _} -> true
_ -> false
end
end)
|> Enum.map(fn row ->
{_, _, symbol_list, _} = row
symbol_list
end)
|> Enum.map(fn symbol_list ->
Enum.map(symbol_list, fn symbol ->
pair =
Enum.find(symbol_pairs, nil, fn {start, _} ->
start == symbol
end)
{_, pend} = pair
pend
end)
|> Enum.reverse()
end)
|> Enum.map(fn symbol_list ->
Enum.reduce(symbol_list, 0, fn symbol, acc ->
acc * 5 + points_lookup[symbol]
end)
end)
|> Enum.sort()
Enum.at(completed_score, length(completed_score) |> div(2))
2904180541