{{
  : $, ( $- ) withLength [ @+ , ] times @ , ;
  create this   ".###.##.#.#.#.#..#.." $,
  create next   this getLength allot
  create group  "..." $,
  variable neighbours

  : reset                  0 !neighbours ;
  : hasNeighbour?          @ '# = [ neighbours ++ ] ifTrue ;
  : countNeighboursOnEdge  '# = [ 1 ] [ 0 ] if !neighbours ;
  : flip                   dup this + @ '# = [ '. ] [ '# ] if ;
  : extract                dup this + 1- group 3 copy ;

  : count
    ( left   ) [  0 = ] [ @this        countNeighboursOnEdge ] when
    ( right  ) [ 19 = ] [  this 19 + @ countNeighboursOnEdge ] when
    ( middle ) reset extract group dup 2 + 2hasNeighbour? ;

  : process
    reset count @neighbours
    [ 0 = ] [ drop dup next + '. swap !       ] when
    [ 1 = ] [ drop dup this + @ over next + ! ] when
    [ 2 = ] [ drop flip over next + !         ] when
    drop ;

  : generation
    0 this getLength
    [ process 1+ ] times drop
    next this withLength copy ;
---reveal---
  : generations
    cr 0 swap [ [ this swap "%d %s\n" puts ] sip generation 1+ ] times drop ;
}}
1 2 3
10 generations
 5 generations
.s

