LoginSignup
0
3

More than 5 years have passed since last update.

一次元セルオートマトン

Last updated at Posted at 2017-01-06

セルオートマトンとは

wikipedia

wikiが充実してるのでそちらを。

単純なコードで目に楽しい出力です。
ちなみに二次元セルオートマトンはライフゲームという名で有名ですね。

Rubyで

やってみます。

make_all_pattern

一次元の場合パターンが256しかないので、力任せに全てのパターンを生成します。
8重forという酷いコード。

class Cells
  attr :table, :cells

  def initialize
    @cells = [1]
    @table = make_all_patterns
  end

  def make_all_patterns
    cs = [0,1]
    ops = []
    ips = []
    ps = [] 

    for i1 in cs
      for i2 in cs
        for i3 in cs
          ips.push [i1,i2,i3]
        end
      end
    end

    for o1 in cs
      for o2 in cs
        for o3 in cs
          for o4 in cs
            for o5 in cs
              for o6 in cs
                for o7 in cs
                  for o8 in cs
                    os = [o1,o2,o3,o4,o5,o6,o7,o8]
                    n = os.map { |o| o.to_s }.reduce(:+).to_i(2)
                    ops[n] = os
                  end
                end
              end
            end
          end
        end
      end
    end

    ops.each_with_index { |os,n|
      ps[n] = {}
      for o,i in os.reverse.zip ips
        ps[n][i] = o 
      end
    }

    ps
  end

apply

各セルにパターンを適応します。
両端に一つずつセルを追加して成長させ、
周囲のセルの状態と自分の状態で次の状態をパターンによって決めていきます。
パターンマッチはただのHashでできてしまいました。Rubyすごい。

  def apply pn
    pt = @table[pn]    
    s = @cells.size
    f = -> i { (i < 0 || i >= s) ? 0 : @cells[i] }
    newCells = []
    for i in -1 .. s
      cs = [f.call(i-1), f.call(i), f.call(i+1)]
      newCells.push(pt[cs])
    end 
    @cells = newCells
  end

show

パターンとセルを見やすく。

  def show_cells
    #@cells.map { |c| c == 1 ? "O" : " " }.join
    @cells.join
  end

  def show_table pn
    "[#{pn}] " + 
      @table[pn].keys.map { |k| "#{k.join} = #{@table[pn][k]}" }.join(", ")
  end

run

ビジュアライズ。
runの引数は0から255までで。
ターミナルの幅と高さに合わせて表示。
表示が終わったところで@cellsを初期化しておきます。

  require "io/console"
  def run pn
    raise "expected arg in 0..255" unless pn < 256
    puts show_table pn
    rs, cs = IO.console.winsize
    (rs - 2).times  {
      puts show_cells.center(cs)
      apply pn
    }
    @cells = [1]
  end
end

main

折角なので全パターン実行。
newで全パターン生成してるのでuptoの外に。
sleepで目で追える程度に調整。

cs = Cells.new
0.upto(255) { |n| 
  cs.run(n)
  sleep 0.3
}

ルール90

こんな感じで表示されます。

[90] 000 = 0, 001 = 1, 010 = 0, 011 = 1, 100 = 1, 101 = 0, 110 = 1, 111 = 0

                                         1                                                
                                        101                                               
                                       10001                                              
                                      1010101                                             
                                     100000001                                            
                                    10100000101                                           
                                   1000100010001                                          
                                  101010101010101                                         
                                 10000000000000001                                        
                                1010000000000000101                                       
                               100010000000000010001                                      
                              10101010000000001010101                                     
                             1000000010000000100000001                                    
                            101000001010000010100000101                                   
                           10001000100010001000100010001                                  
                          1010101010101010101010101010101                                 
                         100000000000000000000000000000001                                
                        10100000000000000000000000000000101                               
                       1000100000000000000000000000000010001                              
                      101010100000000000000000000000001010101                             
                     10000000100000000000000000000000100000001                            
                    1010000010100000000000000000000010100000101                           
                   100010001000100000000000000000001000100010001                          
                  10101010101010100000000000000000101010101010101                         
                 1000000000000000100000000000000010000000000000001                        
                101000000000000010100000000000001010000000000000101                       
               10001000000000001000100000000000100010000000000010001                      
              1010101000000000101010100000000010101010000000001010101                     
             100000001000000010000000100000001000000010000000100000001                    
            10100000101000001010000010100000101000001010000010100000101                   
           1000100010001000100010001000100010001000100010001000100010001                  
          101010101010101010101010101010101010101010101010101010101010101                 

make_all_patternsの8重forがダサいですが、
パターンマッチがHashで済んでしまう所はクールでした。
簡単ながらそこそこ作り甲斐があるので新しい言語覚える時は、
hello,worldの代わりに書いたりしてます。

0
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3