Created
December 11, 2021 05:51
-
-
Save sarahzrf/fcb60e94fcc6e7823d298caf096c1ab5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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