Skip to content

Instantly share code, notes, and snippets.

@amiratak88
Created December 5, 2021 04:27
Show Gist options
  • Save amiratak88/02088a980d6331a665ea18bb5c79064b to your computer and use it in GitHub Desktop.
Save amiratak88/02088a980d6331a665ea18bb5c79064b to your computer and use it in GitHub Desktop.
Advent 2021 - Day 4
class Board
class Cell
attr_reader :row, :column, :value
def initialize(row:, column:, value:)
@row = row
@column = column
@value = value
@marked = false
end
def mark
self.marked = true
end
def marked?
@marked
end
private
attr_writer :marked
end
attr_reader :rows
def initialize(data)
@rows = data.each_with_index.map do |row, i|
row.each_with_index.map do |value, j|
Cell.new(row: i, column: j, value: value)
end
end
end
def columns
rows.transpose
end
def vectors
rows + columns
end
def cells
rows.flatten
end
def on_draw(value)
cells.each { |c| c.mark if c.value == value }
end
def bingo?
vectors.any? { |v| v.all?(&:marked?) }
end
def unmarked_cells
cells.reject(&:marked?)
end
end
def parse_input
input = File.read('input.txt')
numbers_to_draw, *boards = *input.split("\n\n")
numbers_to_draw = numbers_to_draw.split(',').map(&:to_i)
boards = boards
.map { |b| b.lines.map { |l| l.strip.split(/ +/).map(&:to_i) } }
.map { |b| Board.new(b) }
return [numbers_to_draw, boards]
end
def part_one
numbers_to_draw, boards = *parse_input
numbers_to_draw.each do |drawn_number|
boards.each do |board|
board.on_draw(drawn_number)
if board.bingo?
return board.unmarked_cells.map(&:value).sum * drawn_number
end
end
end
end
def part_two
part_two_helper(*parse_input)
end
def part_two_helper(numbers_to_draw, boards)
raise 'impossible' if numbers_to_draw.empty? || boards.empty?
boards.each { |b| b.on_draw(numbers_to_draw.first) }
if boards.all?(&:bingo?)
return boards.last.unmarked_cells.map(&:value).sum * numbers_to_draw.first
end
part_two_helper(numbers_to_draw[1..], boards.reject(&:bingo?))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment