(*****************************************************)
(* reverse a list, 
   example:  reverse ([1, 2, 3, 4]);
 *)

fun reverse (nil) = nil
  | reverse (x::xs) = reverse (xs) @ [x] ;

val x = [ true, false, false, false];

reverse x;

(******************************************************)
(* padd (P, Q)  returns polynomial sum P + Q
   for P=  x^2 - 2 x + 3, use val P = [3.0, ~2.0, 1.0]
   example: padd (P, [1.0, 10.0, 100.0])
 *)

fun padd (p, nil) = p
 |  padd (nil, q) = q
 |  padd ((p: real) :: ps, q :: qs ) = (p + q) :: padd (ps, qs);

val x = [ 3.0, ~2.0, 1.0 ];  (* x^2 - 2x + 3 *)
padd (x, [1.0, 1.0, 1.0 ]);  

(******************************************************)
(* smult (P, s) multiples polynomial P by scalar s
   example: smult ( [3.0, ~2.0, 1.0], ~10.0)
 *)

fun smult (nil, s) = nil
 |  smult ( (p:real) :: ps, s) = (p*s) :: smult(ps, s);

val x = [1.0, 10.0, 100.0];
val scalar = 5.0;

smult (x, scalar);


(******************************************************)
(* pmult(P, Q) produces P*Q, polynomial multiply
   example: pmult( [1.0, 10.0], [2.0, 20.0] )
 *)

fun pmult (p, nil) = nil
 |  pmult (p, q::qs) = padd (smult (p, q), 0.0 :: pmult (p, qs) );

pmult( [1.0, 10.0], [2.0, 20.0] );

(********************************************************)
(* merge (L1, L2) mergest two sorted integer lists into
   one sorted list
   example: merge ( [5, 10, 15, 20], [ 2, 12, 22] )
 *)

fun merge (nil, y) = y
 |  merge (x, nil) = x
 |  merge (x :: xs, y :: ys) =
       if (x : int) < y then x :: merge (xs, y :: ys)
                        else y :: merge (x :: xs, ys);

merge ( [5, 10, 15, 20], [2, 12] );

(******************************************************)
(* sumPairs ( [ (a, b), (c, d) ] ) returns the sum of the
   sum of each pair, i.e. (a+b) + (c+d)
   example: sumPairs ( [ (1, 2), (3, 4), (5, 6), (7, 8) ] ) --> 36
 *)

fun sumPairs (nil) = 0
 |  sumPairs ((x, y) :: zs) = x + y + sumPairs(zs);

sumPairs ( [ (1, 2), (3, 4), (5, 6), (7, 8) ] );

(*****************************************************)
(* sumLists ( [ L1, L2, L3, ... ] ) returns the sum of the
   integer elements of the lists. 
   example: sumLists ( [ [1, 2], nil, [3, 4, 5], [6], [7, 8, 9] ] ) --> 45
 *)

fun sumLists (nil) = 0
 |  sumLists (nil :: ys) = sumLists (ys)   (* the first element in the parameter is the empty list *)
 |  sumLists ((x :: xs) :: ys ) = x + sumLists ( xs :: ys);

sumLists ( [ [1, 2], nil, [3, 4, 5], [6] ] );
sumLists ( [ [1, 2], nil, [3, 4, 5], [6], [7, 8, 9]]);
