# Conway's Life de-golfed

**URL:** <https://www.ruby-forum.com/t/conways-life-de-golfed/60485>\
**Category:** Ruby\
**Created:** [May 14, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485 "2006-05-14T17:15:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 14, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/1 "2006-05-14T17:15:24Z")

</div>

I took some golfed code from a discussion here little while back (  
[http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums%5B%5D=4](http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums%5B%5D=4)  
) and tried my hand at de-golfing and re-working it a bit to make it  
readable.

There are some things here that are a little clumsy, I think. I’m  
wondering if there are other things that I might do to it to make it  
even more readable. Any ideas?

Cell\_Set, Cell\_Clear = “#”, " "  
Line\_Range = 0…20  
before = Line\_Range.map {Line\_Range.map {(rand\<0.7) ? Cell\_Set :  
Cell\_Clear}}

Neighbors = []  
(-1…1).map do |x|  
(-1…1).map do |y|  
Neighbors \<\< [x,y] unless x==0 && y==0  
end  
end

puts “\e[2J” # clear screen  
save = nil  
until save == before do  
puts “\e[H” # go ‘home’  
puts before.map {|x| x.join(" ")} \* “\n”  
save = before.map {|x| x.dup}  
before =Line\_Range.map do |x|  
Line\_Range.map do |y|  
count = (Neighbors.map do |n|  
dx, dy = x+n[0], y+n[1]  
if Line\_Range===dx and Line\_Range===dy  
before[dx][dy]  
else  
Cell\_Clear  
end  
end - [Cell\_Clear, nil]).size  
count==2 ? before[x][y] : (count==3 ? Cell\_Set :  
Cell\_Clear)  
end  
end  
sleep 0.1  
end

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 14, 2006, 8:30pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/2 "2006-05-14T20:30:44Z")

</div>

Thanks alot Mike, I was the one who started that thread, and wrote most  
of  
the basic code.  
Even though I wrote it, I couldn’t deobfuscate it afterwards! Is it ok  
if I  
pop this on my site?  
[http://code.eachmapinject.com/game\_of\_life\_golf.rb](http://code.eachmapinject.com/game_of_life_golf.rb)

j`ey  
[http://www.eachmapinject.com](http://www.eachmapinject.com)

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 15, 2006, 9:24am UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/3 "2006-05-15T09:24:11Z")

</div>

On 5/14/06, Mike N. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I took some golfed code from a discussion here little while back (  
> [Search results for '' - Ruby-Forum](http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums%5B%5D=4)  
> ) and tried my hand at de-golfing and re-working it a bit to make it  
> readable.
> 
> There are some things here that are a little clumsy, I think. I’m  
> wondering if there are other things that I might do to it to make it  
> even more readable. Any ideas?

I made a game of life example some time ago, for  
an online ruby book (in danish):  
[http://aeditor.rubyforge.org/book/refining.html](http://aeditor.rubyforge.org/book/refining.html)

–  
Simon S.

module GameOfLife  
def determine\_destiny(alive, count)  
unless alive  
return (count == 3)  
end  
(count == 2) or (count == 3)  
end  
def get(cells, y, x)  
return 0 if x \< 0 or y \< 0  
return 0 if y \>= cells.size  
row = cells[y]  
return 0 if x \>= row.size  
row[x]  
end  
def count\_neighbours(cells, x, y)  
n = 0  
n += get(cells, y-1, x-1)  
n += get(cells, y-1, x)  
n += get(cells, y-1, x+1)  
n += get(cells, y, x-1)  
n += get(cells, y, x+1)  
n += get(cells, y+1, x-1)  
n += get(cells, y+1, x)  
n += get(cells, y+1, x+1)  
n  
end  
def lifecycle(cells)  
y = 0  
next\_cells = cells.map do |row|  
x = 0  
next\_row = row.map do |cell|  
n = count\_neighbours(cells, x, y)  
x += 1  
determine\_destiny((cell != 0), n) ? 1 : 0  
end  
y += 1  
next\_row  
end  
next\_cells  
end  
end

if $0 == **FILE**  
puts “lets play a game”  
class Game  
include GameOfLife  
def initialize  
@cells = [  
[0, 0, 0, 0, 0, 0],  
[0, 0, 0, 0, 0, 0],  
[0, 0, 1, 1, 1, 0],  
[0, 1, 1, 1, 0, 0],  
[0, 0, 0, 0, 0, 0],  
[0, 0, 0, 0, 0, 0]  
]  
end  
def next  
@cells = lifecycle(@cells)  
end  
def inspect  
rows = @cells.map do |row|  
row.join(" “)  
end  
rows.join(”\n")  
end  
end  
game = Game.new  
loop do  
p game  
gets  
game.next  
end  
end

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 15, 2006, 6:27pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/4 "2006-05-15T18:27:03Z")

</div>

Mike N. wrote:

> I took some golfed code from a discussion here little while back (  
> [Search results for '' - Ruby-Forum](http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums%5B%5D=4)  
> ) and tried my hand at de-golfing and re-working it a bit to make it  
> readable.

What version did you deobfuscate?

I have here the version on J`ey’s site, and then a three-line version of  
mine.

I used these clarification methods:

- add whitespace
- add comments
- rename variables
- translate conditional tri-graphs (foo?bar:baz) to if blocks

Cheers,  
Dave

> #############################################################################
> 
> # [http://en.wikipedia.org/wiki/Conway's\_Game\_of\_Life](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
> 
> # removed\_email\_address@domain.invalid
> 
> # j`ey (with thanks to Florian G. and Dave B.)
> 
> # 305 characters
> 
> #############################################################################  
> s,o,f,c,u=20,“#”," “;b=(z=0…s).map{z.map{(rand\<0.3)?o:f}};$\>\<\<”\e[2J";until  
> c==b;$\>\<\<“\e[H”\<\<b.map{|x|x\*" “}\*”\n";c=b.map{|z|z.dup};s.times{|i|s.times{|  
> e|n=(q,z=-1…1,[];q.map{|x|q.map{|y|z\<\<[x,y]}};(z-=[[0,0]]).map{|x|c[i+x[0]][  
> e+x[1]]rescue u}-[f,u]).size;b[i][e]=(n==2?b[i][e]:n==3?o:f)}};sleep 0.2;end

size, occupied, forsaken, combat\_area\_last\_turn, undefined =  
20, “#”, " " # nil, nil

battlefield = (z = 0…size).map {  
z.map {  
if rand \< 0.3  
occupied  
else  
forsaken  
end  
}  
}

$\> \<\< “\e[2J”

until combat\_area\_last\_turn == battlefield

$\> \<\< “\e[H” \<\<  
battlefield.map {|x| x \* " " } \* “\n”

combat\_area\_last\_turn = battlefield.map {|z| z.dup }

# iterate over the entire grid

size.times {|i|  
size.times {|e|

```
  neighbour_count =
    (q, z = -1..1, []
     q.map {|x| q.map {|y| z << [x, y] } }

     # x iterates over the set of 8 relative neighbour coordinates
     (z -= [[0, 0]]).map {|x|

       # return the neighbour's value from last turn
       combat_area_last_turn[i + x[0]][e + x[1]] rescue undefined

     } - [forsaken, undefined] # don't count empties or 

```

off-the-edges  
).size

```
  # update the cell based on last turn's neighbour count
  battlefield[i][e] =
    if neighbour_count == 2
      battlefield[i][e]
    else
      if neighbour_count == 3
        occupied
      else
        forsaken
      end
    end
}

```

}  
sleep 0.2  
end

# And my version. You will need to hit Ctrl+Break to stop it.

o,f,m,c=“#”,"  
“,[-1,0,1]\*3;b=([7]_20).map{(0…20).map{(rand\<0.3)?o:f}};loop{  
$\>\<\<b.map{|x|x_f+”\n"};c=b.map{|x|x.dup};20.times{|i|20.times{|e|n=(m.sort.zip(  
m)-[[0,0]]).select{|x,y|o==(c[i+x]||[])[e+y]}.size;n!=2?b[i][e]=n==3?o:f:9}}}

# And the same thing with a little whitespace.

o = “#”  
f = " "  
c = nil # copy of b

# b # main grid

m = [-1, 0, 1] \* 3

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

loop {  
$\> \<\< b.map {|x| x \* f + “\n” }  
c = b.map {|x| x.dup }  
20.times {|i|  
20.times {|e|  
n =  
(m.sort.zip(m) - [[0, 0]]).select {|x, y|  
o == (c[i + x] || [])[e + y]  
}.size  
n != 2 ? b[i][e] = n == 3 ? o :  
f :  
9  
}  
}  
#sleep 0.1  
}

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 15, 2006, 8:15pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/5 "2006-05-15T20:15:56Z")

</div>

Dave B. wrote:

> Mike N. wrote:
> 
> > I took some golfed code from a discussion here little while back (  
> > [Search results for '' - Ruby-Forum](http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums%5B%5D=4)  
> > ) and tried my hand at de-golfing and re-working it a bit to make it  
> > readable.
> 
> What version did you deobfuscate?  
> This is the orginal version that I worked from,  
> #############################################################################

# [http://en.wikipedia.org/wiki/Conway's\_Game\_of\_Life](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)

# 

# removed\_email\_address@domain.invalid

# 

# j`ey (with thanks to Florian G. and Dave B.)

# 

# 305 characters

# 

#############################################################################  
s,o,f,c,u=20,“#”,"  
“;b=(z=0…s).map{z.map{(rand\<0.3)?o:f}};$\>\<\<”\e[2J";until  
c==b;$\>\<\<“\e[H”\<\<b.map{|x|x\*"  
“}\*”\n";c=b.map{|z|z.dup};s.times{|i|s.times{|  
e|n=(q,z=-1…1,[];q.map{|x|q.map{|y|z\<\<[x,y]}};(z-=[[0,0]]).map{|x|c[i+x[0]][  
e+x[1]]rescue u}-[f,u]).size;b[i][e]=(n==2?b[i][e]:n==3?o:f)}};sleep  
0.2;end

> I have here the version on J`ey’s site, and then a three-line version of  
> mine.  
> I didn’t see that one. I really like the sort.zip part, like this  
> pseudoquote,

(m =[-1,0,1]\*3).sort.zip(m) - [[0,0]]

that’s just lovely.

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 15, 2006, 5:08pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/6 "2006-05-15T17:08:28Z")

</div>

Joey wrote:

> Even though I wrote it, I couldn’t deobfuscate it afterwards! Is it ok  
> if I  
> pop this on my site?  
> [http://code.eachmapinject.com/game\_of\_life\_golf.rb](http://code.eachmapinject.com/game_of_life_golf.rb)

Joey,

Go right ahead. Feel free.

Thanks,  
Mike

---

<div class="post-metadata">

**Author:** ![miken700](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@miken700](https://www.ruby-forum.com/u/miken700)\
**Post date:** [May 15, 2006, 11:33pm UTC](https://www.ruby-forum.com/t/conways-life-de-golfed/60485/7 "2006-05-15T23:33:26Z")

</div>

Mike N. wrote:

> Dave B. wrote:
> 
> > I have here the version on J`ey’s site, and then a three-line version of  
> > mine.  
> > I didn’t see that one. I really like the sort.zip part, like this  
> > pseudoquote,
> 
> (m =[-1,0,1]\*3).sort.zip(m) - [[0,0]]
> 
> that’s just lovely.

I should have credited Daniel S. originally. He’s responsible for  
this gem and a few other bits – you can see his contribution in the  
original thread.

Cheers,  
Dave
