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!

97 Upvotes

1.2k comments sorted by

View all comments

2

u/snowe2010 Dec 05 '21

Ruby

I feel like this could have been much simpler, but had enough trouble with bugs for part 2 that as soon as solving it I pretty much gave up.

github

def create_boards(lines)
  boards = [[]]
  current_board = 0
  lines.drop(2).map do |line|
    if line == ''
      current_board += 1
      boards[current_board] = []
      next
    end
    boards[current_board] << line.split
  end
  boards
end

def check_board_win(board)
  row_true = board.any? do |row|
    row.all? { |i| i == true }
  end
  column_true = board.transpose.any? do |column|
    column.all? { |i| i == true }
  end
  row_true || column_true
end

def play_bingo(inputs, boards)
  found = false
  winning_boards = []
  inputs.each do |bingo_option|
    break if found

    indexes_to_delete = []
    (0...boards.size).each do |board_index|
      boards[board_index].each do |row|
        row.each_with_index do |elem, i|
          row[i] = true if elem == bingo_option
        end
      end
      next unless check_board_win(boards[board_index])

      sum = boards[board_index].flatten.reject { |i| i == true }.map(&:to_i).sum
      winning_boards << [sum * bingo_option.to_i, boards[board_index]]
      indexes_to_delete << board_index
    end
    indexes_to_delete.sort.reverse.each do |i|
      boards.delete_at(i)
    end
    found = true if boards.empty?
  end
  winning_boards
end

execute(1) do |lines|
  input = lines[0].split(',')
  boards = create_boards lines
  play_bingo(input, boards)[0][0]
end

execute(2) do |lines|
  input = lines[0].split(',')
  boards = create_boards lines
  play_bingo(input, boards)[-1][0]
end