Skip to content

Instantly share code, notes, and snippets.

@sarahzrf
Created December 11, 2021 05:51
Show Gist options
  • Save sarahzrf/fcb60e94fcc6e7823d298caf096c1ab5 to your computer and use it in GitHub Desktop.
Save sarahzrf/fcb60e94fcc6e7823d298caf096c1ab5 to your computer and use it in GitHub Desktop.
require 'set'
class Octopus
def initialize(cave, x, y)
@cave = cave
@x = x
@y = y
end
attr_reader :x, :y
def energy
@cave.energy_at(x, y)
end
def energy=(n)
@cave.set_energy_at(x, y, n)
end
def flashed?
@cave.flashed_at?(x, y)
end
def flashed=(b)
@cave.set_flashed_at(x, y, b)
end
def neighbors
@cave.neighbors_at(x, y)
end
end
class Cave
def initialize(energies)
@energies = energies
@flashed = energies.map {|row| row.map {false}}
@height = energies.length
@width = energies[0].length
@to_flash = Set.new
@total_flashes = 0
end
attr_reader :width, :height, :total_flashes
def in_bounds?(x, y)
x >= 0 && y >= 0 && x < width && y < height
end
def [](x, y)
Octopus.new(self, x, y) if in_bounds?(x, y)
end
def energy_at(x, y)
@energies[y][x]
end
def set_energy_at(x, y, n)
@energies[y][x] = n
@to_flash << [x, y] if n > 9 and not flashed_at?(x, y)
end
def flashed_at?(x, y)
@flashed[y][x]
end
def set_flashed_at(x, y, b)
@flashed[y][x] = b
end
Offsets = [
[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]
]
def neighbors_at(x, y)
Offsets.map {|dx, dy| self[x + dx, y + dy]}.compact
end
def start_step
(0...height).each do |y|
(0...width).each do |x|
self[x, y].energy += 1
end
end
end
def step_done?
@to_flash.empty?
end
def do_flashes
old = @to_flash
old.each do |x, y|
self[x, y].flashed = true
@total_flashes += 1
end
@to_flash = Set.new
old.each do |x, y|
self[x, y].neighbors.each do |n|
n.energy += 1
end
end
end
def reset_flashes
@flashed.each {|row| row.map! {false}}
end
def finish_step
@flashed.each_with_index do |row, y|
row.each_with_index do |fl, x|
self[x, y].energy = 0 if fl
end
end
reset_flashes
end
def step
start_step
do_flashes until step_done?
all_flashed = @flashed.all? {|row| row.all?}
finish_step
all_flashed
end
end
cave = Cave.new($<.map {|l| l.chomp.chars.map(&:to_i)})
n = 0
loop do
n += 1
if cave.step
print n
break
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment