diff --git a/2020/ruby/day_17.rb b/2020/ruby/day_17.rb index a60de7b..72a1f90 100644 --- a/2020/ruby/day_17.rb +++ b/2020/ruby/day_17.rb @@ -1,24 +1,28 @@ -state = ARGF.read.split("\n").flat_map.with_index {|line,y| - line.chars.map.with_index {|c,x| [[0,0,y,x], c == "#"] } +DIMENSIONS = 4 +state = ARGF.read.strip.split("\n").flat_map.with_index {|line,y| + line.chars.map.with_index {|c,x| + [[x,y].fill(0, 2, DIMENSIONS-2), c == "#"] + } }.to_h -NEIGHBORS = (0...3**4).map {|n| n.digits(3) }.map {|n| (0..3).map {|x| n.fetch(x, 0) - 1 }} - [[0,0,0,0]] +NEIGHBORS = (0...3**DIMENSIONS) + .reject {|n| n == 3**DIMENSIONS / 2 } + .map {|n| n.digits(3) } + .map {|n| (0...DIMENSIONS).map {|x| n.fetch(x, 0) - 1 }} def tick(state) actives = state.select {|_,c| c }.keys - ww, zz, yy, xx = actives.transpose.map(&:minmax).map {|min,max| [min-1, max+1] } - Range.new(*ww).flat_map {|w| - Range.new(*zz).flat_map {|z| - Range.new(*yy).flat_map {|y| - Range.new(*xx).map {|x| - active_neighbors = NEIGHBORS.map {|dw,dz,dy,dx| state[[w+dw,z+dz,y+dy, x+dx]] }.count(&:itself) - wzyx = [w,z,y,x] - [ wzyx, - state[wzyx] ? (2..3).cover?(active_neighbors) : active_neighbors == 3 - ] - } - } - } + minmaxes = actives + .transpose.map(&:minmax) + .map {|min,max| (min-1..max+1).to_a } + coords = minmaxes.inject {|n,x| + n.flat_map {|nn| x.map {|xx| [nn, xx] }} + }.map(&:flatten) + coords.map {|coord| + active_neighbors = NEIGHBORS.count {|delta| state[coord.zip(delta).map {|a,b| a + b }] } + [ coord, + state[coord] ? (2..3).cover?(active_neighbors) : active_neighbors == 3 + ] }.to_h end