;;1. ;; per-person-fee: number -> number ;; takes in the size of the group of people and ;; returns the price per person to enter the ;; amusement park ;; 1 person = $30 ;; 2-4 people = $25 each ;; 5-10 people = $20 each ;; > 10 people = $15 each (define (per-person-fee num) (cond [(number? num) (cond [(= 1 num) 30] [(and (< 1 num) (> 5 num)) 25] [(and (< 5 num) (> 11 num)) 20] [(< 10 num) 15])])) ;; test cases (eq? (per-person-fee 1) 30) (eq? (per-person-fee 3) 25) (eq? (per-person-fee 4) 25) (eq? (per-person-fee 10) 20) (eq? (per-person-fee 60) 15) ;;2a. ;; translate-posn: posn, num, num -> posn ;; Return the point which is a-point offset by (+x, +y). ;; (define p34 (make-posn 3 4)) (define origin (make-posn 0 0)) (define (translate-posn a-point x y) (make-posn (+ (posn-x a-point) x) (+ (posn-y a-point) y))) ;; test cases (make-posn 8 16) (translate-posn p34 5 12) p34 (translate-posn origin 3 4) origin (translate-posn p34 -3 -4) ;;2b ; A color is one of {'red, 'yellow, 'white, 'black, 'blue, 'green}. ; ; Examples of color: (explicitly enumerated in data def'n). ;It's fine to write this in this notation, rather than taking six lines. ;Fortunately, we don't have to write a template for colors, ;since we don't write any functions which process them. ;(That definitely would need a six-line cond!)) (define-struct circle (location radius color)) ; ; A circle is: ; (make-circle posn num symbol color) ;;(Note how we've already given data defs for posns and colors, ;;which is why we cavalierly refer to them as known data types.) ; Examples of circles: ; (define circ1 (make-circle p34 1 'red)) ; A little red dot. (define circ23 (make-circle origin 23 'blue)) ;;2c. (define-struct rectangle (location width height color)) ;A rectangle is: ; (make-rectangle posn num num color) ; ;Examples: (define rect1 (make-rectangle (make-posn 10 10) 15 30 'yellow)) (define rect2 (make-rectangle (make-posn 0 0) 2 2 'red)) ;;2d. ;; A shape is a structure that contains ;; - a circle, or ;; - a rectangle ;; Examples of shapes: ;; circ1 circ23 rect1 rect2 ;; Template: ;; #| (define (shape-func a-shape) (cond [(circle? a-shape) ..(circle-location a-shape).. ..(circle-radius a-shape).. ..(circle-color a-shape)..] [(rectangle? a-shape) ..(rectangle-location a-shape).. ..(rectangle-width a-shape).. ..(rectangle-height a-shape).. ..(rectangle-color a-shape)..])) |# ;; 2e. ;; perimeter: Shape -> num ;; Return a-shape's perimeter. ;; (define (perimeter a-shape) (cond [(circle? a-shape) (* 2 pi (circle-radius a-shape))] [(rectangle? a-shape) (+ (* 2 (rectangle-height a-shape)) (* 2 (rectangle-width a-shape)))])) ;; Test cases. ;; (perimeter (make-circle (make-posn 0 0) 5 'blue )) (= 14 (perimeter (make-rectangle (make-posn 0 0) 3 4 'black))) ;;2f. ;; in?: shape, posn -> boolean ;; Is a-posn located inside of a-shape? ;; (We'll consider the edge as NOT being inside, unlike tennis.) ;; (define (in? a-shape a-posn) (cond [(circle? a-shape) (< (distance (circle-location a-shape) a-posn) (circle-radius a-shape))] [(rectangle? a-shape) (and (< 0 (distance-x (rectangle-location a-shape) a-posn) (rectangle-width a-shape)) (< 0 (distance-y (rectangle-location a-shape) a-posn) (rectangle-height a-shape)))])) #| Notes: This function took in a Shape and Posn, but which template did we use? Shape; we ended up only passing along a-posn to other functions and never dissected it. (Though it's okay if you did; in this case it's even okay if you looked at (posn-x (rectangle-location a-shape)).) Notice how well-chosen helper functions make this function easy to read, and easy to be confident of correctness. (It's not always obvious what helper functions would be best -- a bit of an art! In this case, the fact that rectangles stored offsets from the NW corner turns out to make comparing distances more convenient than comparing x,y coordinates.) One other approach might be to write translate-shape first, and then see if (translate a-shape a-posn) covers the origin. Whether or not you consider a point on a shape's border to be in the shape or not isn't important, but you should (a) document your choice in the Purpose, and (b) have a test case which test for it. We also took advantage of the fact that < can actually take three arguments. You aren't expected to have known this (unless you enjoy reading the manual on your friday nights); of course you could have used multiple num ;; distance-y: posn, posn -> num ;; Determine the distance you need to travel along the x- or y-axis (resp.) ;; to go from p1 to p2. ;; Note that it's a signed amount: negative distance means ;; travel in the negative direction along the axis. ;; (define (distance-x p1 p2) (- (posn-x p2) (posn-x p1))) (define (distance-y p1 p2) (- (posn-y p2) (posn-y p1))) (= 3 (distance-x origin p34)) (= -3 (distance-x p34 origin)) (= 0 (distance-y origin origin)) (= 4 (distance-y origin p34)) ;; distance: posn, posn ->; num ;; Determine the cartesian distance between p1 and p2. ;; Note that cartesian distances are always positive. ;; (define (distance p1 p2) (sqrt (+ (sqr (distance-x p1 p2)) (sqr (distance-y p1 p2))))) (= 5 (distance (make-posn 0 0) (make-posn 5 0))) (= 5 (distance origin p34)) (= 5 (distance p34 origin)) (= 13 (distance p34 (translate-posn p34 5 -12))) ;Finally, now that all the helpers have been written, ;we can call in?: (boolean=? true (in? circ1 p34)) (boolean=? true (in? (make-circle (make-posn 5 5) 2 'blue) (make-posn 5 6))) (boolean=? false (in? (make-circle (make-posn 5 5) 2 'blue) (make-posn 8 8))) (boolean=? false (in? (make-rectangle (make-posn 5 5) 3 4 'black) (make-posn 6 9))) (boolean=? false (in? (make-rectangle (make-posn 5 5) 3 4 'black) (make-posn 5 5))) (boolean=? true (in? (make-rectangle (make-posn 5 5) 3 4 'black) (make-posn 6 6))) ;;2g. ;; translate-shape: Shape Num Num -> Shape ;; Return a shape which is like a-shape, but moved by (+x,+y). ;; (define (translate-shape a-shape x y) (cond [(circle? a-shape) (make-circle (translate-posn (circle-location a-shape) x y) (circle-radius a-shape) (circle-color a-shape))] [(rectangle? a-shape) (make-rectangle (translate-posn (rectangle-location a-shape) x y) (rectangle-width a-shape) (rectangle-height a-shape) (rectangle-color a-shape))])) ;; Tests: (make-circle (make-posn 2 3) 4 'blue) (translate-shape (make-circle (make-posn 0 0) 4 'blue) 2 3) (make-rectangle (make-posn 3 8) 4 14 'red) (translate-shape (make-rectangle (make-posn 3 7) 4 14 'red) 0 1) ;;2h (start 500 500) ; Opens a canvas to draw on. ;; draw-shape: Shape -> true ;; Draw a-shape on the current canvas, and return true. ;; (define (draw-shape a-shape) (cond [(circle? a-shape) (draw-solid-disk (circle-location a-shape) (circle-radius a-shape) (circle-color a-shape))] [(rectangle? a-shape) (draw-solid-rect (rectangle-location a-shape) (rectangle-width a-shape) (rectangle-height a-shape) (rectangle-color a-shape))])) ;Test-cases (boolean=? true (draw-shape circ1)) (boolean=? true (draw-shape circ23)) (boolean=? true (draw-shape rect1)) (boolean=? true (draw-shape rect2)) ;Note that the return type of the function is true ;(we can easily be more specific than boolean). ;;2i ;; my-picture: posn size -> true ;; Draw a black background, with an observatory. ;; Centered at here, and proportional to this-big. ;; Too bad, there aren't (currently) stars drawn on the ;; background. ;; (define (my-picture here this-big) (and (night-sky here (* this-big 2)) (observatory here this-big))) ;; observatory: posn size ->; true ;; Draw an observatory. ;; Centered at here, and proportional to this-big. ;; (Bug -- the green observatory opening ;; isn't actually centered, and width not scaled.) ;; (define (observatory here this-big) (and (draw-shape (make-circle here this-big 'blue)) (draw-shape (translate-shape (make-rectangle here this-big 17 'green) 0 (- this-big))) (draw-shape (translate-shape (make-rectangle here this-big (* this-big 2) 'yellow) (- this-big) 0)))) ;; night-sky: posn, num -> true ;; Draw a black rectangle. ;; Centered near center, and twice as wide as half-horizon ;; (define (night-sky center half-horizon) (draw-shape (make-rectangle (translate-posn center (- half-horizon) (- half-horizon)) (* 2 half-horizon) (round (* 3/2 half-horizon)) 'black))) ;; Tests ;; (boolean=? true (my-picture (make-posn 40 40) 20)) (boolean=? true (my-picture (make-posn 150 150) 70)) ;;my-picture2: posn --> true, ;; which takes in a location, and draws two copies ;;of my-picture. (define (my-picture2 a-posn) (and (my-picture a-posn 20) (my-picture (translate-posn a-posn 5 5) 30))) (boolean=? true (my-picture2 (make-posn 40 40))) (boolean=? true (my-picture2 (make-posn 150 150)))