;; The first three lines of this file were inserted by DrScheme.
;; They record information about the language level.
#reader(lib "plai-restricted-reader.ss" "plai")((modname solution-2) (read-case-sensitive #t) (teachpacks ()))
;; 11. Function which checks to see if each number in a list is 
;;    between 5 and 95 inclusive.

;; between? : check if a number is between 5 and 95 inclusive.
(define (between? x)
  (and (>= x 5) (<= x 95)))
(test (between? 3) false)
(test (between? 30) true)

(define (check-range list-temps)
  (if (empty? list-temps) 
      true
      (and (between? (first list-temps))
           (check-range (rest list-temps)))))

(test (check-range empty) true)
(test (check-range (list 20 32 55 90)) true)
(test (check-range (list 20 32 97 90)) false)


;; 12. Functions which convert a list of digits to the coresponding number.
(define (convert list-digits)
  (if (empty? list-digits)
      0
      (+ (first list-digits) (* 10 (convert (rest list-digits))))))
(test (convert empty) 0)
(test (convert (list 3 4 5)) 543)


;; 13. Function which average the values in a list.

;; sum-prices : adds together all the numbers in the list
(define (sum-prices list-prices)
  (if (empty? list-prices)
      0
      (+ (first list-prices) (sum-prices (rest list-prices)))))
(test (sum-prices empty) 0)
(test (sum-prices (list 1 2 3 4 5 6)) 21)

;; count-prices : count the number of items in the list
(define (count-prices list-prices)
  (if (empty? list-prices)
      0
      (+ 1 (count-prices (rest list-prices)))))
(test (count-prices empty) 0)
(test (count-prices (list 1 2 3 4 5 21)) 6)

(define (average-price list-prices)
  (/ (sum-prices list-prices) (count-prices list-prices)))
(test (average-price (list 1 2 3 4 5 6)) 3.5)


;; 14. Functions which convert a list of Celsius temperatures to
;;     Fahrenheit temperatures.

;; f2c : converts a Fahrenheit temperature to a Celsius temperature
(define (f2c tempF)
  (* (/ 5 9) (- tempF 32)))
(test (f2c 32) 0)
(test (f2c 212) 100)

(define (convertFC list-Ftemps)
  (if (empty? list-Ftemps)
      empty
      (cons (f2c (first list-Ftemps)) (convertFC (rest list-Ftemps)))))
(test (convertFC empty) empty)
(test (convertFC (list 32 212 98.6)) (list 0 100 37.0))


;; 15. Function which removes all items from a list which are greater
;;     than a user provided value.

(define (eliminate-exp lotp value)
  (if (empty? lotp)
      empty
      (if (<= (first lotp) value)
          (cons (first lotp) (eliminate-exp (rest lotp) value))
          (eliminate-exp (rest lotp) value))))
(test (eliminate-exp (list 1 2 3 4 5 6 5 4 3 2 1 20) 4)
      (list 1 2 3 4 4 3 2 1))

;; 16. Function which consumes a list [lst] and produces all the 
;;     suffixes of [lst].
(define (suffixes lst)
  (if (empty? lst) 
      (cons empty empty)
      (cons lst (suffixes (rest lst)))))
(test (suffixes (list 1 2 3 4))
      (list (list 1 2 3 4)
            (list 2 3 4)
            (list 3 4)
            (list 4)
            empty))


;; 17. Structure and data definitions which represent a family tree.
(define-type family-tree
  [unknown]
  [person (name string?) (birth-year number?)
          (eye-color symbol?) (mother family-tree?) (father family-tree?)])

(define example-tree
  (person "Dave" 1977 'brown
          (person "Ken" 1945 'brown
                  (unknown)
                  (unknown))
          (person "Mary Ellen" 1946 'brown
                  (unknown)
                  (unknown))))

(define test-tree
  (person "me" 1983 'blue
          (person "mom" 1964 'blue 
                  (unknown) 
                  (person "morgentaler" 1960 'brown (unknown) (unknown)))
          (unknown)))

;; 18. Function which counts the number of people in a family-tree.
(define (count-persons tree)
  (type-case family-tree tree
    [unknown () 0]
    [person (n birth eye mom dad)
            (+ 1 (count-persons mom) (count-persons dad))]))
(test (count-persons (unknown)) 0)
(test (count-persons example-tree) 3)
(test (count-persons test-tree) 3)


;; 19. Functions which computes the average age of the people in a family
;;     tree using the current year and their brith years.
(define (age-sum tree year)
  (type-case family-tree tree
    [unknown () 0]
    [person (n birth eye mom dad)
            (+ (- year birth) (age-sum mom year) (age-sum dad year))]))
(test (age-sum (unknown) 2004) 0)
(test (age-sum example-tree 2004) 144)
(test (age-sum test-tree 2004) 105)

(define (age-average tree year)
  (/ (age-sum tree year) (count-persons tree)))
(test (age-average example-tree 2004) 48)
(test (age-average test-tree 2004) 35)


;; 20. Function which creates a list of the eye-color of everyone 
;;     in a family-tree.
(define (eye-color tree)
  (type-case family-tree tree
    [unknown () empty]
    [person (n birth eye mom dad)
            (cons 
             eye
             (append (eye-color mom) (eye-color dad)))]))
(test (eye-color example-tree)
      (list 'brown 'brown 'brown))
(test (eye-color test-tree)
      (list 'blue 'blue 'brown))
