Prolog 写経記 その 60 random/3
(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.
- 作者: ボグダンフィリピッチ,中島誠,伊藤哲郎
- 出版社/メーカー: 海文堂出版
- 発売日: 1990/08
- メディア: 単行本
- 購入: 4人 クリック: 33回
- この商品を含むブログ (68件) を見る
random/3
を写経します.解説
random(Min, Max, Num)
はMin
とMax
の間からランダムに選んだ数をNum
に具体化する.
ふむ.
モード
random(+, +, -).
ふむふむ.
定義
では,こいつの定義を写経しませう.
random(Min, Max, Num) :- integer(Min), integer(Max), Min =< Max, retract(seed(S)), Num is S mod (Max - Min + 1) + Min, NewSeed is (125 * S +1) mod 4096, asserta(seed(NewSeed)), !. seed(7).
うーみゅ...
ここでポイントになるのは以下のとこ.
retract(seed(S)),
retract/1
は引数で指定した述語を Prolog の実行環境 (Prolog ではこれをデータベースと呼ぶらしい) から取り除きます.Java でいうとクラスのアンロードみたいなものでしょうか.
その際に,乱数の種 S
を具体化しています.
その種から引数で指定された範囲の乱数 Num
を求めた後,新しい種 NewSeed
を求めて
asserta(seed(NewSeed)), !.
asserta/1
により新しい種を Prolog の実行環境に追加します.
つまり,実行環境 (データベース) をグローバル変数として利用しているわけです.
し・か・も
破壊的代入をしているのと同等.
なんか,とってもいやーんなやり方ですね...
なお,SWI-Prolog (ってか ISO 標準?) では random/3
や seed/1
を定義する前に
:- dynamic seed/1.
としておく必要があります.
こうしておかないと retract/1
等で seed/1
を扱えません.
注記
Min
とMax
は整数である.16 ビットコンピュータではNewSeed
に関する整数オーバーフローを防ぐために,定義中の 4096 を 256 に置き換えること.
上記の定義ではランダム数生成の元となる数 (シード (seed) と呼ばれる) の初期値は定数としてある.しかし,たとえばシステム時間のような変数を用いれば,random
が呼ばれるたびに同じランダム数の列が作り出されるのを防げる.
ふむふむふむふむ.
定義中の
seed(7).
がシードの初期値を定義した定数になるわけですね.
例
では使用例を写経しませう.
2 ?- nl, repeat, random(1, 100, X), write(X), tab(2), X == 77. 8 77 X = 77 Yes
うーみゅ.
repeat
はバックトラックで制御が戻ってくる度にまた後続の節を実行する述語なので,random/3
の生成する乱数 X
が 77 になるまで延々繰り返すという事ですね.
そして最初に生成された乱数が 8.その次に生成された乱数が 77.終了.
あっけなさすぎるのでもう一度.
3 ?- nl, repeat, random(1, 100, X), write(X), tab(2), X == 77. 6 91 4 73 54 43 92 93 30 3 48 13 10 47 48 5 70 55 60 45 82 99 68 9 30 51 44 73 78 95 60 9 6 95 96 93 90 31 24 1 2 79 16 9 22 15 52 89 18 7 4 17 70 39 48 69 54 79 64 21 38 7 16 45 6 95 88 17 26 23 52 9 78 55 84 5 34 79 56 73 66 59 48 89 58 79 32 29 78 7 80 65 2 23 72 77 X = 77 Yes
お,それっぽい感じ.
さらにもう一度.
4 ?- nl, repeat, random(1, 100, X), write(X), tab(2), X == 77. 6 99 80 37 62 11 84 21 50 35 52 1 46 43 64 57 18 11 92 61 42 19 12 85 2 35 100 13 62 39 28 9 2 3 76 57 98 99 12 29 26 11 20 97 54 7 68 41 66 63 32 29 30 59 92 45 26 63 16 57 26 51 84 45 2 3 68 77 X = 77 Yes
いい感じ♪