;; Caltech CS 1 Fall 2007
;; Scheme code used in Lecture 10 (10/31/07)
;; mvanier@cs.caltech.edu
;; Page 1 of 2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data Pairs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; represent result pairs
(define (make-result x y) (cons x y))
(define (get-x result) (car result))
(define (get-y result) (cdr result))

;; example use
(define a-result (make-result 3 4))
(get-x a-result)
(get-y a-result)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data Collection 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; sample data
(define my-results
  (list (make-result  4  7.8)
        (make-result  2  4.3)
        (make-result  5 10.2)
        (make-result  1  1.9)
        (make-result  3  6.0))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Design strategy for list processing procedures
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 1) Identify the inputs and outputs and write skeleton procedure
;; 2) Identify base cases and deal with them
;; 3) Figure out what to do with
;;    a) the first element of the list
;;    b) the rest of the list
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define (remove-by-x a-list x)
   (cond ((null? a-list) a-list)
         ((= (get-x (car a-list)) x)
          (cdr a-list))
         (else (cons (car a-list) 
                     (remove-by-x (cdr a-list) x)))))

;; use:
(define new-results (remove-by-x my-results 2))

;; Page 2 of 2
;; Adding elements to lists in descending order:

(define (insert-in-order new-result a-list)
  (cond ((null? a-list) (cons new-result a-list))
        ((goes-before? new-result (car a-list))
         (cons new-result a-list))
        (else 
         (cons (car a-list)
               (insert-in-order new-result (cdr a-list))))))

(define (goes-before? r1 r2)
  (> (get-x r1) (get-x r2)))

;; insertion sort
(define (insertion-sort a-list)
  (define (isort-helper unsorted sorted)
    (if (null? unsorted)
        sorted
        (isort-helper (cdr unsorted)
                      (insert-in-order 
                       (car unsorted) sorted))))
  (isort-helper a-list (list)))

;; merge sort
(define (merge-sort a-list)
  (if (or (null? a-list)  
          (null? (cdr a-list)))
      a-list
      (let ((h1 (even-half a-list))
            (h2 (odd-half  a-list)))     
        (merge-in-order (merge-sort c1)
                        (merge-sort c2)))))

(define (odd-half a-list)
  (cond ((null? a-list) (list))
        ((null? (cdr a-list))
         (cons (car a-list) (list)))
        (else 
         (cons (car a-list)
               (odd-half (cdr (cdr a-list)))))))

(define (even-half a-list)
  (if (null? a-list)
      (list)
      (odd-half (cdr a-list))))

(define (merge-in-order alist blist)
  (cond ((null? alist) blist)
        ((null? blist) alist)
        ((goes-before? (car alist)
                       (car blist))
         (cons (car alist)
               (merge-in-order (cdr alist) blist)))
        (else 
         (cons (car blist)
               (merge-in-order alist (cdr blist))))))
