Advent of Code 2021 - Day 10
Mix.install([
{:kino, "~> 0.6.1"}
])
Instructions
https://adventofcode.com/2021/day/10
Test Input
test_input = """
[({(<(())[]>[[{[]{<()<>>
[(()[<>])]({[<{<<[]>>(
{([(<{}[<>[]}>{[]{[(<()>
(((({<>}<{<{<>}{[]{[]{}
[[<[([]))<([[{}[[()]]]
[{[{({}]{}}([{[{{{}}([]
{<[[]]>}<{[{[{[]{()[[[]
[<(<(<(<{}))><([]([]()
<{([([[(<>()){}]>(<<{{
<{([{{}}[<[[[<>{}]]]>[]]
"""
Puzzle Input
Paste your own input from Advent of Code or copy from sdball 2021 Advent of Code Day 10 input
puzzle_input = Kino.Input.textarea("Please paste your Day 10 puzzle input:")
puzzle_input = Kino.Input.read(puzzle_input)
Parsing
test_input = String.split(test_input, "\n", trim: true) |> Enum.map(&to_charlist/1)
puzzle_input = String.split(puzzle_input, "\n", trim: true) |> Enum.map(&to_charlist/1)
Part 1 - Prep
Huge thanks to José for teaching us how to write a basic parser!
I thrashed around with pieces of this approach using bitstrings and a stack like you can see below; but never quite got it all together until I saw José's example.
defmodule Parser do
def parse(line) do
parse(line, [])
end
def parse(_line = [], _stack = []), do: :ok
def parse(_line = [], stack) when length(stack) > 0, do: {:incomplete, stack}
def parse([char | line], [char | stack]), do: parse(line, stack)
def parse([char | line], stack) do
# IO.inspect(char, label: "char")
# IO.inspect(line, label: "line")
# IO.inspect(stack, label: "stack")
case char do
?( -> parse(line, [?) | stack])
?{ -> parse(line, [?} | stack])
?[ -> parse(line, [?] | stack])
?< -> parse(line, [?> | stack])
char -> {:corrupted, char}
end
end
def score_corrupted(corrupted) do
points = %{
?) => 3,
?] => 57,
?} => 1197,
?> => 25137
}
corrupted
|> Enum.reduce(0, fn char, score ->
score + points[char]
end)
end
def score_incomplete_fixes(fixes) do
points = %{
?) => 1,
?] => 2,
?} => 3,
?> => 4
}
fixes
|> Enum.map(fn fix ->
Enum.reduce(fix, 0, fn char, score ->
score * 5 + points[char]
end)
end)
|> Enum.sort()
|> Enum.at(floor(length(fixes) / 2))
end
end
Parser.parse('')
Parser.parse('(((})))')
Parser.parse('(')
Parser.parse('()')
Parser.parse('((((')
Part 1 - Test Input
test_input
|> Enum.reduce([], fn line, corrupted ->
case Parser.parse(line) do
{:corrupted, char} -> [char | corrupted]
_ -> corrupted
end
end)
|> Parser.score_corrupted()
Part 1 - Puzzle Input
puzzle_input
|> Enum.reduce([], fn line, corrupted ->
case Parser.parse(line) do
{:corrupted, char} -> [char | corrupted]
_ -> corrupted
end
end)
|> Parser.score_corrupted()
Part 2 - Test Input
test_input
|> Enum.reduce([], fn line, all_fixes ->
case Parser.parse(line) do
{:incomplete, line_fixes} -> [line_fixes | all_fixes]
_ -> all_fixes
end
end)
|> Parser.score_incomplete_fixes()
Part 2 - Puzzle Input
puzzle_input
|> Enum.reduce([], fn line, all_fixes ->
case Parser.parse(line) do
{:incomplete, line_fixes} -> [line_fixes | all_fixes]
_ -> all_fixes
end
end)
|> Parser.score_incomplete_fixes()