Day 10: Syntax Scoring
Setup
Mix.install([
{:kino, "~> 0.4.1"}
])
Input
input = Kino.Input.textarea("Input")
Stack
defmodule Stack do
defstruct list: []
def new(list \\ []) do
%__MODULE__{list: list}
end
def pop(%__MODULE__{list: [value | rest]}) do
{%__MODULE__{list: rest}, value}
end
def push(%__MODULE__{list: list}, value) do
%__MODULE__{list: [value | list]}
end
end
Part 1
defmodule Bracket do
def brackets do
%{
?( => ?),
?[ => ?],
?{ => ?},
?< => ?>
}
end
def points do
%{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
end
def feed(chars) do
Enum.reduce_while(chars, {Stack.new(), nil}, fn char, {stack, _} ->
acc = feed(stack, char)
if elem(acc, 1) == nil, do: {:cont, acc}, else: {:halt, acc}
end)
end
def feed(stack, char) do
if brackets()[char] do
{Stack.push(stack, char), nil}
else
{stack, value} = Stack.pop(stack)
{stack, if(brackets()[value] == char, do: nil, else: char)}
end
end
end
Kino.Input.read(input)
|> String.split("\n", trim: true)
|> Enum.map(&String.to_charlist/1)
|> Enum.map(&Bracket.feed/1)
|> Enum.map(&elem(&1, 1))
|> Enum.filter(& &1)
|> Enum.map(fn char -> Bracket.points()[char] end)
|> Enum.sum()
Part 2
defmodule Score do
def score(stack) do
stack.list
|> Enum.map(fn char ->
case Bracket.brackets()[char] do
?) -> 1
?] -> 2
?} -> 3
?> -> 4
end
end)
|> Enum.reduce(0, fn n, acc -> acc * 5 + n end)
end
end
Kino.Input.read(input)
|> String.split("\n", trim: true)
|> Enum.map(&String.to_charlist/1)
|> Enum.map(&Bracket.feed/1)
|> Enum.filter(&(!elem(&1, 1)))
|> Enum.map(&elem(&1, 0))
|> Enum.map(&Score.score/1)
|> Enum.sort(:asc)
|> then(fn l ->
Enum.at(l, div(length(l), 2))
end)