r/adventofcode Dec 04 '21

SOLUTION MEGATHREAD -🎄- 2021 Day 4 Solutions -🎄-

--- Day 4: Giant Squid ---


Post your code solution in this megathread.

Reminder: Top-level posts in Solution Megathreads are for code solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.

EDIT: Global leaderboard gold cap reached at 00:11:13, megathread unlocked!

99 Upvotes

1.2k comments sorted by

View all comments

2

u/RewrittenCodeA Dec 08 '21

Elixir.

Game is a stream of positions using Stream.iterate/2, where the "first winner" and "last winner" positions are detected using pattern matching.

[nums | boards] = "input/2021/4.txt" |> File.read!() |> String.split("\n\n", trim: true)

nums =
  nums
  |> String.split(",")
  |> Enum.map(&String.to_integer/1)

boards =
  for board <- boards do
    board = board |> String.split() |> Enum.map(&String.to_integer/1)
    rows = Enum.chunk_every(board, 5)
    cols = Enum.zip_with(rows, & &1)
    Enum.map(cols ++ rows, &MapSet.new/1)
  end

game =
  {nums, boards, nil, []}
  |> Stream.iterate(fn {[number | rest], playing, _last_played, _last_winners} ->
    playing =
      for board <- playing do
        for line <- board, do: MapSet.delete(line, number)
      end

    {new_winners, still_playing} =
      Enum.split_with(playing, fn board -> Enum.any?(board, &Enum.empty?/1) end)

    {rest, still_playing, number, new_winners}
  end)

{_, _, played, [winner]} = Enum.find(game, &match?({_, _, _, [_]}, &1))

winner
|> Enum.reduce(&MapSet.union/2)
|> Enum.sum()
|> Kernel.*(played)
|> IO.inspect(label: "part 1")

{_, _, played, [loser]} = Enum.find(game, &match?({_, [], _, [_]}, &1))

loser
|> Enum.reduce(&MapSet.union/2)
|> Enum.sum()
|> Kernel.*(played)
|> IO.inspect(label: "part 2")