Scheme の練習。100 個の乱数のリスト。

Scheme の練習中。
やりたいこと:

100 個の要素を持つリストを作りたい。
各要素は、0 から 99 までの整数から、ランダムに選んだやつにしたい。

とりあえず書いてみた(正しく動かない版)

random100.scm

#! /usr/local/bin/gosh
(use srfi-27)

(define (main args)
  (define lis (make-list 100 (random-integer 100)))

  (print lis)

  0)

実行してみた:

%./random100.scm
(81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81)
%./random100.scm
(81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81)
%./random100.scm
(81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81)
%

いろいろ間違ってるぽい。

問題は以下の 2 点

  1. ./random100.scm を起動するたびに、毎回同じ値になってる。
  2. リストの要素が全部同じ値になってる。

問題点 1 をなんとかする

起動するたびに、同じ値を返してしまうという問題は、こうすればよいらしい。
random100.scm

#! /usr/local/bin/gosh
(use srfi-27)

(random-source-randomize! default-random-source) ; <<<=== ここだけ追加した。

(define (main args)
  (define lis (make-list 100 (random-integer 100)))

  (print lis)

  0)

実行してみた:

%./random100.scm
(78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78)
%./random100.scm
(88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88)
%./random100.scm
(68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68)
%

random-source-randomize! を使うと、現在の時刻とプロセス ID を使って乱数発生源をかき回すらしい。

問題点 2 をなんとかする

リストの中身が全部同じ値で埋め尽くされているのは、(random-integer 100) の評価が行われてから、その値が make-list 手続きで使われているから。そもそも make-list を選んだのが間違い。

srfi-1 の中にこういうのを発見:

list-tabulate n init-proc

[SRFI-1] n個の要素をもつリストを構築し、それぞれの要素を (init-proc i) で生成します。

「値」を渡すのではなく、「値を作り出す手続き」を渡してあげる、ってことですね。これが欲しかった。

完成

random100.scm

#! /usr/local/bin/gosh
(use srfi-1)
(use srfi-27)

(random-source-randomize! default-random-source)
(define (main args)
  (define lis
    (list-tabulate 100
                   (lambda (dummy)
                     (random-integer 100))))

  (print lis)

  0)

実行してみた:

%./random100.scm
(80 76 79 38 62 94 95 91 24 99 21 94 29 4 18 14 2 19 64 5 10 57 59 6 98 81 41 82 29 75 82 78 56 37 58 30 83 37 39 66 26 67 87 60 2 26 25 41 66 52 52 2 59 64 16 83 55 69 19 42 38 20 11 8 79 87 25 43 48 53 82 65 59 29 24 44 14 88 77 77 9 71 98 58 37 64 2 2 51 87 21 28 44 24 78 29 51 61 83 96)
%./random100.scm
(1 14 25 28 11 39 15 34 73 38 58 81 11 17 70 87 25 18 1 6 54 57 26 7 59 43 88 42 11 56 82 52 8 47 42 67 82 23 83 88 47 86 11 42 20 93 53 19 38 2 28 40 5 38 79 41 36 44 23 53 48 6 90 79 6 71 38 94 62 77 9 54 57 65 6 20 87 32 49 35 69 92 45 34 75 89 0 98 80 66 30 57 79 21 20 5 64 19 47 43)
%./random100.scm
(8 55 78 57 54 50 86 16 35 16 58 49 55 24 67 67 36 45 93 91 41 7 86 55 12 38 53 26 40 18 0 90 29 97 88 11 99 65 15 69 55 96 66 98 38 50 85 95 31 83 33 53 72 51 72 44 94 78 95 64 63 23 75 44 65 87 17 36 63 29 10 47 70 79 24 45 12 4 9 73 62 34 35 15 5 93 20 48 11 41 71 57 55 94 23 10 34 33 38 55)
%