Sander Land wrote:
> de-obfuscated it a bit to understand it :)

Here's what I used:

o = "#"
f = " "
c = nil    # copy of b
# u = nil  # alias for nil
# b        # main grid

b = ([nil] * 20).map { (0..20).map { (rand < 0.3) ? o : f } }

$> << "\e[2J"  # this line is not strictly necessary (11 bytes)

until c == b
  $> << "\e[H" << b.map {|x| x * f } * "\n"
  c = b.map {|x| x.dup }
  20.times {|i|          # -4: b.each_index => 20.times
    20.times {|e|        # -7: b[i].each_index => 20.times
      n = (
        q, z = -1..1, []
        q.map {|x| q.map {|y| z << [x, y] } }
        (z - [[0, 0]]).map {|x|                      # -1: -= => -
          c[i + x[0]][e + x[1]] rescue nil
        } - [f, nil]
      ).size
      b[i][e]=(n==2?b[i][e]:n==3?o:f)           # -23
    }
  }
  sleep 0.1
end

> some ways i found to decrease the size:
> remove "-[[0,0]]" and change the condition to (n>4||n<3) to account for

Good one. Can still do that to my result. -8

> the +1
> "rescue f" over "rescue ()", and -[f] over -[f,nil]

-2

> possible bug here though:
> c[i+x[0]][e+x[1]]
> take  i=e=0 and x=[-1,-1],  this results in c[-1][-1] which is
> bottom-right, i don't think this is what you want (unless i
> misunderstood the 'game').

It's sort of a feature - it's half a wrap-rule. Here's both halves and
minus another character:

< c[i+x[0]][e+x[1]] rescue f
> c[(i+x[0])%s][(e+x[1])%s]

That's assuming you put s=20 back in, which costs you that character
right back again, but is worth it, because that's now 6 esses.

Cheers,
Dave