100 lines
2.0 KiB
Ruby
100 lines
2.0 KiB
Ruby
input = File.readlines('./input').map(&:chomp)
|
|
|
|
class Tile
|
|
attr_accessor :x, :y, :z, :black, :white
|
|
|
|
NEIGHBOURS = {
|
|
'nw' => [0, +1, -1],
|
|
'ne' => [1, 0, -1],
|
|
'sw' => [-1, 0, +1],
|
|
'se' => [0, -1, +1],
|
|
'e' => [+1, -1, 0],
|
|
'w' => [-1, 1, 0]
|
|
}
|
|
|
|
def initialize(x,y,z)
|
|
@x, @y, @z = x, y, z
|
|
@black = false
|
|
@white = true
|
|
end
|
|
|
|
def walk_and_flip(dir)
|
|
if dir.empty?
|
|
@black, @white = @white, @black
|
|
return
|
|
end
|
|
move = if %w[se sw ne nw].include? dir[0,2]
|
|
move = dir[0,2]
|
|
dir.gsub!(/^../, '')
|
|
move
|
|
else
|
|
move = dir[0,1]
|
|
dir.gsub!(/^./, '')
|
|
move
|
|
end
|
|
|
|
offset = NEIGHBOURS[move]
|
|
next_coord = [@x, @y, @z].map.with_index {|c,i| c+offset[i]}
|
|
tile = if $tiles[next_coord]
|
|
$tiles[next_coord]
|
|
else
|
|
tile = Tile.new(*next_coord)
|
|
$tiles[next_coord] = tile
|
|
tile
|
|
end
|
|
tile.walk_and_flip(dir)
|
|
end
|
|
|
|
def next_day
|
|
neigh = neighbours
|
|
new_tile = self.dup
|
|
if @black && [0,3,4,5,6].include?(neigh.count(&:black))
|
|
new_tile.black = false
|
|
new_tile.white = true
|
|
elsif @white && neigh.count(&:black) == 2
|
|
new_tile.black = true
|
|
new_tile.white = false
|
|
end
|
|
new_tile
|
|
end
|
|
|
|
def neighbours
|
|
NEIGHBOURS.values.map do |offset|
|
|
next_coord = [@x, @y, @z].map.with_index {|c,i| c+offset[i]}
|
|
tile = if $tiles[next_coord]
|
|
$tiles[next_coord]
|
|
else
|
|
Tile.new(*next_coord)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
def draw_bounds
|
|
$tiles.values.each do |t|
|
|
t.neighbours.each do |n|
|
|
$tiles[[n.x, n.y, n.z]] = n
|
|
end
|
|
end
|
|
end
|
|
|
|
$tiles = {[0,0,0] => Tile.new(0,0,0)}
|
|
|
|
input.each do |dir|
|
|
$tiles[[0,0,0]].walk_and_flip(dir)
|
|
end
|
|
puts $tiles.values.count(&:black)
|
|
|
|
$new_tiles = {}
|
|
|
|
100.times do |i|
|
|
draw_bounds
|
|
$tiles.each do |coord, tile|
|
|
$new_tiles[coord] = tile.next_day
|
|
end
|
|
$tiles = $new_tiles
|
|
$new_tiles = {}
|
|
end
|
|
puts $tiles.values.count(&:black)
|