Conway's Life de-golfed


#1

I took some golfed code from a discussion here little while back (
http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums[]=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


#2

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

j`ey
http://www.eachmapinject.com


#3

On 5/14/06, Mike N. removed_email_address@domain.invalid wrote:

I took some golfed code from a discussion here little while back (
http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums[]=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


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


#4

Mike N. wrote:

I took some golfed code from a discussion here little while back (
http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums[]=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

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
}


#5

Dave B. wrote:

Mike N. wrote:

I took some golfed code from a discussion here little while back (
http://www.ruby-forum.com/search?query=Golfing+a+signature.&forums[]=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

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.


#6

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

Joey,

Go right ahead. Feel free.

Thanks,
Mike


#7

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