[romandie.rb] LifeGame - Suite à la réunion du 16 sept.

0 views
Skip to first unread message

Yann Lugrin

unread,
Sep 17, 2010, 4:42:53 AM9/17/10
to Discussions du RUG romandie.rb
Bonjour à tous,

J'ai push le code que nous avons produit avec Damien hier sur Gist, je
l'ai aussi debug et ajouté quelques tests, mais l'était dans lequel il
était hier en fin de session est dispo à l'origine de l'historique.

http://gist.github.com/583865

Je lui avais dit à Damien que clone sur un Array multi dimensionnel ça
ne marchai pas :D

--
Yann Lugrin
yann....@sans-savoir.net
_______________________________________________
romandie.rb mailing list
roman...@zarb.org
https://www.zarb.org/mailman/listinfo/romandie.rb

Andreas Kundig

unread,
Sep 17, 2010, 5:41:55 AM9/17/10
to Discussions du RUG romandie.rb
# Ecrit par Thibaud et Andréas à Lausanne,
# débuggé par Stéphane et Andréas dans le train pour Genève.
# Nul doute qu'il reste pas mal de choses à améliorer, mais ça marche.
Dans DOS.
# Pour unix il faut en tout cas remplacer system("cls") par system("clear").
#
# J'avais promis de mettre ça sous gist, mais je suis trop à la bourre
pour apprendre ça ce matin.
#
# Thibaud, notre bug a été d'oublier que cloner un tableau de tableaux
ne clone que le tableau extérieur,
# de sorte que board_clone[x][y]=false modifie aussi l'original.

class Life
attr_accessor :board, :size

def initialize(sequence = "0000000000011100000000000",
options = { :size => 5 })
@size = options[:size]
@board = []
sequence.split(//).each_with_index do | cell,i |
@board << [] if i%size == 0
@board[-1] << (cell == "1")
end
end

def live
new_board = []#board.clone
board.each_index do |row|
new_board[row] = []
board[row].each_index do |col|
new_board[row][col] = new_cell(row, col)
end
end
@board = new_board
end

def new_cell(row, col)
case count_living_neighbours(row,col)
when 2
board[row][col]
when 3
true
else
false
end
end

def count_living_neighbours(row, col)
count = 0
count += 1 if board[row-1][col-1]
count += 1 if board[row-1][col]
count += 1 if board[row-1][(col+1)%size]
count += 1 if board[row][col-1]
count += 1 if board[row][(col+1)%size]
count += 1 if board[(row+1)%size ][col-1]
count += 1 if board[(row+1)%size ][col]
count += 1 if board[(row+1)%size ][(col+1)%size]
count
end


def display
system('cls')

board.each do |line|
line.each do |cell|
print cell ? 'X' : 0
end
print "\n"
end
sleep 1
end

def play
loop do
display
live
end
end
end

life = Life.new
life.play

Stéphane

unread,
Sep 17, 2010, 6:29:25 AM9/17/10
to roman...@zarb.org
Salut à tous,

Ah le coup du clone ;-)
J'en connais qui sont tombés dans le panneau.
En fouillant un peu, l'idiome pour une "deep copy" d'un array est
Marshal.load(Marshal.dump(a)).

cf http://gist.github.com/584027

J'ai trouvé très intéressant de voir les différentes approches hier
soir.

à retenir : mieux préciser le pb au départ, et faire attention au
temps nécessaire
à découvrir un environnement (emacs, windaube, ...)

A+

On Sep 17, 10:42 am, Yann Lugrin <yann.lug...@gmail.com> wrote:
> Bonjour à tous,
>
> J'ai push le code que nous avons produit avec Damien hier sur Gist, je
> l'ai aussi debug et ajouté quelques tests, mais l'était dans lequel il
> était hier en fin de session est dispo à l'origine de l'historique.
>
> http://gist.github.com/583865
>
> Je lui avais dit à Damien que clone sur un Array multi dimensionnel ça
> ne marchai pas :D
>
> --
> Yann Lugrin

> yann.lug...@sans-savoir.net
> _______________________________________________
> romandie.rb mailing list
> romandie...@zarb.orghttps://www.zarb.org/mailman/listinfo/romandie.rb

Gaspard Bucher

unread,
Sep 19, 2010, 7:59:57 AM9/19/10
to Discussions du RUG romandie.rb
Mes racines en "C" me dictent d'utiliser un seul Array:

class Grid < Array
  ...

  def get(x,y)
    self[(y % @height) * @width + (x % @width)]
  end
end

old_grid = grid.dup

Et ça transforme le monde en tore pour pas cher.

Mais en plus je me passerais de dup en utilisant le double-buffering cher aux vieux codeurs graphiques:


class SmartGrid < Array
  def initialize(width, height)
    @r_offset, @w_offset = (width*height), 0
    ...
  end

  def write(x,y,value)
    self[@w_offset + (y % @height) * @width + (x % @width)] = value
  end

  def read(x,y)
    self[@r_offset + (y % @height) * @width + (x % @width)] = value
  end

  def swap!
    @r_offset, @w_offset = @w_offset, @r_offset
  end
end

Finalement, je pense que l'implémentation du décompte des voisins devrait se faire sous forme de matrice (kernel):

grid.set_mat(
[[1, 1, 1],
 [1, 0, 1],
 [1, 1, 1]]
)

Avec 

def build_kernel(mat)
  mat_r = (mat.size - 1) / 2
  mat_c = (mat.first.size - 1) / 2
  @kernel = []
  mat.each_with_index do |row, row_i|
    row.each_with_index do |weight, col_i|
      @kernel << [col_i - mat_c, row_i - mat_r, weight]
    end
  end
end

def regression(x,y)
  @kernel.inject(0) do |s, k|
    s += k[2] * read(k[0], k[1])
  end
end


G.

2010/9/17 Stéphane <stephan...@gmail.com>
Reply all
Reply to author
Forward
0 new messages