Chapter #10 Examples in Oz
% Utility functions
fun {RandomInt Min Max}
X = {OS.rand}
MinOS
MaxOS
in
{OS.randLimits ?MinOS ?MaxOS}
Min + X*(Max - Min) div (MaxOS - MinOS)
end
{OS.srand 0}
proc {Exchange A I J}
X = A.I
in
A.I := A.J
A.J := X
end
proc {While Expr Stmt}
if {Expr} then {Stmt} {While Expr Stmt} end
end
% 10.1 Stacks
fun {MakeStack MaxStack}
stack(data:{NewArray 0 MaxStack-1 _} top:{NewCell 0})
end
fun {StackEmpty S}
if @(S.top) == 0 then
true
else
false
end
end
proc {Push S X}
(S.top) := @(S.top) + 1
(S.data).(@(S.top)) := X
end
fun {Pop S}
if {StackEmpty S} then
raise "underflow" end
else
(S.top) := @(S.top) - 1
(S.data).(@(S.top)+1)
end
end
local
S = {MakeStack 100}
in
{Push S 1234}
{Push S 5678}
{Browse 'Stack'#{Pop S}}
{Browse 'Stack'#{Pop S}}
end
% 10.1 Queues
fun {MakeQueue MaxQueue}
queue(data:{NewArray 0 MaxQueue-1 _} head:{NewCell 1} tail:{NewCell 1})
end
proc {Enqueue Q X}
Q.data.(@(Q.tail)) := X
if @(Q.tail) == {Array.high Q.data} then
(Q.tail) := 1
else
(Q.tail) := @(Q.tail) + 1
end
end
fun {Dequeue Q}
X = Q.data.(@(Q.head))
Q.data.(@(Q.head)) = _
in
if @(Q.head) == {Array.high Q.data} then
(Q.head) := 1
else
(Q.head) := @(Q.head) + 1
end
X
end
local
Q = {MakeQueue 100}
in
{Enqueue Q 1234}
{Enqueue Q 5678}
{Browse 'Queue'#{Dequeue Q}}
{Browse 'Queue'#{Dequeue Q}}
end
% 10.2 Linked Lists
fun {MakeLinkedList}
linkedlist(head:{NewCell nil})
end
fun {MakeLinkedListNode K X}
linkedlistnode(key:K data:X next:{NewCell nil} prev:{NewCell nil})
end
fun {ListSearch L K}
X = {NewCell @(L.head)}
in
{While
fun {$} @X \= nil andthen @X.key \= K end
proc {$} X := @(@X.next) end}
@X
end
proc {ListInsert L X}
(X.next) := @(L.head)
if @(L.head) \= nil then
(@(L.head).prev) := X
end
(L.head) := X
(X.prev) := nil
end
proc {ListDelete L X}
if @(X.prev) \= nil then
(@(X.prev).next) := @(X.next)
else
(L.head) := @(X.next)
end
if @(X.next) \= nil then
(@(X.next).prev) := @(X.prev)
end
end
local
L = {MakeLinkedList}
in
{ListInsert L {MakeLinkedListNode 1 1234}}
{ListInsert L {MakeLinkedListNode 2 3456}}
{ListInsert L {MakeLinkedListNode 3 5678}}
{ListDelete L {ListSearch L 2}}
{Browse 'LinkedList'#{ListSearch L 1}}
{Browse 'LinkedList'#{ListSearch L 3}}
{Browse 'LinkedList'#{ListSearch L 2}}
end
% 10.2 Linked List with sentinel
fun {MakeSentinelLinkedList}
Sentinel = null(next:{NewCell _} prev:{NewCell _})
in
(Sentinel.next) := Sentinel
(Sentinel.prev) := Sentinel
sentinallinkedlist(sentinel:Sentinel)
end
fun {SentinelListSearch L K}
X = {NewCell @((L.sentinel).next)}
in
{While
fun {$} @X \= L.sentinel andthen @X.key \= K end
proc {$} X := @(@X.next) end}
@X
end
proc {SentinelListInsert L X}
(X.next) := @((L.sentinel).next)
(@((L.sentinel).next).prev) := X
((L.sentinel).next) := X
(X.prev) := L.sentinel
end
proc {SentinelListDelete L X}
(@(X.prev).next) := @(X.next)
(@(X.next).prev) := @(X.prev)
end
local
L = {MakeSentinelLinkedList}
in
{SentinelListInsert L {MakeLinkedListNode 1 1234}}
{SentinelListInsert L {MakeLinkedListNode 2 3456}}
{SentinelListInsert L {MakeLinkedListNode 3 5678}}
{SentinelListDelete L {SentinelListSearch L 2}}
{Browse 'SentinelLinkedList'#{SentinelListSearch L 1}}
{Browse 'SentinelLinkedList'#{SentinelListSearch L 3}}
{Browse 'SentinelLinkedList'#{SentinelListSearch L 2}}
end
% 10.3 Pointers
Free = {NewCell 0}
Next = {NewArray 0 10 _}
Key = {NewArray 0 10 _}
Prev = {NewArray 0 10 _}
proc {InitObject}
for I in {Array.low Next}..({Array.high Next}-1) do
Next.I := I + 1
end
end
{InitObject}
fun {AllocateObject}
if @Free == nil then
raise error('out of stack space') end
else
local
X = @Free
in
Free := Next.X
X
end
end
end
proc {FreeObject X}
Next.X := @Free
Free := X
end
L = {NewCell {AllocateObject}}
Next.@L := {AllocateObject}
Prev.@L := nil
Key.@L := 10
Next.(Next.@L) := {AllocateObject}
Prev.(Next.@L) := @L
Key.(Next.@L) := 20
Next.(Next.(Next.@L)) := nil
Prev.(Next.(Next.@L)) := @L
Key.(Next.(Next.@L)) := 30
{Browse 'Pointers'#Key.@L#Key.(Next.@L)#@Free}
% 10.4 Compact List Search
fun {CompactListSearch L N K}
Return = {NewCell nil}
I = {NewCell L}
in
{While
fun {$} @Return == nil andthen @I \= nil andthen Key.@I < K end
proc {$}
J = {NewCell {RandomInt 0 N}}
in
if Key.@I < Key.@J andthen Key.K =< K then
I := @J
if Key.@I == K then
Return := @I
else
I := Next.@I
end
else
I := Next.@I
end
end}
if @Return \= nil then
@Return
elseif @I == nil orelse Key.@I > K then
nil
else
@I
end
end
{Browse 'CompactListSearch'#{CompactListSearch @L 2 20}}
% 10.4 Compact List Search'
fun {CompactListSearch_ L N K T}
Return = {NewCell nil}
I = {NewCell L}
in
for Q in 1..T do
local
J = {RandomInt 0 N}
in
if @Return == nil andthen Key.@I < Key.J andthen Key.J =< K then
I := J
if Key.@I == K then
Return := @I
end
end
end
end
if @Return \= nil then
@Return
else
{While
fun {$} @I \= nil andthen Key.@I < K end
proc {$}
I := Next.@I
end}
if @I == nil orelse Key.@I > K then
nil
else
@I
end
end
end
{Browse 'CompactListSearch_'#{CompactListSearch_ @L 2 20 5}}
|