1 (* From the SML
/NJ benchmark suite
. *)
5 val testit
: TextIO.outstream
-> unit
7 structure Main
: BMARK
=
11 | map
f (a
::x
) = f a
:: map f x
13 exception ex_undefined
of string
14 fun error str
= raise ex_undefined str
16 fun accumulate f
= let
18 | foldf
a (b
::x
) = foldf (f a b
) x
24 fun consifp x a
= if p a
then a
::x
else x
26 rev
o accumulate consifp
[]
30 fun exists p
= let fun existsp
[] = false
31 |
existsp (a
::x
) = if p a
then true else existsp x
34 fun equal a b
= (a
= b
)
36 fun member x a
= exists (equal a
) x
42 fun revonto x
= accumulate (C cons
) x
44 fun length x
= let fun count n a
= n
+1 in accumulate count
0 x
end
46 fun repeat f
= let fun rptf n x
= if n
=0 then x
else rptf(n
-1)(f x
)
47 fun check n
= if n
<0 then error
"repeat<0" else n
50 fun copy n x
= repeat (cons x
) n
[]
52 fun spaces n
= concat (copy n
" ")
56 |
lexordset (a
::x
) = lexordset (filter (lexless a
) x
) @
[a
] @
57 lexordset (filter (lexgreater a
) x
)
58 and lexless(a1
:int,b1
:int)(a2
,b2
) =
59 if a2
<a1
then true else if a2
=a1
then b2
<b1
else false
60 and lexgreater pr1 pr2
= lexless pr2 pr1
62 let fun accumf sofar
[] = sofar
63 | accumf
sofar (a
::x
) = accumf (revonto
sofar (f a
)) x
67 (* finds coords which occur exactly
3 times
in coordlist x
*)
68 let fun f xover x3 x2 x1
[] = diff x3 xover
69 | f xover x3 x2
x1 (a
::x
) =
70 if member xover a
then f xover x3 x2 x1 x
else
71 if member x3 a
then f (a
::xover
) x3 x2 x1 x
else
72 if member x2 a
then f
xover (a
::x3
) x2 x1 x
else
73 if member x1 a
then f xover
x3 (a
::x2
) x1 x
else
74 f xover x3
x2 (a
::x1
) x
75 and diff x y
= filter (not
o member y
) x
76 in f
[] [] [] [] x
end
78 abstype generation
= GEN
of (int*int) list
80 fun alive (GEN livecoords
) = livecoords
81 and mkgen coordlist
= GEN (lexordset coordlist
)
82 and mk_nextgen_fn neighbours gen
=
83 let val living
= alive gen
84 val isalive
= member living
85 val liveneighbours
= length
o filter isalive
o neighbours
86 fun twoorthree n
= n
=2 orelse n
=3
87 val survivors
= filter (twoorthree
o liveneighbours
) living
88 val newnbrlist
= collect (filter (not
o isalive
) o neighbours
) living
89 val newborn
= occurs3 newnbrlist
90 in mkgen (survivors @ newborn
) end
94 fun neighbours (i
,j
) = [(i
-1,j
-1),(i
-1,j
),(i
-1,j
+1),
96 (i
+1,j
-1),(i
+1,j
),(i
+1,j
+1)]
98 local val xstart
= 0 and ystart
= 0
99 fun markafter n
string = string ^ spaces n ^
"0"
100 fun plotfrom (x
,y
) (* current position
*)
101 str (* current line being prepared
-- a
string *)
102 ((x1
,y1
)::more
) (* coordinates to be plotted
*)
104 then (* same line so extend str
and continue from y1
+1 *)
105 plotfrom(x
,y1
+1)(markafter(y1
-y
)str
)more
106 else (* flush current line
and start a new line
*)
107 str
:: plotfrom(x
+1,ystart
)""((x1
,y1
)::more
)
108 |
plotfrom (x
,y
) str
[] = [str
]
109 fun good (x
,y
) = x
>=xstart
andalso y
>=ystart
110 in fun plot coordlist
= plotfrom(xstart
,ystart
) ""
111 (filter good coordlist
)
116 fun coordlist
at (x
:int,y
:int) = let fun move(a
,b
) = (a
+x
,b
+y
)
117 in map move coordlist
end
118 val rotate
= map (fn (x
:int,y
:int) => (y
,~x
))
120 val glider
= [(0,0),(0,2),(1,1),(1,2),(2,1)]
121 val bail
= [(0,0),(0,1),(1,0),(1,1)]
123 let fun f i
= if i
=n
then (n
+n
-1,n
+n
)::(n
+n
,n
+n
)::nil
124 else (i
+i
,i
+i
+1)::(i
+i
+2,i
+i
+1)::f(i
+1)
125 in (0,0)::(1,0):: f
0
128 val genB
= mkgen(glider
at (2,2) @ bail
at (2,12)
129 @
rotate (barberpole
4) at (5,20))
131 fun nthgen g
0 = g | nthgen g i
= nthgen (mk_nextgen_fn neighbours g
) (i
-1)
134 [(2,20),(3,19),(3,21),(4,18),(4,22),(4,23),(4,32),(5,7),(5,8),(5,18),
135 (5,22),(5,23),(5,29),(5,30),(5,31),(5,32),(5,36),(6,7),(6,8),(6,18),
136 (6,22),(6,23),(6,28),(6,29),(6,30),(6,31),(6,36),(7,19),(7,21),(7,28),
137 (7,31),(7,40),(7,41),(8,20),(8,28),(8,29),(8,30),(8,31),(8,40),(8,41),
138 (9,29),(9,30),(9,31),(9,32)]
140 fun show pr
= (app (fn s
=> (pr s
; pr
"\n"))) o plot
o alive
142 fun doit () = show (fn _
=> ()) (nthgen gun
25000)
155 fun testit strm
= show (fn c
=> TextIO.output (strm
, c
)) (nthgen gun
50)