challenge ライフゲーム

セルオートマトンに関するお題です. 
2次元タイプの'ライフゲーム'を実装して下さい. 
初期値としては10行10列程度の格子上の平面に0.3程度の人口(?)密度を考え, 
末端はループするようにして下さい. (例: 座標[-1, -1] = [10, 10])

それだけだと簡単すぎると思われる方は, 
過密状態で間引きが発生するような機能を組み込んで下さい. 
間引きは, 少なくともその後の1時間ステップにおける死亡率が, 
それをしなかった場合よりも小さくなれば結構です. 
(死亡率の最小化は複雑性が高すぎる感がありますし. )
サンプル:
t = 0
[ ][*][ ][ ][ ][ ][*][*][*][ ]
[ ][ ][ ][ ][*][ ][ ][*][*][ ]
[ ][ ][ ][*][ ][ ][*][ ][*][ ]
[*][ ][*][*][ ][ ][*][ ][ ][ ]
[ ][*][ ][ ][ ][ ][ ][ ][*][ ]
[*][ ][ ][ ][*][ ][*][*][ ][*]
[ ][*][ ][ ][ ][ ][*][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][ ][*][ ][ ][*]
[ ][ ][ ][ ][*][*][ ][ ][*][ ]
t = 1
[ ][ ][ ][ ][*][ ][ ][ ][ ][*]
[ ][ ][ ][ ][ ][*][ ][ ][ ][*]
[ ][ ][*][ ][*][*][*][ ][*][*]
[ ][*][ ][*][ ][ ][ ][ ][ ][*]
[ ][ ][*][*][ ][*][*][ ][*][ ]
[ ][*][ ][ ][ ][*][*][ ][*][*]
[ ][ ][ ][ ][ ][*][*][*][*][*]
[ ][ ][ ][ ][ ][ ][ ][ ][ ][*]
[*][ ][ ][ ][ ][*][ ][ ][*][ ]
[*][ ][ ][ ][ ][ ][ ][ ][ ][ ]

Posted feedbacks - Other

シェーダ言語のHLSLで書いてみました。 これ以外にシェーダを駆動するためのコードが500行以上必要なので、参考ページURLに載せておきました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Cから変更できる変数の宣言。問題サイズに対応。座標計算に使う。
float F_X;
float F_Y;
// テクスチャの宣言
texture SrcTex1;
// テクスチャの定義
sampler Samp1 = sampler_state
{
    Texture        = <SrcTex1>;
    MinFilter    = POINT;
    MagFilter    = POINT;
    MipFilter    = NONE;
    AddressU    = WRAP;
    AddressV    = WRAP;
};
// 頂点シェーダの出力形式
struct VS_OUTPUT
{
    float4 Pos        : POSITION;
    float2 Tex        : TEXCOORD;
};
// 頂点シェーダ(未使用)
VS_OUTPUT VS_DEFAULT (
    float4 Pos        : POSITION,
    float2 Tex        : TEXCOORD
){
    VS_OUTPUT Out    = (VS_OUTPUT)0;
    return Out;
}
// ピクセルシェーダ
float4 PS_TEST ( VS_OUTPUT In ) : COLOR
{
    float4 Color        = {0.0f, 0.0f, 0.0f, 0.0f};
    float2 TexA            = {0.0f, 0.0f};
    float4 Color0        = {0.0f, 0.0f, 0.0f, 0.0f};
    int num;
    int sum;
    int ret;

    TexA                = In.Tex + float2(F_X*0.5f, F_Y*0.5f);

    Color                += tex2D( Samp1, TexA+float2(-F_X, -F_Y) );
    Color                += tex2D( Samp1, TexA+float2(0.0f, -F_Y) );
    Color                += tex2D( Samp1, TexA+float2( F_X, -F_Y) );
    Color                += tex2D( Samp1, TexA+float2(-F_X,  0.0f) );
    Color0                =  tex2D( Samp1, TexA+float2( 0.0f,  0.0f) );
    Color                += tex2D( Samp1, TexA+float2( F_X,  0.0f) );
    Color                += tex2D( Samp1, TexA+float2(-F_X,  F_Y) );
    Color                += tex2D( Samp1, TexA+float2(0.0f,  F_Y) );
    Color                += tex2D( Samp1, TexA+float2( F_X,  F_Y) );
    num                    = round(Color0.r);
    sum                    = round(Color.r);
    ret                    = (sum==3) + (sum==2) * num;
    /*
    // 上の行は以下の条件式をまとめたもの。
    // 分岐をなくしたので多くのGPUで実行可能なはず。
    if(num==0)
    {
        ret                = sum==3;
    }else{
        ret                = ((sum==2)+(sum==3)) != 0;
    }
    */
    return float4((float)(ret*0xff), 0.0f, 0.0f, 1.0f);    // RGBA
}
// テクニック
technique RenderScene
{
    pass P0
    {
        VertexShader    = compile vs_2_0 VS_DEFAULT();
        PixelShader        = compile ps_2_0 PS_TEST();
    }
}

Google Goで書いてみました。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
    "rand"
    "time"
)

type LifeGame struct {
    board [][]bool
    row, col int
    time int
}

func (p *LifeGame) Init(row, col int) *LifeGame {
    //rand.Seed(0)
    p.row = row
    p.col = col
    p.board = make([][]bool, row)
    for r := 0; r < row; r++ {
        p.board[r] = make([]bool, col)
        for c := 0; c < col; c++ {
            if rand.Float() < 0.3 {
                p.board[r][c] = true
            }
        }
    }
    p.time = 0
    return p
}

func (p *LifeGame) Print() {
    print("time=")
    println(p.time)
    f := func(b bool) (s string) {
        if b {
            s = "[*]"
        } else {
            s = "[ ]"
        }
        return s
    }
    for r := 0; r < p.row; r++ {
        for c := 0; c < p.col; c++ {
            print(f(p.board[r][c]))
        }
        println()
    }
}


func (p *LifeGame) count_now_alive(r, c int) (i int) {
    if r < 0 {
        r += p.row
    }
    if p.row <= r {
        r -= p.row
    }
    if c < 0 {
        c += p.col
    }
    if p.col <= c {
        c -= p.col
    }
    if p.board[r][c] {
        i = 1
    } else {
        i = 0
    }
    return i
}
func (p *LifeGame) is_dead_or_alive(r, c int) (b bool) {
    count := p.count_now_alive(r - 1, c - 1) +
         p.count_now_alive(r - 1, c    ) +
         p.count_now_alive(r - 1, c + 1) +
         p.count_now_alive(r    , c - 1) +
         p.count_now_alive(r    , c    ) +
         p.count_now_alive(r    , c + 1) +
         p.count_now_alive(r + 1, c - 1) +
         p.count_now_alive(r + 1, c    ) +
         p.count_now_alive(r + 1, c + 1)
    switch count {
        case 3:
            b = true
        case 4:
            b = p.board[r][c]
        default:
            b = false
    }
    return b
}

func generate_gen(game *LifeGame, ch chan<- *LifeGame) {
    for true {
        next := new(LifeGame).Init(game.row, game.col)
        for r := 0; r < game.row; r++ {
            for c := 0; c < game.col; c++ {
                next.board[r][c] = game.is_dead_or_alive(r, c)
            }
        }
        next.time = game.time + 1
        ch <- next
        game = next
    }
}


func main() {
    game := new(LifeGame).Init(10, 10)
    game.Print()

    ch := make(chan *LifeGame)
    go generate_gen(game, ch)
    for next := range ch {
        next.Print()
        time.Sleep(1e9)
    }
}

Index

Feed

Other

Link

Pathtraq

loading...