第一章 練習問題
第一章の問題。Mozart/OZの紹介が多い。
1 計算機
(a)
declare X Y Z
X = 2 * 2 * 2 * 2 * 2 % 2 ** 5
Y = X * X * X * X * X % (2**5)**5
Z = Y * Y * Y * Y % ((2**5)**5)**4
{Show Z}
(b)
delcare X
X = 100 * 99 * .. * 1
{Show X}簡単にやる方法はない。
2 組み合わせの計算
(a)
declare
fun {Product From To}
if From == To then
From
else
From * {Product From+1 To}
end
end
fun {Comb N K}
{Product N-K+1 N} div {Product 1 K}
end
(b)
Combは先ほどの物と同じ。
fun {CombSmart N K}
if K > (N div 2) then
{Comb N N-K}
else
{Comb N K}
end
end
3 プログラムの正しさ
ちゃんと証明しきれていない気がする。
面倒なので、補助関数ShiftLeft、ShiftRight、AddListが正しいものとする。
4 プログラムの計算量
O(n**100)のプログラムが実用的か否か、という問題。
1.7節では特に述べられていない。
しかし計算量が高次の多項式であったとしても、増加率は指数の計算量には及ばないので、十分実用的であると考える。
5 遅延計算
停止しない。そのため、良い考えではない。
6 高階プログラミング
(a)
2行目(N=2)のとき{OpList Mul [0 1] [1 0]}を計算する。そのため、すべて0になる。
Mullを使うと、次のようになる。
[10 6235300 160344312228246705825060 49116946500844767398714340184254871599279813644844 505756353132539355991535788904396967700352784465846135098293311191732044 505756353132539355991535788904396967700352784465846135098293311191732044 49116946500844767398714340184254871599279813644844 160344312228246705825060 6235300 10]
(b)
proc {ShowPascal Op}
for I in 1..10 do
{Show {GenericPascal Op I}}
end
end
7 明示的状態
前者は23を、後者は44を表示する。
8 明示的状態と関数
間違っている理由は、毎回セルを作り初期化してしまっているから。
declare
local Acc
Acc = {NewCell 0}
in
fun {Accumulate N}
Acc := @Acc + N
@Acc
end
end
{Show {Accumulate 5}}
{Show {Accumulate 100}}
{Show {Accumulate 45}}
9 記憶域(memory store)
(a)
Supplements for "Concepts, Techniques, and Models of Computer Programming"にウェブサイトの補充ファイル
がおいてある。ファイル: booksuppl.oz。
この分量だっらコピペが楽。
declare
fun {NewStore}
D={NewDictionary}
C={NewCell 0}
proc {Put K X}
if {Not {Dictionary.member D K}} then
C:=@C+1
end
D.K:=X
end
fun {Get K} D.K end
fun {Size} @C end
in
storeobject(put:Put get:Get size:Size)
end
proc {Put S K X} {S.put K X} end
fun {Get S K} {S.get K} end
fun {Size S} {S.size} end
S ={NewStore}
{Put S 2 [22 33]}
{Show {Get S 2}}
{Show {Size S}}
(b)
local
S = {NewStore}
in
fun {FasterPascal N}
if N > {Size S} then L = {FasterPascal N-1} in
{Put S N L}
L
else
{Get S N}
end
end
end
(c)
fun {MyNewStore}
{NewCell nil}
end
proc {MyPut S Key Value}
S := (Key|Value)|@S
end
fun {MyGet S Key}
fun {Assoc L}
case L of (K1|Value)|T then
if K1 == Key then Value
else {Assoc T} end
else nil end
end
in
{Assoc @S}
end
(d)
proc {MyPut S Key Value}
if {MyGet S Key} == nil then _ = {Bump} in
S := (Key|Value)|@S
else
S := (Key|Value)|@S
end
end
fun {MySize}
{Read}
endMyPutが汚ないな。ノットイコールの書き方が分らない。
あと、この問題は1.13と1.3と間違えている。
10 明示的状態と並列性
(a)
1になることもあるはずだけれども、常に2が得られた。1の代入のほうが上に書いてあるからかな?
(b)
declare
C={NewCell 0}
thread {Delay 10} C:=1 end
thread C:=2 end
(c)
ここで言う「遅延技法」はlazyなやつではなく、Delayを挿入する技法のことだろう。
Delayを挿入しても結果は代らない。結果が得られるのが遅くなるだけ。