Skip to content

Instantly share code, notes, and snippets.

@johngian
Created December 5, 2021 21:47
Show Gist options
  • Save johngian/6ecb8359d02485dcae6ceb7b13cd9d82 to your computer and use it in GitHub Desktop.
Save johngian/6ecb8359d02485dcae6ceb7b13cd9d82 to your computer and use it in GitHub Desktop.
Advent of code 2021 - day 4 - part 2 - solution
defmodule Bingo do
def parseline(line) do
line
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
end
def parseboard(board) do
Enum.map(board, &parseline/1)
end
def read(path) do
input = File.read!(path)
input = String.split(input, "\n")
[numbers | boards] = input
numbers = numbers |> String.split(",") |> Enum.map(&String.to_integer/1)
boards =
boards
|> Enum.chunk_by(fn x -> x != "" end)
|> Enum.reject(fn x -> x == [""] end)
|> Enum.map(&parseboard/1)
%{boards: boards, numbers: numbers}
end
def checkboard(board, history) do
vertical = board
horizontal =
board
|> Enum.map(fn line -> MapSet.subset?(MapSet.new(line), history) end)
|> Enum.find_index(fn line -> line == true end)
vertical =
vertical
|> Enum.zip()
|> Enum.map(&Tuple.to_list(&1))
|> Enum.map(fn line -> MapSet.subset?(MapSet.new(line), history) end)
|> Enum.find_index(fn line -> line == true end)
{horizontal, vertical}
end
def checkboards(history, boards) do
history = MapSet.new(history)
boards
|> Enum.map(fn board -> checkboard(board, history) end)
|> Enum.find_index(fn result -> result != {nil, nil} end)
end
def count(boards, winner, history) do
board = boards |> Enum.at(winner)
latest = history |> Enum.at(-1)
history = MapSet.new(history)
s =
board
|> Enum.map(fn line -> Enum.filter(line, fn x -> !MapSet.member?(history, x) end) end)
|> Enum.map(&Enum.sum/1)
|> Enum.sum()
result = s * latest
{board, result, latest, history}
end
def play(history, future, boards, winner) when future == [] do
"done"
end
def cleanup(boards, nil) do
boards
end
def cleanup(boards, winner) do
boards = List.delete_at(boards, winner)
end
def play(history, future, boards, winner) do
winner = checkboards(history, boards)
if winner != nil do
IO.inspect(count(boards, winner, history))
boards = cleanup(boards, winner)
play(history,future, boards, winner)
else
[next | future] = future
curr = history ++ [next]
boards = cleanup(boards, winner)
play(curr, future, boards, winner)
end
end
def run() do
input = read("./input/day4.txt")
{history, future} = Enum.split(input[:numbers], 4)
play(history, future, input[:boards], nil)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment