Comp210: Principles of Computing and Programming
Fall 2004 -- Lab #2,  define-struct functions   



;; within-two?: number, number --> boolean
;; Are m,n less than 2 apart?
;; (Difference of exactly 2 returns false.)
;;
(define (within-two? m n)
  (and (< (- m n) 2)
       (< (- n m) 2)))

(within-two? 99.8 101)
true

(within-two? 5 -5)
false

(within-two? 7 7)
true




;; fastest-runner: nonnegative-number -> symbol
;; Given a distance to run (in meters),
;; return the fastest runner on the team.
;;
(define (fastest-runner distance)
  (cond [(< distance  300)                            'Marianne]
        [(and (>= distance  300) (< distance  1000))  'Becca]
        [(and (>= distance 1000) (< distance 10000))  'Suzy]
        [>= distance 10000)                           'Yvonne]))

"Test fastest-runner."
(symbol=? (fastest-runner 10000) 'Yvonne)
(symbol=? (fastest-runner  8000) 'Suzy)
(symbol=? (fastest-runner  2000) 'Suzy)
(symbol=? (fastest-runner   200) 'Marianne)
(symbol=? (fastest-runner   999) 'Becca)




;; lion-pop-later: nonnegative-number --> nonnegative-number
;; Given this year's lion-population,
;; returns next year's lion-population, according to the model specified on
;; Lab02)
;;
(define (lion-pop-later pop-now)
  (cond ; Low population: 10% growth.
        [(< pop-now 800)                        (* 1.1  pop-now)]
        ; Moderate population: 2% growth.
        [(and (>= pop-now 800) (< pop-now 1100) (* 1.02 pop-now)]
        ; Overcrowding: -30% growth.
        [(>= pop-now 1100)                      (* 0.7  pop-now)]))

"Test lion-pop-later"
(= (lion-pop-later 0) 0)
(= (lion-pop-later 100) 110)
(= (lion-pop-later 700) 770)
(= (lion-pop-later 800) 816)
(= (lion-pop-later 1100) 770)
(= (lion-pop-later 10000) 7000)



(define-struct ppg (name color ferocity ca?))
;
; A Powerpuff Girl ("ppg") is:
;   (make-ppg symbol symbol number boolean)
; where name is the ppg's name,
; color is their color 
;   (presumably one of {'green,'blue,'red}, but perhaps different
;    if new ppgs are ever created)
; ferocity is their ferocity index, a number.
; and ca? is whether or not they're conflict avoidant.


"Examples of ppgs"
(make-ppg 'Buttercup 'green 90 false)
(make-ppg 'Blossom   'red   70 false)
(make-ppg 'Bubbles   'blue  77 true)




;; negotiates-well?: ppg -> boolean
;; Given a powerpuff girl, would she make a good negotiator?
;;
(define (negotiates-well? a-ppg)
  (< (ppg-ferocity a-ppg) 80))

"Test negotiates-well?:"
(negotiates-well? (make-ppg 'Buttercup 'green 90 false))
false

(negotiates-well? (make-ppg 'Blossom   'red   70 false))
true

(negotiates-well? (make-ppg 'Bubbles   'blue  77 true))
true
                   

;;; Optional Challenge version:
;; negotiates-well-v2?: ppg -> boolean
;; Given a powerpuff girl, would she make a good negotiator?
;;
(define (negotiates-well-v2? a-ppg)
  (or (ppg-ca? a-ppg)
      (and (> 80 (ppg-ferocity a-ppg))
           (> (ppg-ferocity a-ppg) 20))))   ; Alternately: (< 20 (ppg-ferocity a-ppg) 80)
#|
Using cond, this could be written with:
  (cond [(ppg-ca? a-ppg)              true]
        [(>= (ppg-ferocity a-ppg) 80) false]
        [(>= 20 (ppg-ferocity a-ppg)) false]
        [else                         true])
  Sorry for the weird phrasing of the >=; Unfortunately,
  in .html files the less-than would get swallowed.
|#

(negotiates-well-v2? (make-ppg 'buttercup 'green 90 false))
false

(negotiates-well-v2? (make-ppg 'blossom   'red   70 false))
true

(negotiates-well-v2? (make-ppg 'bubbles   'blue  77 true))
true
    
; We want to test somebody who is a conflict-avoidant but 
; not between 20 & 80 ferocity:
(negotiates-well-v2? (make-ppg 'didi 'rainbow 15 true))
true

; Also test ferocity below 20 and not avoidant:
(negotiates-well-v2? (make-ppg 'dexter    'white 10 false))
false




;; two-can-beat-up?: ppg, ppg, number --> boolean   
;; Can two ppg's combined take on a villain with toughness "v-toughness"?
;;
(define (two-can-beat-up? p1 p2 v-toughness)
    (>= (+ (ppg-ferocity p1) (ppg-ferocity p2))
        v-toughness))
    ; Note: perhaps adding the ferocities is not a good
    ; model; perhaps there is synergy for increased ferocity,
    ; or diminishing returns as you add ferocity.
    ; Ah well, this is a good model for now,
    ; and we can tweak it later for increased reality.

"Test two-can-beat-up?"

(two-can-beat-up? (make-ppg 'buttercup 'green 90 false)
                  (make-ppg 'bubbles   'blue  77 true)
                  110)
true

; Test when villain is totally wimpy:
(two-can-beat-up? (make-ppg 'buttercup 'green 90 false)
                  (make-ppg 'bubbles   'blue  77 true)
                  23)
true

(two-can-beat-up? (make-ppg 'buttercup 'green 90 false)
                  (make-ppg 'bubbles   'blue  77 true)
                  190)
false

; Test when villain is between the two ppg's ferocity:
(two-can-beat-up? (make-ppg 'buttercup 'green 90 false)
                  (make-ppg 'bubbles   'blue  77 true)
                  84)
true

; Test when villain is exactly the sum of the two ppg's ferocity:
; (Presumably both sides succesfully beat each other up.)
(two-can-beat-up? (make-ppg 'buttercup 'green 90 false)
                  (make-ppg 'bubbles   'blue  77 true)
                  (+ 90 77))
true



 
;;--------------------------------------------------------------
     "Optional Challenge problems"
     "(further tests should be true, or instances of structs.)"
;;
(define-struct villain (name power always-hungry? iq weakness))
;;
;; A villain is:
;;   (make-villain [symbol] [number] [boolean] [number] [symbol])
;; where power is the power-rating, iq is an IQ.
;; weakness describes the villain's achilles heel.
;; name and always-hungry? are self-evident.

; Examples of data:
(make-villain 'fuzzy-lumpkins 90 true 35 'witty-banter)
(make-villain 'mojo-jojo 35 false 190 'soliliquizing)


#|
;;;; TEMPLATE
;; villain-handler: villain --> ??
;;
(define (villain-handler a-villain)
  ..(villain-name a-villain) ..(villain-power a-villain)
  ..(villain-iq   a-villain) ..(villain-always-hungry? a-villain)
  ..(villain-weakness a-villain) )
|#



;; can-handle?: ppg, villain -> boolean
;; returns whether a-ppg could handle a-villain, one-on-one.
;; Peaceful resolutions count as 'handling'.
;;
(define (can-handle? a-ppg a-villain)
  (or (>= (ppg-ferocity a-ppg) (villain-power a-villain))    ; Combat resolution.
      (and (ppg-ca? a-ppg) (> (villain-iq a-villain) 150)))) ; Negotiation.

(boolean=? (can-handle? (make-ppg 'bubbles 'blue  77 true)
                        (make-villain 'fuzzy-lumpkins 90 true 35 'witty-banter))
           false)

(boolean=? (can-handle? (make-ppg 'bubbles 'blue  77 true)
                        (make-villain 'mojo-jojo 35 false 190 'soliliquizing))
           true)
; More test cases needed, to be confident.


; Data definition:   
; A Townsvillite is:
;  - a ppg, or
;  - a villain.

;; is-rash? : Townsvillite -> boolean
;; Is the Townsvillite prone to ill-considered, hot-tempered actions?
;;
(define (is-rash? townie)
  (cond [(ppg? townie) (not (ppg-ca? townie))]
        [(villain? townie) (> 120 (villain-iq townie))]
        [else (error 'is-rash? "Expected a Townsvillite, got ~s." townie)]))


(boolean=? (is-rash? (make-ppg 'bubbles 'blue  77 true))
           false)
(boolean=? (is-rash? (make-villain 'mojo-jojo 35 false 190 'soliliquizing))
           false)
(boolean=? (is-rash? (make-villain 'fuzzy-lumpkins 90 true 35 'witty-banter))
           true)

;; More test cases needed, to be confident.



(define-struct citizen (name gender))
; A Citizen is:
;   (make-citizen [symbol] [symbol])
; where gender is one of {'male, 'female}.

; Example data:
(make-citizen 'mayor 'male)
(make-citizen 'teacher 'female)   ;What is her name? Email ian@rice, thx.

;; Include citizen in the definition of Townsvillite,
;; and correspondingly update is-rash?:
; A Townsvillite is:
;  - a ppg, or
;  - a villain, or
;  - a citizen.

;; is-rash? : Townsvillite -> boolean
;; Is the Townsvillite prone to ill-considered, hot-tempered actions?
;;
(define (is-rash? townie)
  (cond [(ppg? townie) (not (ppg-ca? townie))]
        [(villain? townie) (> 120 (villain-iq townie))]
        ;[(citizen? townie) false]
        [(citizen? townie) false]
        [else (error 'is-rash? "Expected a Townsvillite, got ~s." townie)]))


(boolean=? false (is-rash? (make-citizen 'mayor 'male)))
; Plus we should repeat the previous test-cases,
; to see if bugs were introduced.
(boolean=? (is-rash? (make-ppg 'bubbles 'blue  77 true))
           false)
(boolean=? (is-rash? (make-villain 'mojo-jojo 35 false 190 'soliliquizing))
           false)
(boolean=? (is-rash? (make-villain 'fuzzy-lumpkins 90 true 35 'witty-banter))
           true)


Last Revised Friday, 03-Sep-2004 12:04:27 CDT

©2004 Stephen Wong and Dung Nguyen