⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

class WireWorld
  EMPTY     = ' '
  HEAD      = 'H'
  TAIL      = 't'
  CONDUCTOR = '.'
  NEIGHBOURS = [-1,0,1].product([-1,0,1]) - [0,0]
  
  def initialize(string)
    @grid = string.each_line.collect do |line|
              line.chomp.each_char.collect do |char| 
                case char
                when EMPTY, HEAD, TAIL, CONDUCTOR
                  char
                else
                  EMPTY
                end 
              end
            end
    @width = @grid.collect{|row| row.length}.max + 1
    @height = @grid.length
    pad_grid
    @original_grid = Marshal.restore(Marshal.dump @grid)   # this is a deep copy
  end
  
  # initialize from a file
  def self.open(filename)
    self.new(File.read(filename))
  end
  
  def reset
    @grid = @original_grid
  end
  
  # ensure all rows are the same length by padding short rows with empty cells
  def pad_grid
    @grid << []
    @grid.each do |row|
      row.concat(Array.new(@width - row.length, EMPTY))
    end
  end
  
  # the "to_string" method
  def to_s
    @grid.collect {|row| row.join}.join("\n")
  end
  
  # transition all cells simultaneously
  def transition
    @grid = @grid.each_with_index.collect do |row, y| 
              row.each_with_index.collect do |state, x| 
                transition_cell(state, x, y)
              end
            end
  end
  
  # how to transition a single cell
  def transition_cell(current, x, y)
    case current
    when EMPTY then EMPTY
    when HEAD  then TAIL
    when TAIL  then CONDUCTOR
    else neighbours_with_state(x, y).between?(1,2) ? HEAD : CONDUCTOR
    end
  end
  
  # given a position in the grid, find the neighbour cells with a particular state
  def neighbours_with_state(x, y)
    NEIGHBOURS.count {|dx, dy| @grid[y+dy][x+dx] == HEAD}
  end
  
  # run a simulation up to a limit of transitions, or until a recurring
  # pattern is found
  # This will print text to the console
  def run(iterations = 25)
    seen = {}
    for count in 0..iterations
      puts "Generation : #{count}"
      puts to_s
      
      if seen[@grid]
        puts "I've seen this grid before... after #{count} iterations"
        return
      end
      
      seen[@grid] = count
      transition
    end
    puts "ran through #{iterations} iterations"
  end
end

Test (Text version)

# this is the "2 Clock generators and an XOR gate" example from the wikipedia page
text = <<WORLD
 ......tH
.        ......
 ...Ht...      .
              ....
              .  .....
              ....
 tH......      .
.        ......
 ...Ht...
WORLD

ww = WireWorld.new text
 
ww.run
puts 'bye'

{{out}}

Generation : 0
 ......tH              
.        ......        
 ...Ht...      .       
              ....     
              .  ..... 
              ....     
 tH......      .       
.        ......        
 ...Ht...              
                       
Generation : 1
 .......t              
.        H.....        
 ..Ht....      .       
              ....     
              .  ..... 
              ....     
 .tH.....      .       
.        ......        
 ..Ht....              
                       
Generation : 2
 ........              
.        tH....        
 .Ht....H      .       
              ....     
              .  ..... 
              ....     
 ..tH....      .       
.        ......        
 .Ht.....              
                       
Generation : 3
 ........              
.        .tH...        
 Ht....Ht      .       
              ....     
              .  ..... 
              ....     
 ...tH...      .       
.        ......        
 Ht......              
                       
Generation : 4
 ........              
H        ..tH..        
 t....Ht.      .       
              ....     
              .  ..... 
              ....     
 ....tH..      .       
H        ......        
 t.......              
                       
Generation : 5
 H.......              
t        ...tH.        
 ....Ht..      .       
              ....     
              .  ..... 
              ....     
 H....tH.      .       
t        ......        
 ........              
                       
Generation : 6
 tH......              
.        ....tH        
 ...Ht...      .       
              ....     
              .  ..... 
              ....     
 tH....tH      .       
.        ......        
 ........              
                       
Generation : 7
 .tH.....              
.        .....t        
 ..Ht....      H       
              ....     
              .  ..... 
              ....     
 .tH....t      .       
.        H.....        
 ........              
                       
Generation : 8
 ..tH....              
.        ......        
 .Ht.....      t       
              HHH.     
              .  ..... 
              ....     
 ..tH....      .       
.        tH....        
 .......H              
                       
Generation : 9
 ...tH...              
.        ......        
 Ht......      .       
              tttH     
              H  H.... 
              ....     
 ...tH...      .       
.        .tH...        
 ......Ht              
                       
Generation : 10
 ....tH..              
H        ......        
 t.......      .       
              ...t     
              t  tH... 
              HHHH     
 ....tH..      .       
.        ..tH..        
 .....Ht.              
                       
Generation : 11
 H....tH.              
t        ......        
 ........      .       
              ....     
              .  .tH.. 
              tttt     
 .....tH.      .       
.        ...tH.        
 ....Ht..              
                       
Generation : 12
 tH....tH              
.        ......        
 ........      .       
              ....     
              .  ..tH. 
              ....     
 ......tH      .       
.        ....tH        
 ...Ht...              
                       
Generation : 13
 .tH....t              
.        H.....        
 ........      .       
              ....     
              .  ...tH 
              ....     
 .......t      H       
.        H....t        
 ..Ht....              
                       
Generation : 14
 ..tH....              
.        tH....        
 .......H      .       
              ....     
              .  ....t 
              HHH.     
 ........      t       
.        tH....        
 .Ht....H              
                       
Generation : 15
 ...tH...              
.        .tH...        
 ......Ht      .       
              ....     
              H  H.... 
              tttH     
 ........      .       
.        .tH...        
 Ht....Ht              
                       
Generation : 16
 ....tH..              
.        ..tH..        
 .....Ht.      .       
              HHHH     
              t  tH... 
              ...t     
 ........      .       
H        ..tH..        
 t....Ht.              
                       
Generation : 17
 .....tH.              
.        ...tH.        
 ....Ht..      .       
              tttt     
              .  .tH.. 
              ....     
 H.......      .       
t        ...tH.        
 ....Ht..              
                       
Generation : 18
 ......tH              
.        ....tH        
 ...Ht...      .       
              ....     
              .  ..tH. 
              ....     
 tH......      .       
.        ....tH        
 ...Ht...              
                       
Generation : 19
 .......t              
.        H....t        
 ..Ht....      H       
              ....     
              .  ...tH 
              ....     
 .tH.....      H       
.        .....t        
 ..Ht....              
                       
Generation : 20
 ........              
.        tH....        
 .Ht....H      t       
              HHH.     
              .  ....t 
              HHH.     
 ..tH....      t       
.        ......        
 .Ht.....              
                       
Generation : 21
 ........              
.        .tH...        
 Ht....Ht      .       
              tttH     
              .  H.... 
              tttH     
 ...tH...      .       
.        ......        
 Ht......              
                       
Generation : 22
 ........              
H        ..tH..        
 t....Ht.      .       
              ...t     
              .  t.... 
              ...t     
 ....tH..      .       
H        ......        
 t.......              
                       
Generation : 23
 H.......              
t        ...tH.        
 ....Ht..      .       
              ....     
              .  ..... 
              ....     
 H....tH.      .       
t        ......        
 ........              
                       
I've seen this grid before... after 23 iterations
bye

```


The GUI version
{{libheader|Ruby/Tk}}

The GUI is somewhat "halfway", in that it animates a text widget so it's not "real" graphics.

```ruby
require 'tk'
 
class WireWorld
  def run_tk
    @tk_root = TkRoot.new(title: "WireWorld")
    
    @tk_text = TkText.new(width: @width, height: @height, font: 'courier')
    @tk_text.insert('end', self.to_s).state('disabled')
    
    @tk_after_interval = 150
    faster_cmd = proc {@tk_after_interval = [25, @tk_after_interval-25].max}
    slower_cmd = proc {@tk_after_interval += 25}
    reset_cmd = proc {self.reset}
    close_cmd = proc do
      @tk_root.after_cancel(@tk_after_id)
      @tk_root.destroy
    end
    
    controls = TkFrame.new
    [ TkButton.new(controls, text: 'Slower', command: slower_cmd),
      TkButton.new(controls, text: 'Faster', command: faster_cmd),
      TkButton.new(controls, text: 'Reset',  command: reset_cmd),
      TkButton.new(controls, text: 'Close',  command: close_cmd),
    ].each {|btn| btn.pack(expand: 1, fill: 'x', side: 'left')}
    
    @tk_text.pack(expand: 1, fill: 'both')
    controls.pack(fill: 'x')
    
    @tk_after_id = @tk_root.after(500) {animate}
    Tk.mainloop
  end
  
  def animate
    transition 
    @tk_text.state('normal') \
            .delete('1.0','end') \
            .insert('end', self.to_s) \
            .state('disabled')
    @tk_after_id = @tk_root.after(@tk_after_interval) {animate}
  end
end

ww = WireWorld.new text
ww.run_tk
```


{{libheader|Shoes}}

```ruby
ww = WireWorld.new text
Shoes.app(title: "Wireworld") do
  world = para('', family: 'monospace')
  animate(4) do
    world.text = ww.to_s
    ww.transition
  end
end
```