Skip to content

Commit

Permalink
Lots of new test cases based on wiki exercises.
Browse files Browse the repository at this point in the history
  • Loading branch information
aquark committed Feb 16, 2009
1 parent c862261 commit 333bd5f
Show file tree
Hide file tree
Showing 19 changed files with 640 additions and 1 deletion.
41 changes: 41 additions & 0 deletions OrcJava/examples/exercises/auction.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{--
Write a function which conducts an auction given
a list of "bidder" sites and a starting bid. An
auction consists of a number of bidding rounds
performed in sequence. A bidding round consists
of calling every bidder site in parallel, passing
the current maximum bid. Each bidder site may
return a higher value (a bid). The first caller
to return a higher bid sets a new maximum bid for
the next round. If no callers return a bid within
5 seconds, the auction (and round) ends. Your
function should return the value of the winning
bid.
--}

def auction(bidders, max) =
val (done, bid) =
Rtimer(100) >> (true, max)
| each(bidders) >bidder>
bidder(max) >bid>
if(bid > max) >>
(false, bid)
println("Current bid: " + max) >>
if done then max else auction(bidders, bid)

def bidder(max)(n) = if(n < max) >> n + 1
auction(map(lambda (_) = bidder(random(10)), range(0,10)), 1)

{-
OUTPUT:
Current bid: 1
Current bid: 2
Current bid: 3
Current bid: 4
Current bid: 5
Current bid: 6
Current bid: 7
Current bid: 8
Current bid: 9
9
-}
52 changes: 52 additions & 0 deletions OrcJava/examples/exercises/balance.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{--
Write a function which takes an input channel (in),
an output channel (out), and a list of sites (ps)
as arguments. The function must repeatedly read an
input value from in, call one of the sites in ps
with the value (using each site in the list in turn),
and write the result to out. The order values are
written to the output channel must correspond to the
order values were received on the input channel.
--}

def balance(in, out, ps) =
val bs = map(ignore(Buffer), ps)
def write(b:bs) = out.put(b.get()) >> write(append(bs, [b]))
def read((p,b):pbs) =
( in.get() ; b.close() >> stop ) >x>
( b.put(p(x)) >> stop | read(append(pbs, [(p,b)])) )
write(bs) | read(zip(ps,bs))

val in = Buffer()
val out = Buffer()
def compute(n)(x) = println("Site " + n) >> x*x

( balance(in, out, [compute(1), compute(2), compute(3), compute(4)])
; out.close() >> stop )
| ( upto(10) >n> in.put(n) >> stop
; in.close() >> stop )
| repeat(out.get)

{-
OUTPUT:
Site 1
0
Site 2
1
Site 3
4
Site 4
9
Site 1
16
Site 2
25
Site 3
36
Site 4
49
Site 1
64
Site 2
81
-}
34 changes: 34 additions & 0 deletions OrcJava/examples/exercises/bfs.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{--
You are given a data type for binary trees with the
constructors <code>Tree(left, value, right)</code> and
<code>Leaf()</code>. Write a function which, given a tree,
returns a list of values in the tree ordered by
depth. I.e. the first element should be the root
value, followed by the root's children, followed by
its grandchildren, and so on.
--}

type Tree = Tree(_, _, _) | Leaf()

def levels(tree) =
def helper([]) = []
def helper(Leaf():rest) = helper(rest)
def helper(Tree(l,v,r):rest) =
v:helper(append(rest, [l, r]))
helper([tree])

levels(Tree(
Tree(
Tree(Leaf(), 3, Leaf()),
2,
Tree(Leaf(), 3, Leaf())),
1,
Tree(
Tree(Leaf(), 3, Leaf()),
2,
Tree(Leaf(), 3, Leaf()))))

{-
OUTPUT:
[1, 2, 2, 3, 3, 3, 3]
-}
39 changes: 39 additions & 0 deletions OrcJava/examples/exercises/counter.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{--
Write a program with three functions: inc, dec, and read.
Each of these functions modifies a shared state which is
a natural number (n), initially = 0. When inc is called,
increment n. When dec is called, decrement n. When read
is called, publish the value of n. Each of these
functions must act atomically, so that the expression
<code>inc() | dec()</code> is guaranteed to leave the
counter state unchanged after it completes.

Hint: use a semaphore to control access to the shared state.
--}

val n = Ref(0)
val lock = Semaphore(1)

def inc() =
lock.acquire() >>
n := n? + 1 >>
lock.release()

def dec() =
lock.acquire() >>
n := n? - 1 >>
lock.release()

def read() =
lock.acquire() >>
n? >out>
lock.release() >>
out

inc() >> signals(10) >> (inc(), dec()) >> stop
; read()

{-
OUTPUT:
1
-}
16 changes: 16 additions & 0 deletions OrcJava/examples/exercises/firstn.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{--
Write a function which, given a number (n) and a channel (c),
returns a list of the first n values received from c.
--}

def firstN(0, c) = []
def firstN(n, c) = c.get() >x> x:firstN(n-1, c)

val c = Buffer()
firstN(5, c)
| upto(10) >n> c.put(n) >> stop

{-
OUTPUT:
[0, 1, 2, 3, 4]
-}
28 changes: 28 additions & 0 deletions OrcJava/examples/exercises/firstnpub.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{--
Write a program which calls a definition f, which
may publish multiple values. Publish the first 10
values published by <code>f()</code>, and then
terminate the call to f.
--}

{- Publish first n values received on c, then release s -}
def allow(0, c, s) = c.closenb() >> s.release() >> stop
def allow(n, c, s) = c.get() >x> ( x | allow(n-1, c, s) )

{- Example f -}
def f() = upto(10) >x> Rtimer(x) >> x

{- Main program -}
val c = Buffer()
val s = Semaphore(0)
allow(5, c, s) <<
s.acquire() | f() >x> c.put(x) >> stop

{-
OUTPUT:
0
1
2
3
4
-}
20 changes: 20 additions & 0 deletions OrcJava/examples/exercises/forkjoin.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{--
Write a function which, given a list of sites, calls
each site in the list in parallel and publishes a
signal when all site calls have returned.
--}

def forkjoin([]) = signal
def forkjoin(f:rest) = (f(), forkjoin(rest)) >> signal

def example() = println("called")
forkjoin([example, example, example, example])

{-
OUTPUT:
called
called
called
called
signal
-}
34 changes: 34 additions & 0 deletions OrcJava/examples/exercises/hanoi.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{--
Write a function to solve the
<ulink url="http://en.wikipedia.org/wiki/Tower_of_Hanoi">Towers of Hanoi</ulink>
problem. There are three pegs, numbered 0..2;
disks are to be moved from peg 0 to peg 2. Your
function should take as its argument the number
of disks initially on peg 0, and it should return
a list of moves, where a move is a tuple (source
peg number, destination peg number), e.g. <code>(0,1)</code>.
Since the point of this exercise is to practice Orc,
not solve puzzles, feel free to use the algorithm
given in Wikipedia.
--}

{--
Algorithm as described in
http://en.wikipedia.org/wiki/Tower_of_Hanoi
--}
def hanoi(n) =
{- arguments: h(eight), f(rom peg),
r(emaining peg), t(o peg), m(ove)s -}
def move(1, f, r, t, ms) = (f,t):ms
def move(h, f, r, t, ms) =
move(h-1, f, t, r, ms) >ms>
move(1, f, r, t, ms) >ms>
move(h-1, r, f, t, ms)
reverse(move(n, 0, 1, 2, []))

hanoi(3)

{-
OUTPUT:
[(0, 2), (0, 1), (2, 1), (0, 2), (1, 0), (1, 2), (0, 2)]
-}
14 changes: 14 additions & 0 deletions OrcJava/examples/exercises/length.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{--
Write a function which, given a list, returns
the number of elements in the list.
--}

def length([]) = 0
def length(x:xs) = 1 + length(xs)

length([0,0,0,0])

{-
OUTPUT:
4
-}
46 changes: 46 additions & 0 deletions OrcJava/examples/exercises/ls.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{--
You are given the site <code>ls(x)</code> which returns
a list of file names found in the directory named
by the path <code>x</code>, or an empty list if <code>x</code> is
not a directory. Paths are written as strings
using POSIX conventions, e.g. "/foo/bar/baz".
So for example <code>ls("/usr/")</code> might return
<code>["local/", "bin/", "lib/]</code>. Unlike POSIX, you
can assume that directory paths always end in "/".
Write a function <code>find(x)</code> which returns a list
of all paths in the directory tree starting at the
given path. E.g. <code>find("/")</code> might return
<code>["/", "/usr/", "/usr/bin/", "/usr/bin/ls"]</code>.
--}
{--
Example ls function which lists
files in directories: results are
hard-coded.
--}
def ls("/") = ["usr/", "bin/", "lib/"]
def ls("/usr/") = ["local/", "bin/", "lib/"]
def ls("/usr/bin/") = ["ls", "sh", "find"]
def ls(_) = []
-------- main program ------
{-
This implementation makes use of map
and foldr to achieve a much more concise
and readable solution.
-}
def flatten(lists) = foldr(append, [], lists)
def find(root) =
def resolve(file) = root + file
root:flatten(map(find, map(resolve, ls(root))))
find("/")
{-
OUTPUT:
[/, /usr/, /usr/local/, /usr/bin/, /usr/bin/ls, /usr/bin/sh, /usr/bin/find, /usr/lib/, /bin/, /lib/]
-}
45 changes: 45 additions & 0 deletions OrcJava/examples/exercises/monitor.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{--
Write a program with two functions: dec and wait.
These functions share a state which is a natural number
(n), initially = 5. When <code>dec()</code> is called,
decrement n. When <code>wait()</code> is called, wait until
<code>n = 0</code> and then publish a signal. Write the program
without using <code>Ref</code>.

Hint: create a single process running in the background which
manages the shared state.
--}

val m = Buffer()
type Message = Dec() | Wait(_)
def actor(n, waiters) =
def on(Dec()) =
if n = 1 then join(waiters)
else actor(n-1, waiters)
def on(Wait(callback)) =
if n = 0 then callback()
else actor(n, callback:waiters)
on(m.get())

def dec() = println("Decrementing") >> m.put(Dec())
def wait() =
val b = Semaphore(0)
b.acquire() | m.put(Wait(b.release)) >> stop

actor(5, []) >> stop
| dec() >> stop
| dec() >> stop
| dec() >> stop
| dec() >> stop
| Rtimer(100) >> dec() >> stop
| wait() >> "Zero!"

{-
OUTPUT:
Decrementing
Decrementing
Decrementing
Decrementing
Decrementing
Zero!
-}
Loading

0 comments on commit 333bd5f

Please sign in to comment.