bjorng
Advent of Code 2021 - Day 10
This topic is about Day 10 of the Advent of Code 2021.
We have a private leaderboard (shared with users of Erlang Forums ):
https://adventofcode.com/2021/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
Most Liked
ruslandoga
I used a bit of metaprogramming to define the line processor that worked on binaries:
defp process_line(line) do
process_line(line, _stack = [])
end
for <<open, close>> <- ["[]", "()", "{}", "<>"] do
defp process_line(<<unquote(close), rest::bytes>>, [unquote(close) | stack]) do
process_line(rest, stack)
end
defp process_line(<<unquote(open), rest::bytes>>, stack) do
process_line(rest, [unquote(close) | stack])
end
end
defp process_line(<<>>, []), do: :valid
defp process_line(<<>>, stack), do: {:incomplete, stack}
defp process_line(<<char, _rest::bytes>>, _stack), do: {:corrupted, char}
mexicat
Today’s problem seemed like a good match for Elixir.
defmodule AdventOfCode.Day10 do
@chunks %{
"(" => ")",
"[" => "]",
"{" => "}",
"<" => ">"
}
def part1(input) do
input
|> parse_input()
|> Enum.map(&eval_line/1)
|> Enum.filter(&(elem(&1, 0) == :error))
|> Enum.map(fn {_, v} -> v end)
|> Enum.sum()
end
def part2(input) do
results =
input
|> parse_input()
|> Enum.map(&eval_line/1)
|> Enum.filter(&(elem(&1, 0) == :ok))
|> Enum.map(fn {_, v} -> v end)
|> Enum.sort()
middle = results |> length() |> div(2)
Enum.at(results, middle)
end
def eval_line(line, open \\ [])
def eval_line([head | tail], open) when head in ["(", "[", "{", "<"] do
eval_line(tail, [head | open])
end
def eval_line([head | tail], [open_head | open_tail]) do
if head == @chunks[open_head] do
eval_line(tail, open_tail)
else
{:error, score_error(head)}
end
end
def eval_line(_, open) do
score =
Enum.reduce(open, 0, fn char, acc ->
acc * 5 + score_ac(@chunks[char])
end)
{:ok, score}
end
def score_error(")"), do: 3
def score_error("]"), do: 57
def score_error("}"), do: 1197
def score_error(">"), do: 25137
def score_ac(")"), do: 1
def score_ac("]"), do: 2
def score_ac("}"), do: 3
def score_ac(">"), do: 4
def parse_input(input) do
input
|> String.split("\n", trim: true)
|> Enum.map(&String.codepoints/1)
end
end
ruslandoga
I think it is equivalent except that my implementation for part2 needs to be updated to score openers instead of closers (since stack contains openers for incomplete lines). I rerun the tests with these two changes and they passed.
As for your original question,
Any reason it is better to match on insertion into the stack rather than on popping off the stack?
I don’t think I had any particular reason, at the moment it just made sense to add closers to the stack.
Popular in Challenges
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









