仮想計算機構

IT業界と無縁な派遣社員のブログ

Schemeでセルラー・オートマトン

人工生命の本*1積読になっていたので読み始めました。何番煎じかわかりませんが1次元セルラーオートマトンで遊んでみたいと思います。

以下、筆者の実行環境です。
OS : WIndows 10
CPU : Intel Core i5 2.60GHz
言語 : Gauche 0.9.9

実験のために以前作ったコードを再利用します。
グラフィックスの下準備 その1 - 仮想計算機構

グラフィックスの下準備 その2 - 仮想計算機構

線を丁寧に描くよ - 仮想計算機構

円を丁寧に描くよ - 仮想計算機構

以前作った grBMP.scm や circle.scm と同じディレクトリに以下の main.scm を作成しました。基本的にはALife本(p.38)のコードをそのままSchemeで書いてみただけの素朴なものになります。画像サイズを640 x 400にしてあるので、1ピクセルを1つのセルとみなし、640個のセルが400世代に渡って変化する様子をシミュレーションします。

(use gauche.array)
(include "grBMP.scm")
(include "line.scm")
(include "circle.scm")

(define space_size 640)
(define N 400)
(define rule 30)
(define state (make-array (shape 0 space_size) 0))
(array-set! state (/ space_size 2) 1)
(define next_state (make-array (shape 0 space_size) 0))

(define (gr_state n)
    (do
        ((i 0 (+ i 1)))
        ((= i space_size))
        (if (= 1 (array-ref state i))
            (gr_dot i (- 400 n) WHITE)
        )
    )
)

(gr_state 0)
(do
    ((i 1 (+ i 1)))
    ((= i N))
    (do
        ((j 0 (+ j 1)))
        ((= j space_size) (set! state (array-copy next_state)) (gr_state i))
        (let
            ((l (array-ref state (remainder (+ space_size (- j 1)) space_size))) 
             (c (array-ref state j)) 
             (r (array-ref state (remainder (+ j 1) space_size))))
            (let ((neighbor_cell_code (+ (* 2 2 l) (* 2 c) r)))
                (if (= 1 (logand 1 (ash rule (* -1 neighbor_cell_code))))
                    (array-set! next_state j 1)
                    (array-set! next_state j 0)
                )
            )
        )
    )
)
(gr_BMP "test.bmp")

プログラム中のruleという変数は0から255まで自由に設定することが可能です。これはセルの状態遷移の仕方を決める重要なパラメータとなります。Wikipedia*2によると、いくつか有名なルールがあるようです。今回は3通り試します。
では実行です。

PS > gosh .\main.scm

プログラムの実行によってBMP形式のファイルが生成されます。
実行結果は以下の通りです。

ルール30
f:id:riverta1992:20200509133506j:plain

ルール90
f:id:riverta1992:20200509133546j:plain

ルール110
f:id:riverta1992:20200509133604j:plain

思いのほか上手くできてしまいました。
やはりルール90は美しいですね。