#include "BUCASCS320.hats"
#define :: list0_cons
#define cons list0_cons
#define nil list0_nil
fun upto (m: int, n: int): list0 int =
if m > n then nil () else m :: upto (m+1, n)
fun prod (ns: list0 int): int = case+ ns of
| n :: ns => n * prod (ns) | nil () => 1
fun maxl (ns: list0 int): int = case- ns of
| n :: nil () => n
| n1 :: n2 :: ns =>
if n1 >= n2 then maxl (n1 :: ns) else maxl (n2 :: ns)
fun factl (n: int): int = prod (upto (1, n))
fun null {a:t@ype} (xs: list0 a): bool =
case+ xs of nil () => true | _ :: _ => false
fun{a:t@ype} hd (xs: list0 a): a =
let val- cons (x, _) = xs in x end
fun{a:t@ype} tl (xs: list0 a): list0 a =
let val- cons (_, xs) = xs in xs end
local
fun{a:t@ype} addlen (n: int, xs: list0 a): int =
case+ xs of | _ :: xs => addlen (n+1, xs) | nil () => n
in
fun{a:t@ype} length (xs: list0 a): int = addlen (0, xs)
end
fun{a:t@ype} take (xs: list0 a, i: int): list0 a =
case+ xs of
| x :: xs => if i > 0 then x :: take (xs, i-1) else nil ()
| nil () => nil ()
fun{a:t@ype} rtake
(xs: list0 a, i: int, taken: list0 a): list0 a =
case+ xs of
| x :: xs => if i > 0 then rtake (xs, i-1, x :: taken) else taken
| nil () => taken
fun{a:t@ype} drop (xs: list0 a, i: int): list0 a =
case+ xs of
| x :: xs => if i > 0 then drop (xs, i-1) else x :: xs
| nil () => nil ()
fun{a:t@ype}
revAppend (xs: list0 a, ys: list0 a): list0 a =
case+ (xs, ys) of
| (nil (), _) => ys
| (x :: xs, _) => revAppend (xs, x :: ys)
fun{a:t@ype} rev (xs: list0 a): list0 a = revAppend (xs, nil ())
fun{a:t@ype} concat (xss: list0 (list0 a)): list0 a =
case+ xss of xs :: xss => xs + concat xss | nil () => nil ()
fun{a,b:t@ype} zip (xs: list0 a, ys: list0 b): list0 @(a, b) =
case+ (xs, ys) of
| (x :: xs, y :: ys) => (x, y) :: zip (xs, ys) | (_, _) => nil ()
fun{a,b:t@ype} unzip (xys: list0 @(a, b)): (list0 a, list0 b) =
case+ xys of
| xy :: xys => let
val xsys = unzip<a,b> (xys) in (xy.0 :: xsys.0, xy.1 :: xsys.1)
end | nil () => (nil (), nil ())
typedef coinlst = list0 int
fun allChange (
coins: coinlst
, coinvals: coinlst
, amount: int
) : list0 coinlst =
case+ (coins, coinvals, amount) of
| (_, _, 0) => cons (coins, nil ())
| (_, nil (), amount) => nil ()
| (_, c :: coinsval, amount) =>
if amount < 0 then nil ()
else list0_append<coinlst> (
allChange (c :: coins, c :: coinvals, amount - c)
, allChange (coins, coinvals, amount)
)
staload Math = "libc/SATS/math.sats"
fun squares (r: int): list0 @(int, int) = let
typedef res_t = list0 @(int, int)
fun between (x: int, y: int):<cloref1> res_t = let
val diff = r - x * x
fun above (y: int):<cloref1> res_t =
if y > x then nil ()
else if y * y < diff then above (y+1)
else if y * y = diff then (x, y) :: between (x-1, y+1)
else between (x-1, y)
in
above y
end
val firstx = int_of_double ($Math.sqrt (double_of_int r))
in
between (firstx, 0)
end
fun quick (xs: list0 double): list0 double = case+ xs of
| nil () => xs
| _ :: nil () => xs
| a :: bs => let
fun partition (
left: list0 double, right: list0 double, bs: list0 double
) :<cloref1> list0 double =
case+ bs of
| nil () => quick left + cons (a, quick right)
| x :: xs =>
if x <= a then partition (x :: left, right, xs)
else partition (left, x :: right, xs)
in
partition (nil (), nil (), bs)
end
fun merge (xs: list0 double, ys: list0 double): list0 double =
case+ (xs, ys) of
| (nil (), _) => ys
| (_, nil ()) => xs
| (x :: xs, y :: ys) => begin
if x <= y then x :: merge (xs, y :: ys) else y :: merge (x :: xs, ys)
end
fun tmergesort (xs: list0 double): list0 double = case+ xs of
| nil () => xs
| _ :: nil () => xs
| _ => let
val k = list0_length<double> (xs) / 2 in
merge (tmergesort (take (xs, k)), tmergesort (drop (xs, k)))
end
implement main () = let
in
end