Aetherus
Advent of Code 2021 - Day 4
This topic is about the Advent of Code 2021 - Day 4.
Thanks to @bjorng , we now have a new Private Leaderboard.
The entry code is:
370884-a6a71927
Most Liked
code-shoily
It’s starting to get difficult already, at least from the perspective of Elixir. It’s difficult to come up with a solution fast that is mutation and early return friendly on a matrix like data.
Aetherus
I usually use %{{x, y} => val} to represent a matrix, but for today’s challenge, I recognized that I need to look up {x, y} by values, so I swapped the keys and the values.
hauleth
Again, LiveBook:
Day 4
Input
This time it is a little bit more convoluted, as there are 2 parts of the input.
Fortunately we can easily disect the parts via pattern matching.
Technically the conversion to the numbers is not needed, but it does no harm
and provides additional layer of safety against some whitespace characters left there
and here.
The Day4.win/2 function is manually unrolled, as it is easier to write than some
random jumping in the list.
[numbers | bingos] =
File.read!("day4.txt")
|> String.split("\n\n", trim: true)
numbers =
numbers
|> String.trim()
|> String.split(",")
|> Enum.map(&String.to_integer/1)
bingos =
bingos
|> Enum.map(fn bingo ->
bingo
|> String.split(~r/\s+/, trim: true)
|> Enum.map(&String.to_integer/1)
end)
defmodule Day4 do
def win(
[
a1, a2, a3, a4, a5,
b1, b2, b3, b4, b5,
c1, c2, c3, c4, c5,
d1, d2, d3, d4, d5,
e1, e2, e3, e4, e5
],
nums
) do
# Rows
all_in([a1, a2, a3, a4, a5], nums) or
all_in([b1, b3, b3, b4, b5], nums) or
all_in([c1, c2, c3, c4, c5], nums) or
all_in([d1, d2, d3, d4, d5], nums) or
all_in([e1, e2, e3, e4, e5], nums) or
# Columns
all_in([a1, b1, c1, d1, e1], nums) or
all_in([a2, b2, c2, d2, e2], nums) or
all_in([a3, b3, c3, d3, e3], nums) or
all_in([a4, b4, c4, d4, e4], nums) or
all_in([a5, b5, c5, d5, e5], nums) or
# Diagonals
all_in([a1, b2, c3, d4, e5], nums) or
all_in([a5, b4, c3, d2, e1], nums)
end
def not_matched(bingo, nums) do
Enum.reject(bingo, &(&1 in nums))
end
defp all_in(list, nums) do
Enum.all?(list, &(&1 in nums))
end
end
Task 1
We simply traverse the numbers list aggregating the numbers (order doesn’t really matter,
here we aggregate them in reverse order to speedup the code). When we have enough numbers
that any of the bingos is winning one, then we halt the reduction and return computed
result.
numbers
|> Enum.reduce_while([], fn elem, acc ->
matches = [elem | acc]
case Enum.find(bingos, &Day4.win(&1, matches)) do
nil -> {:cont, matches}
bingo -> {:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
end
end)
Task 2
numbers
|> Enum.reduce_while({bingos, []}, fn elem, {bingos, acc} ->
matches = [elem | acc]
case bingos do
[bingo] ->
if Day4.win(bingo, matches) do
{:halt, Enum.sum(Day4.not_matched(bingo, matches)) * elem}
else
{:cont, {bingos, matches}}
end
_ ->
{:cont, {Enum.reject(bingos, &Day4.win(&1, matches)), matches}}
end
end)
Whole project can be watched there - https://github.com/hauleth/advent-of-code/blob/master/2021/solutions.livemd
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









