Day10
Setup
Mix.install(
[
{:kino, "~> 0.4.1"}
],
consolidate_protocols: false
)
input = Kino.Input.textarea("Please paste your input:")
chunks =
input
|> Kino.Input.read()
|> String.split(["\n"], trim: true)
# |> (fn parsed -> ["999999999999"] ++ parsed ++ ["999999999999"] end).()
# |> Enum.map(&String.to_charlist/1)
Part 1
defmodule Stack do
defstruct elements: []
def new, do: %Stack{}
def push(stack, element) do
%Stack{stack | elements: [element | stack.elements]}
end
def pop(%Stack{elements: []}), do: raise("Stack is empty!")
def pop(%Stack{elements: [top | rest]}) do
{top, %Stack{elements: rest}}
end
def top(%Stack{elements: [top | _rest]}) do
top
end
def top(%Stack{elements: []}) do
0
end
def elements(%Stack{elements: elements}) do
elements
end
def depth(%Stack{elements: elements}), do: length(elements)
end
{last, st} = Stack.new() |> Stack.push(1) |> Stack.push(2) |> Stack.push(2) |> Stack.pop()
# Stack.new
# start_end = %{
# '{' => '}',
# '[' => ']',
# '<' => '>',
# '(' => ')'
# }
# Map.get(start_end, '{')
Stack.top(st)
defmodule Part1 do
@start_chunk '{[(<'
@start_end %{
'{' => '}',
'[' => ']',
'<' => '>',
'(' => ')'
}
def find_bug(_chunk = [], {last_started, started_so_far}) do
# {:ok, nil}
{false, [last_started], started_so_far}
end
def find_bug(chunk, {last_started, started_so_far}) do
[char | chunk] = chunk
# IO.puts("#{chunk} #{[char]} #{[last_started]} #{inspect(started_so_far)}")
if char in @start_chunk do
find_bug(chunk, {char, Stack.push(started_so_far, char)})
else
expected = Map.get(@start_end, [last_started])
if [char] == expected do
{_, started_so_far} = Stack.pop(started_so_far)
# IO.puts("Closing #{[last_started]} remaining #{inspect(started_so_far)}")
find_bug(chunk, {Stack.top(started_so_far), started_so_far})
else
# {:bug, [last_started], [char]}
{true, [char], started_so_far}
end
end
end
end
# [chunk | _ ] = chunks
# Part1.validate_chunk(chunk, {0, Stack.new})
chunks
|> Enum.map(&String.to_charlist/1)
|> Enum.map(fn chunk -> Part1.find_bug(chunk, {0, Stack.new()}) end)
|> Enum.filter(fn {is_buggy, _bug, _incompleted} -> is_buggy end)
|> Enum.reduce(0, fn {_, bug_char, _}, score ->
case bug_char do
')' -> score + 3
']' -> score + 57
'}' -> score + 1197
'>' -> score + 25137
_ -> 99999
end
end)
Part 2
defmodule Part2 do
def score_incomplete({_, _, incompleted}) do
Stack.elements(incompleted)
|> Enum.reduce(0, fn char, score ->
case [char] do
'(' -> 5 * score + 1
'[' -> 5 * score + 2
'{' -> 5 * score + 3
'<' -> 5 * score + 4
_ -> 99999
end
end)
end
end
scores =
chunks
|> Enum.map(&String.to_charlist/1)
|> Enum.map(fn chunk -> Part1.find_bug(chunk, {0, Stack.new()}) end)
|> Enum.filter(fn {is_buggy, _bug, _incompleted} -> is_buggy == false end)
|> Enum.map(&Part2.score_incomplete/1)
|> Enum.sort()
Enum.fetch!(scores, trunc(Enum.count(scores) / 2))
Jose
defmodule Syntax do
def parse(line), do: parse(line, [])
# Opening
defp parse(<rest::binary>, stack), do: parse(rest, [?) | stack])
defp parse(<rest::binary>, stack), do: parse(rest, [?] | stack])
defp parse(<rest::binary>, stack), do: parse(rest, [?} | stack])
defp parse(<rest::binary>, stack), do: parse(rest, [?> | stack])
# Closing
defp parse(<>, [char | stack]), do: parse(rest, stack)
# Base/error cases
defp parse(<>, _stack), do: {:corrupted, char}
defp parse(<<>>, []), do: :ok
defp parse(<<>>, stack), do: {:incomplete, stack}
def test(<>) do
IO.puts(rest)
end
end
points = %{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
# Enum.sum(
for line <- chunks,
{:corrupted, char} <- [Syntax.parse(line)],
do: Map.fetch!(points, char)
# )
points = %{
?) => 1,
?] => 2,
?} => 3,
?> => 4
}
scores =
Enum.sort(
for line <- chunks,
{:incomplete, chars} <- [Syntax.parse(line)],
do: Enum.reduce(chars, 0, fn char, acc -> acc * 5 + Map.fetch!(points, char) end)
)
# Enum.fetch!(scores, div(length(scores), 2))