メインコンテンツへスキップ
見出し画像

A#01 ライフゲーム

    プログラミングの勉強のため、一瞬fortranを勉強していた時に作成したものです。だいぶ前につくったものですが、面白かったので。

    ライフゲームとは

    1970年にケンブリッジ大のコンウェイが発明したセルオートマトン。初期条件を与えれば一定の規則で世代が進み、生と死を表すセルが更新されていく。Wikipediaわかりやすい


    本を探すと以下のものくらいしか見つからなかった。気がする。
    1974年にはTime誌が「ライフゲイムの大群が数百万ドルの貴重なコンピュータ時間を食ってしまっている」と苦言を呈したほど流行ったらしい。


    代表的なパターン

    白いセルが「生(1)」を、黒いセルが「死(0)」を表していて、初期条件を与えれば、あとは世代を追って一定規則でころころ変わる。
    個人的にはたった5つの「生」でスタートして、ランダムそうな模様を展開するR pentominoが面白い。名前がついているのもまたいい。

    画像
    例1 Nebula

    初期条件は以下のように与える。Nebulaの例。

    画像
    例1 Nebulaの初期条件

    他にも例をいくつか。

    画像
    例2 R pentomino
    画像
    例3 Glider(周期境界条件)

    ソースコード

    プログラムは以下の記事を大いに参考にさせていただいています。

    Fortranで実装、gnuplotで描画しました。もうgnuplotなんて全然使ってない。。
    描画領域を正方形にして、初期条件を乱数ではなく、Excelで作成した init_field.txt から読み込ませてます。境界の条件はcshiftとeoshiftを使い分けて、固定境界か周期境界かを選べるようにしました。

    ! Conway's Game of Life
    
      module lifegame
          implicit none
          integer :: n
          integer, allocatable :: field( : , :  )
          integer, allocatable :: neighbors( : , :  )    
      contains
    
          subroutine init_field( size )
              integer, intent( in ) :: size
              integer i
              integer ios
              n = size
              allocate( field( n, n ) )
              allocate( neighbors( n, n ) )
              open(10, file="init_field.txt")
              do i=0, n
                  read(10, *, iostat=ios) field
                  if (ios .lt. 0) exit
              end do
              close(10)
          end subroutine init_field
    
          subroutine print_field()
              implicit none
              integer :: i
              do i = 1, n
                write (*, '( * ( i0, :, " " ) )' ) field( :, i )
              end do
          end subroutine print_field
    
          subroutine one_epoch
              implicit none
              integer :: dx, dy, i
              neighbors = 0
              do concurrent ( dx = -1 : 1, dy = -1 : 1 )
                ! 周期境界条件(cshift)
                  neighbors = neighbors + cshift( cshift(field, dx, 1), dy, 2 )
                ! 固定境界条件(eoshift, 境界の外は死(0))
                ! neighbors = neighbors + eoshift( eoshift(field, dx, 0, 1), dy, 0, 2 ) 
              end do
              where( neighbors == 3 )
                  field = 1
              elsewhere( neighbors == 4 )
                  field = field
              elsewhere
                  field = 0
              endwhere
          end subroutine one_epoch
    
      end module lifegame
    
    
      ! MainProgram
      program main
          use lifegame
          implicit none
          integer :: epoch, size
          integer :: i
    
          write( *, * ) "# size?"
          read( *, * ) size
          write( *, * ) "# epoch?"
          read( *, * ) epoch
    
          call init_field( size )
          call print_field
    
          do i = 1, epoch
              call one_epoch
              write (*, *)
              call print_field
          end do
    
          stop
      end program main

    gifアニメの出力はgnuplotで。

    reset
    
    set term gif animate size 560, 400    # 出力をgifアニメに設定
    set output "field.gif"                # 出力ファイル名
    
    set size square
    set nozeroaxis
    set notics
    unset colorbox
    
    set palette grey                      # gray0 = 黒
    set title font "Arial,30"
    set key below
    
    do for [n=0:1000:1] {
       plot "field.log" index n matrix with image title sprintf("generation %d", n)
    }

    fortran

    fortranは以下の本とか読んでいました。
    今ならchatgpt使って、最近のプログラムにも簡単に書き換えられるのかもと思いつつ。chatgptもいろいろ試して、記事書いてみたい。

    コンパイラ

    GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0


    準備があればさくっとかける。どんどんかくぞ。


    2023/4/12追記

    調べたら記事たくさんあった!レベル違う。奥が深い。


    chatgptなら、プログラムの書き換えだけじゃなくてこういう使い方もあるのか。そんなに詳しくない言語もなんとかなりそう。

     
     
    2026/8~世界周遊中|理系大学院卒 男 会社員|技術士(建設・河川)|防災士|G検定|世界遺産検定2級|読書、旅行、土木・河川、解析、AIなど|2016年~ブクログ(https://booklog.jp/users/shino424)

    あなたへのおすすめ