aoc2020/day_17/second.rb

173 lines
4.1 KiB
Ruby

map = {}
input = File.readlines('./input').map.with_index do |line, i|
line.chomp.chars.each_with_index { |char, pos| map[[pos, i, 0, 0]] = char }
end
def draw_bounds(map)
x = map.keys.map { |x, _, _, _| x }
y = map.keys.map { |_, y, _, _| y }
z = map.keys.map { |_, _, z, _| z }
w = map.keys.map { |_, _, _, w| w }
[x.min - 1, x.max + 1].each do |x|
(y.min - 1..y.max + 1).each do |y|
(z.min - 1..z.max + 1).each do |z|
(w.min - 1..w.max + 1).each do |w|
map[[x, y, z, w]] = '.'
end
end
end
end
[y.min - 1, y.max + 1].each do |y|
(x.min - 1..x.max + 1).each do |x|
(z.min - 1..z.max + 1).each do |z|
(w.min - 1..w.max + 1).each do |w|
map[[x, y, z, w]] = '.'
end
end
end
end
[z.min - 1, z.max + 1].each do |z|
(y.min - 1..y.max + 1).each do |y|
(x.min - 1..x.max + 1).each do |x|
(w.min - 1..w.max + 1).each do |w|
map[[x, y, z, w]] = '.'
end
end
end
end
[w.min - 1, w.max + 1].each do |w|
(y.min - 1..y.max + 1).each do |y|
(x.min - 1..x.max + 1).each do |x|
(z.min - 1..z.max + 1).each do |z|
map[[x, y, z, w]] = '.'
end
end
end
end
map
end
def surrounding_cords(cord)
x, y, z, w = cord
cords = [
[x, y, z, w - 1],
[x, y, z, w + 1],
# boottom
[x, y, z - 1, w],
[x - 1, y - 1, z - 1, w],
[x, y - 1, z - 1, w],
[x + 1, y - 1, z - 1, w],
[x - 1, y, z - 1, w],
[x + 1, y, z - 1, w],
[x - 1, y + 1, z - 1, w],
[x, y + 1, z - 1, w],
[x + 1, y + 1, z - 1, w],
# top
[x, y, z + 1, w],
[x - 1, y - 1, z + 1, w],
[x, y - 1, z + 1, w],
[x + 1, y - 1, z + 1, w],
[x - 1, y, z + 1, w],
[x + 1, y, z + 1, w],
[x - 1, y + 1, z + 1, w],
[x, y + 1, z + 1, w],
[x + 1, y + 1, z + 1, w],
# middle
[x - 1, y - 1, z, w],
[x, y - 1, z, w],
[x + 1, y - 1, z, w],
[x - 1, y, z, w],
[x + 1, y, z, w],
[x - 1, y + 1, z, w],
[x, y + 1, z, w],
[x + 1, y + 1, z, w],
[x, y, z - 1, w - 1],
[x - 1, y - 1, z - 1, w - 1],
[x, y - 1, z - 1, w - 1],
[x + 1, y - 1, z - 1, w - 1],
[x - 1, y, z - 1, w - 1],
[x + 1, y, z - 1, w - 1],
[x - 1, y + 1, z - 1, w - 1],
[x, y + 1, z - 1, w - 1],
[x + 1, y + 1, z - 1, w - 1],
# top
[x, y, z + 1, w - 1],
[x - 1, y - 1, z + 1, w - 1],
[x, y - 1, z + 1, w - 1],
[x + 1, y - 1, z + 1, w - 1],
[x - 1, y, z + 1, w - 1],
[x + 1, y, z + 1, w - 1],
[x - 1, y + 1, z + 1, w - 1],
[x, y + 1, z + 1, w - 1],
[x + 1, y + 1, z + 1, w - 1],
# middle
[x - 1, y - 1, z, w - 1],
[x, y - 1, z, w - 1],
[x + 1, y - 1, z, w - 1],
[x - 1, y, z, w - 1],
[x + 1, y, z, w - 1],
[x - 1, y + 1, z, w - 1],
[x, y + 1, z, w - 1],
[x + 1, y + 1, z, w - 1],
[x, y, z - 1, w + 1],
[x - 1, y - 1, z - 1, w + 1],
[x, y - 1, z - 1, w + 1],
[x + 1, y - 1, z - 1, w + 1],
[x - 1, y, z - 1, w + 1],
[x + 1, y, z - 1, w + 1],
[x - 1, y + 1, z - 1, w + 1],
[x, y + 1, z - 1, w + 1],
[x + 1, y + 1, z - 1, w + 1],
# top
[x, y, z + 1, w + 1],
[x - 1, y - 1, z + 1, w + 1],
[x, y - 1, z + 1, w + 1],
[x + 1, y - 1, z + 1, w + 1],
[x - 1, y, z + 1, w + 1],
[x + 1, y, z + 1, w + 1],
[x - 1, y + 1, z + 1, w + 1],
[x, y + 1, z + 1, w + 1],
[x + 1, y + 1, z + 1, w + 1],
# middle
[x - 1, y - 1, z, w + 1],
[x, y - 1, z, w + 1],
[x + 1, y - 1, z, w + 1],
[x - 1, y, z, w + 1],
[x + 1, y, z, w + 1],
[x - 1, y + 1, z, w + 1],
[x, y + 1, z, w + 1],
[x + 1, y + 1, z, w + 1]
]
end
def cycle(map)
new_map = {}
map.each do |cord, _state|
neighbours_active = surrounding_cords(cord).map { |cord| map[cord] == '#' }.count(true)
if map[cord] == '#' && (2..3).include?(neighbours_active) ||
map[cord] == '.' && neighbours_active == 3
new_map[cord] = '#'; next
else
new_map[cord] = '.'
end
end
new_map
end
6.times do
map = draw_bounds(map)
map = cycle(map)
end
puts map.values.count('#')