;; The first three lines of this file were inserted by DrScheme. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "reader.ss" "plai" "lang")
;; 1. Function to total the amount of change (pennies, nickels, dimes, quarters)
;;    in a bag.
(define (sum-coins pen nick dime quart)
  (+ (* .01 pen) (* .05 nick) (* .10 dime) (* .25 quart)))

(test (sum-coins 4 3 2 1) .64)



;; 2. Function to computer the surface aera of a cylinder.
(define (area-cylinder radius height)
  (+ (* 2 pi (sqr radius))
     (* 2 pi radius height)))

(test (area-cylinder 0 0) 0)
(test (area-cylinder 1 0) 6.28)
(test (area-cylinder 0 1) 0)
(test (area-cylinder 1 2) 18.85)



;; 3.a Surface area of a pipe computed as a single function.
(define (area-pipe1 inner-radius height thickness)
  (+ (* height 2 pi inner-radius)
     (* height 2 pi (+ thickness inner-radius))
     (* 2 (- (* pi (sqr (+ thickness inner-radius)))
             (* pi (sqr inner-radius))))))

(test (area-pipe1 0.5 0 0.5) 4.71)
(test (area-pipe1 0 2 1) 18.85)
(test (area-pipe1 1 2 1) 56.54)


;; 3.b Surface area of a pipe computed using helper functions.
(define (area-circle r) 
  (* pi r r))
(test (area-circle 2) 12.56)

(define (circumference r)
  (* 2 pi r))
(test (area-circle 2) 12.56)


(define (area-pipe inner-radius height thickness)
  (+ (* height (circumference (+ inner-radius thickness)))
     (* height (circumference inner-radius))
     (* 2 (- (area-circle (+ inner-radius thickness))
             (area-circle inner-radius)))))

(test (area-pipe1 0.5 0 0.5) 4.71)
(test (area-pipe1 0 2 1) 18.85)
(test (area-pipe1 1 2 1) 56.54)


;; 4. Function for computing tax.
(define (tax pay)
  (cond [(<= pay 240) 0]
        [(<= pay 480) (* pay .15)]
        [else (* pay .28)]))

(test (tax 0) 0)
(test (tax 241) 36.15)
(test (tax 480) 72)
(test (tax 500) 140)



;; 5. Function to determine if a quadratic equation is degenerate or not.
;;    If it is not degenerate it then computes whether the solution has
;;    2, 1, or 0 solutions.
(define (discriminant a b c)
  (- (sqr b) (* 4 a c)))

(define (what-kind? a b c)
  (cond [(= a 0) 'degenerate]
        [(> (discriminant a b c) 0) 'two]
        [(= (discriminant a b c) 0) 'one]
        [else 'none]))

(test (what-kind? 0 0 0) 'degenerate)
(test (what-kind? 1 0 0) 'one)
(test (what-kind? 1 2 3) 'none)
(test (what-kind? -1 2 3) 'two)


;; 6. Function to compute the difference in seconds between two points
;;    in time, using the structure time-point to represent hours, minutes
;;    and seconds.
(define-type Time-Point
  [time-point (hour number?) (min number?) (sec number?)])

;; in-seconds : converts hour, minutes and seconds representation of time into
;;              seconds.
(define (in-seconds t)
  (+ (time-point-sec t)
     (* 60 (time-point-min t))
     (* 60 60 (time-point-hour t))))

(test (in-seconds (time-point 1 2 3)) 3723)

;; time-diff : computes the difference in seconds between two time-point(s).
(define (time-diff t1 t2)
  (- (in-seconds t1) (in-seconds t2)))

(test (time-diff (time-point 1 2 3)
                 (time-point 1 2 3))
      0)

(test (time-diff (time-point 1 3 4)
                 (time-point 1 2 3))
      61)

(test (time-diff (time-point 2 3 4)
                 (time-point 1 2 3))
      3661)


;; 7. Struct and data definition for representing a point and a shape.
(define-type Point
  [point (x number?) (y number?)])

(define-type Shape
  [circle (center point?) (radius number?)]  
  [square (top-left point?) (length number?)]  
  [rect (top-left point?) (width number?) (height number?)])

(define c (circle (point 10 20) 2))
(define s (square (point 25 0) 2))
(define r (rect (point 30 15) 2 10))

;; 8. Function for finding the area of a shape.
(define (area s)
  (type-case Shape s
    [circle (c r) (* pi (sqr r))]
    [square (tl len) (sqr len)]
    [rect (tl w h) (* w h)]))

(test (area c) 12.56)
(test (area s) 4)
(test (area r) 20)


;; 9. Function which take a shape and return a new shape. The new shape
;;    is a copy of the old shape translated by a value in the x direction.

(define (point-add p x y)
  (point (+ (point-x p) x)
         (+ (point-y p) y)))

(test (point-add (point 3 4) 10 20)
      (point 13 24))

(define (translate-shape s delta)
  (type-case Shape s
    [circle (c r)
            (circle (point-add c delta 0) r)]
    [square (tl len)
            (square (point-add tl delta 0) len)]
    [rect (tl w h)
          (rect (point-add tl delta 0) w h)]))

(test (translate-shape c 10)
      (circle (point 20 20) 2))

(test (translate-shape s 10)
      (square (point 35 0) 2))

(test (translate-shape r 10)
      (rect (point 40 15) 2 10))

;; 10. Develop the function in-shape, which consumes a shape and a position p,
;;     and returns true if p is within the shape, false otherwise.

(define (distance p1 p2)
  (sqrt (+ (sqr (- (point-x p1) (point-x p2)))
           (sqr (- (point-y p1) (point-y p2))))))

(test (distance (point 1 1) (point 2 2)) 1.41)

(define (between? low x high)
  (and (<= low x) (<= x high)))

(define (in-shape? s p)
  (type-case Shape s
    [circle (c r) (< (distance c p) r)]
    [square (tl len) (and (between? 0 (- (point-x p) (point-x tl)) len)
                          (between? 0 (- (point-y p) (point-y tl)) len))]
    [rect (tl w h) (and (between? 0 (- (point-x p) (point-x tl)) w)
                        (between? 0 (- (point-y p) (point-y tl)) h))]))

(test (in-shape? c (point 11 20.5)) true)
(test (in-shape? c (point 21 22)) false)
(test (in-shape? s (point 26 1)) true)
(test (in-shape? s (point 24 1)) false)
(test (in-shape? r (point 31 17)) true)
(test (in-shape? r (point 33 17)) false)
(test (in-shape? r (point 29 17)) false)
(test (in-shape? r (point 31 26)) false)
(test (in-shape? r (point 31 14)) false)

