2019年4月24日 | ブログ記事

gnuplotで遊ぼう

mds_boy

こんにちは、mds_boyです。
本記事は新歓ブログリレー47日目の記事です。

新入生のみなさん、情報リテラシを履修していますか?
traPに興味がある方の多くは取っているんじゃないかなと思います。

今回紹介するのは、情報リテラシ第二で扱うgnuplotについてです。
(もしかしたらクラスによっては使わないかもしれませんが)

この記事を読めば情報リテラシ楽勝!……とは別にならないと思います。

gnuplotって?

gnuplotは、一般的には実験データをグラフ化したいときに使われるソフトウェアです。

公式サイト

公式サイトにドキュメント(英語, ver5.2)が載っています。
日本語版もありますが若干古い(ver4.6)ので注意です。

インストールはLinux/macOSならパッケージ管理システムから、Windowsなら公式サイトからexeを落とすのが簡単だと思います。

使ってみる

では実際に使ってみます(使い方を知ってる人は飛ばしちゃって大丈夫です)

さて、ターミナル(Winならコマンドプロンプト)を起動して、gnuplotと打ち込むとこんな感じの画面が出ます。

Screenshot-from-2019-04-14-12-31-07

ここでplot sin(x)と打ち込むと、
Screenshot-from-2019-04-14-12-32-20
こんな感じでsin(x)のグラフが表示されます。
簡単ですね!

では次に下のような感じで適当な二次元座標を書いたファイルdata.txtを用意します(名前は何でも良い)

1 1
2 2
3 1
4 3

これが置いてあるディレクトリでplot 'data.txt' with linespointsと打つと

Screenshot-from-2019-04-14-13-51-53

簡単ですね!

こんな感じでグラフを実験データのグラフを描くのに使うのが一般的な用途です。

アニメーション

さて、gnuplotではグラフの描画を時間変化に応じて変更することができます。

do for [i = 0:100 ] {
    pause 0.01
    plot sin(x+i)
}

見ての通りfor文です。
i=0から100まで0.01秒間隔でsin(x+i)を描画します。

適当なファイル名を付けて保存し、load 'ファイル名'として呼び出すと

Peek-2019-04-14-15-27

こんな感じでアニメーションを作ることができます。

ライフゲーム

さてみなさん、ライフゲームって知ってますか?

簡単に言うとマスに生・死があって、一定のルールで生死が変化するのを眺めるものです。
詳しくはwikipediaを読んでください。

ではgnuplotでライフゲームを実装しましょう。

実は、gnuplotは配列を扱うことが出来ます(ver5.2からの新機能です)

配列とforがあればなんとなく実装できそうですね!
というわけでこんな感じです

xsize = 50
ysize = 50

set xrange [0:xsize]
set yrange [0:ysize]

array A[xsize*ysize]
array B[xsize*ysize]
do for [i=1:xsize] {
    do for [j=1:ysize] {
        k = i + (j-1) * xsize
        set object k rect from i,j to i+1,j+1
        A[k] = rand(0) < 0.5
        B[k] = 0
    }
}

do for [n=1:1000] {
    plot 0 lt bgnd
    do for [i=1:xsize] {
        do for [j=1:ysize] {
            k = i + (j-1) * xsize
            if (A[k] == 1) {
                set object k fc rgb "brown"
            } else {
                set object k fc bgnd
            }
        }
    }
    do for [i=1:xsize] {
        do for [j=1:ysize] {
            k = i + (j-1) * xsize
            count = 0
            do for [dx = -1:1] {
                do for [dy = -1:1] {
                    if (dx == 0 && dy == 0) {
                        continue;
                    }
                    nx = (i + dx + xsize - 1) % xsize + 1
                    ny = (j + dy + ysize - 1) % ysize + 1
                    if (A[nx+(ny-1)*xsize] == 1) {
                        count = count + 1
                    }
                }
            }
            if (A[k] == 1) {
                if (count <= 1 || count >= 4) {
                    B[k] = 0
                } else {
                    B[k] = 1
                }
            } else {
                if (count == 3) {
                    B[k] = 1
                } else {
                    B[k] = 0
                }
            }
        }
    }
    do for [i=1:xsize] {
        do for [j=1:ysize] {
            k = i + (j-1) * xsize
            A[k] = B[k]
        }
    }
}

Peek-2019-04-14-18-10

他のプログラミング言語と同じような感じでプログラムを書くことができました。
各マスの生死を0,1で持っておき、毎回色を変えることで表現しています。

ライフゲームはチューリング完全なので、gnuplotもチューリング完全というわけですね。
実際brainfuckのインタプリタを作った人もいます。

おまけ

gnuplotは3次元グラフの描画も行うことができます。
splot x*yとすると
Screenshot-from-2019-04-14-18-32-45

このサイトに立方体の描き方が載っていたので、これを参考にして3Dのライフゲームを描いてみました。
こんな感じです。
元々の機能として回転させることができます。

Peek-2019-04-01-00-39

ついでに立方体に2次元ライフゲームを貼り付けたものも描いてみました(面と面の部分でセルが移動するところが若干バグっています)。

Peek-2019-04-14-18-51

その他参考

http://slpr.sakura.ne.jp/qp/gnuplot-animation/


感想ですが、gnuplotでやる必要あったかな……と思いました。

明日はxecuaくんの記事です。楽しみですね。

この記事を書いた人
mds_boy

ゲーム制作や競技プログラミングをしています

この記事をシェア

このエントリーをはてなブックマークに追加

関連する記事

2019年4月22日
アセンブリを読んでみよう【新歓ブログリレー2019 45日目】
eiya
2019年4月8日
プログラミングを始めよう【新歓ブログリレー2019 31日目】
idaten
2019年3月18日
競プロの最善手
topaz
2019年3月16日
競技プログラミングを始めよう【新歓ブログリレー2019 8日目】
eiya
2019年4月26日
traPへの入部、ありがとうございました!
Yosotsu
2019年4月25日
本【新歓ブログリレー2019 48日目】
xecua

活動の紹介

カテゴリ

タグ