;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;     Function Mergesort - relies on function merge, and recursion:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mergesort(x)
  "
;; Examples:
 (mergesort-tester 10)
 (mergesort-tester 20)
 (mergesort-tester 30)
"
  (let ((n (length x)))
    ;; if the list is of length 1, simply return it (no comparisons necessary)
    (if (= 1 n) x
      ;; otherwise,
      (let* (
	     ;; split the list -
	     (half (floor (/ n 2)))
	     (lhalf (select x (iseq half)))
	     (rhalf (select x (iseq half (- n 1))))
	     )
	;; and merge the two halves once they've been sorted:
	(merge
	 (mergesort lhalf)
	 (mergesort rhalf)
	 )
	)
      )
    )
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;    Function merge - merges two lists (recursive)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun merge(x y)
  ;; if either list is of length 0, then we can simply return the other half
  (if (or
       (= 0 (length x))
       (= 0 (length y))
       )
      ;; if x is empty, return y; else return x:
      (if (= 0 (length x)) y x)
    ;; otherwise, 
    (let ()
      ;; increment the (global) variable compares,
      (incf compares)
      ;; and compare the first elements: 
      (if (< (first x) (first y))
	  ;; we plop (first x) into the top spot, merge the rest, and combine
	  ;; the results into a single list:
	  (combine (list (first x) (merge (rest x) y)))
	;; otherwise, we plop (first y) into the top spot, merge the rest, and
	;; combine the results into a single list: 
	(combine (list (first y) (merge x (rest y))))
	)
      )
    )
  )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;   Function comparisons - simply calculates the theoretical "worst-case
;;   scenario"
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun comparisons(n) (- (* n (/ (ln n) (ln 2))) (- n 1)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;   Function mergesort-tester - tests mergesort
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mergesort-tester(n)
  (def compares 0)
  (def a (sample (iseq (* 2 n)) n))
  (print a)
  (print (mergesort a))
  (print compares)
  (print (comparisons n))
  nil
  )

#|
Some results of testing mergesort:

;; Examples:
 (mergesort-tester 10)
 (mergesort-tester 20)
 (mergesort-tester 30)

(5 1 2 12 11 9 7 14 0 8) 
(0 1 2 5 7 8 9 11 12 14) 
23 
24.219280948873624 
nil 
(20 4 33 3 27 28 9 32 0 6 22 39 17 23 13 26 36 14 25 11) 
(0 3 4 6 9 11 13 14 17 20 22 23 25 26 27 28 32 33 36 39) 
66 
67.43856189774725 
nil 
(46 12 22 19 38 8 25 42 15 29 59 28 57 49 5 58 44 20 3 18 31 51 14 21 1 41 33 36 24 23) 
(1 3 5 8 12 14 15 18 19 20 21 22 23 24 25 28 29 31 33 36 38 41 42 44 46 49 51 57 58 59) 
113 
118.20671786825557 
nil 
|#