Advent of Code 2021 day 10
Setup
Mix.install([
{:kino, "~> 0.4.1"}
])
input = Kino.Input.textarea("Please paste your input:")
lines =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
Part 1
defmodule Day10 do
@pair %{
?] => ?[,
?} => ?{,
?> => ?<,
?) => ?(
}
@points %{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
def parse(line) do
Enum.reduce_while(line, [], fn next, opens ->
cond do
next in Map.values(@pair) ->
{:cont, [next | opens]}
next in Map.keys(@pair) ->
[prev | rest] = opens
if prev == Map.get(@pair, next) do
{:cont, rest}
else
{:halt, {prev, next}}
end
end
end)
end
def point(char) do
Map.get(@points, char)
end
end
lines
|> Enum.map(&String.to_charlist/1)
|> Enum.map(&Day10.parse/1)
|> Enum.filter(&is_tuple/1)
|> Enum.map(&elem(&1, 1))
|> Enum.map(&Day10.point/1)
|> Enum.sum()
Part 2
defmodule Day10Part2 do
@points %{
?( => 1,
?[ => 2,
?{ => 3,
?< => 4
}
def calc(line) do
Enum.reduce(line, 0, &next/2)
end
defp next(char, score) do
score * 5 + Map.get(@points, char)
end
end
incompletes =
lines
|> Enum.map(&String.to_charlist/1)
|> Enum.map(&Day10.parse/1)
|> Enum.filter(&is_list/1)
incompletes
|> Enum.map(&Day10Part2.calc/1)
|> Enum.sort()
|> Enum.at(incompletes |> length |> then(&div(&1, 2)))
José’s parser
defmodule Syntax do
def parse(line), do: parse(line, [])
# opening
def parse(<rest::binary>, stack), do: parse(rest, [?) | stack])
def parse(<rest::binary>, stack), do: parse(rest, [?] | stack])
def parse(<rest::binary>, stack), do: parse(rest, [?} | stack])
def parse(<rest::binary>, stack), do: parse(rest, [?> | stack])
# Closing (correctly)
def parse(<>, [char | stack]), do: parse(rest, stack)
# Base/error cases
def parse(<>, _stack), do: {:corrupted, char}
def parse(<<>>, []), do: :ok
def parse(<<>>, stack), do: {:incomplete, stack}
end
Part 1
points = %{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
for line <- lines,
{:corrupted, char} <- [Syntax.parse(line)] do
Map.fetch!(points, char)
end
|> Enum.sum()
Part 2
points = %{
?) => 1,
?] => 2,
?} => 3,
?> => 4
}
scores =
for line <- lines,
{:incomplete, chars} <- [Syntax.parse(line)] do
Enum.reduce(chars, 0, fn char, acc -> acc * 5 + Map.fetch!(points, char) end)
end
|> Enum.sort()
scores
|> Enum.fetch!(scores |> length |> then(&div(&1, 2)))