演習問題が残ってた。
- 作者: Bruce A. Tate,まつもとゆきひろ,田和勝
- 出版社/メーカー: オーム社
- 発売日: 2011/07/23
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 230回
- この商品を含むブログ (64件) を見る
フィボナッチ数列は2つの連続する1で始まる。以降、それぞれの數は直前の2つの數の和になっている。1、1、2、3、5、8、13、21、…という具合だ。フィボナッチ数列のn番目の數を見つけるプログラムを書け。例えばfib(1)は1、fib(4)は3となる。また、この問題を再帰とループを用いて解け。
再帰(Recursive)のfibR
と、ループ(Loop)のfibL
。
fibR := method(n, if(n <= 2, 1, fibR(n - 1) + fibR(n - 2)) ) for(i, 1, 10, writeln("fibR(", i, ") = ", fibR(i)) ) fibL := method(n, if(n <= 2, return 1) n1 := 1 n2 := 1 f := 2 (n - 2) repeat(f = n1 + n2; n2 = n1; n1 = f) f ) for(i, 1, 10, writeln("fibL(", i, ") = ", fibL(i)) )
実行結果。
$ io self-study1.io fibR(1) = 1 fibR(2) = 1 fibR(3) = 2 fibR(4) = 3 fibR(5) = 5 fibR(6) = 8 fibR(7) = 13 fibR(8) = 21 fibR(9) = 34 fibR(10) = 55 fibL(1) = 1 fibL(2) = 1 fibL(3) = 2 fibL(4) = 3 fibL(5) = 5 fibL(6) = 8 fibL(7) = 13 fibL(8) = 21 fibL(9) = 34 fibL(10) = 55
分母がゼロのときゼロを返すように/演算子を変更するには、どうすればよいか。
Number div := Number getSlot("/") Number / := method(n, if(n == 0, 0, self div(n)) ) writeln("10 / 5 = ", 10 / 5) writeln("10 / 3 = ", 10 / 3) writeln("10 / 2 = ", 10 / 2) writeln("10 / 0 = ", 10 / 0)
実行結果。
$ io self-study2.io 10 / 5 = 2 10 / 3 = 3.3333333333333335 10 / 2 = 5 10 / 0 = 0
2次元配列のすべての要素の数値の総和を求めるプログラムを書け。
2次元配列の総和なのでsum2D
と名付けてみました。
Io> List sum2D := method(map(sum) sum) ==> method( map(sum) sum ) Io> list(list(1,2,3), list(4,5,6), list(7,8,9)) sum2D ==> 45
リストに、そのリストのすべての数値の平均を算出するスロットmyAverageを追加せよ。リストに数値が含まれていない場合は何が起こるか?(おまけ:リスト内に数値以外の項目を見つけたら、Io例外を発生させるようにしてみよ。)
単純な実装。
Io> List myAverage := method(select(type == Number type) average) ==> method( select(type == Number type) average ) Io> list(1,2,3,"one","two","three") myAverage ==> 2 Io> list("one","two","three") myAverage Exception: nil does not respond to '/' --------- nil / A3_List.io 6 List average Command Line 1 List myAverage Command Line 1
単純な実装では、数値が含まれないばあい例外が発生した。
数値以外が含まれていたら例外を発生させる。select
ですべての要素について数値か否かを調べているので効率は良くないと思う。
Io> List myAverage := method(if(select(type != Number type) size == 0, average, Exception raise("including not Number"))) ==> method( if(select(type != Number type) size == 0, average, Exception raise("including not Number")) ) Io> list(1,2,3) myAverage ==> 2 Io> list(1,2,3,"one","two","three") myAverage Exception: including not Number --------- Exception raise Command Line 1 List myAverage Command Line 1
2次元リストを実現するプロトタイプを書け。dim(x, y)メソッドは、要素数がxのリストyのリストを割り当てる。set(x, y, value)はリストに値を設定し、get(x, y)はリストの値を取得する。
ボーナス問題:(new_matrix get(y, x)) == matrix get(x, y)が成立するように、元のリストの転置メソッドを書け。
行列をファイルに書き出し、ファイルから行列を読み込め。
次のスクリプトを「Matrix.io」というファイル名で保存して、以降のスクリプトの実行はこのファイルがあるフォルダで実行するものとします。
Matrix := Object clone do( dim := method(x, y, matrix := Matrix clone matrix x := x matrix y := y matrix do( values := List clone setSize(y) for(i, 0, y - 1, values atPut(i, List clone setSize(x))) ) ) set := method(x, y, value, values at(y) atPut(x, value) ) get := method(x, y, values at(y) at(x) ) setValues := method( elems := call evalArgs i := 0 for(row, 0, y -1, for(col, 0, x - 1, self set(col, row, elems at(i)) i = i + 1 ) ) self ) transpose := method( matrix := dim(y, x) for(row, 0, y - 1, for(col, 0, x - 1, matrix set(row, col, get(col, row)) ) ) matrix ) asString := method( "[" .. values map(elem, "[" .. elem join(", ") .. "]") join(", ") .. "]" ) asScript := method( call target type .. " dim(" .. x .. ", " .. y .. ") setValues(" .. values map(join(", ")) join(", ") .. ")" ) )
行列を作って、値を入れて、転置する。
Io> m := Matrix dim(3,5) ==> [ [nil, nil, nil], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil] ] Io> for(y, 0, 4, for(x, 0, 2, m set(x, y, y * 3 + x))) ==> list(12, 13, 14) Io> m ==> [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14] ] Io> m transpose ==> [ [0, 3, 6, 9, 12], [1, 4, 7, 10, 13], [2, 5, 8, 11, 14] ]
ファイルへ保存。
m := Matrix dim(3, 5) for(y, 0, 4, for(x, 0, 2, m set(x, y, y * 3 + x) ) ) fileName := "matrix.txt" file := File with(fileName) openForUpdating file write(m asScript, "\n") file close
ファイルから読み出し。
fileName := "matrix.txt" file := File with(fileName) openForReading m2 := doString(file contents) file clone m2 println
実行結果。
$ io self-study6.io $ cat matrix.txt Matrix dim(3, 5) setValues(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) $ io self-study7.io [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14] ]
スクリプトの形で保存して読み込みはdoString
頼みってのがちょっとあざとい感じがしなくもないですが。それでもdoFile("matrix.txt")
とするのはこらえて、File
を使って読み出してみました。