Sometimes when we solve problems, we find that the solution to one problem
looks a lot like the solution to another one. Check out the following functions
and data definition. From now on we will leave out the definition for lists,
and use the
[listof X] notation.
;; A [listof Number] is one of ;; -- empty ;; -- (cons Number [listof Number]) ;; lon-add2 : [listof Number] -> [listof Number] ;; Add two (2) to each element of the given list of numbers (define (lon-add2 lon) (cond [(empty? lon) empty] [else (cons (+ (first lon) 2) (lon-add2 (rest lon)))])) ;; lon-add5 : [listof Number] -> [listof Number] ;; Add five (5) to each element of the given list of numbers (define (lon-add5 lon) (cond [(empty? lon) empty] [else (cons (+ (first lon) 5) (lon-add5 (rest lon)))]))
Is it clear what each function does? You are hopefully asking "Why would you do that?!" since they are almost exactly the same.
lon-add-nthat abstracts both of the functions above, taking an extra argument, which is the number to be added to each element. Make sure you follow the recipe for abstraction.
lon-add5using your more general function, and write a few tests for each to be sure they work as expected.
A recursive data structure we use very often in programming is the collection of natural numbers:
; A Nat (natural number) is one of: ; - 0 ; - (add1 Nat) ; ; 0 predicate: zero? ; ; (add1 n) predicate: positive? ; (add1 n) accessor: sub1
In the following exercises we will redefine some built-in arithmetic
functions to get practice writing recursive functions over
Nats, so don't simply reuse the built-in functions.
trueif the given
You may only use
sub1 (and possibly
not). E.g., do not use
doublethat doubles the given
Nat. Again, you may only use
down-fromthat takes a
nand returns the list of
Nats counting down from
n. For example,
(down-from 3) = (list 3 2 1 0).
repeatthat takes a
sand returns a list that repeats
ntimes. For example,
(repeat "buffalo" 8) = (list "buffalo" "buffalo" "buffalo" "buffalo" "buffalo" "buffalo" "buffalo" "buffalo"). Do not use
make-list! (though it's good to know about)
nat+that takes two
Nats and computes their sum. (Use recursion, not the built-in
nat*that takes two
Nats and computes their product. (Again use recursion, not the built-in
*function, though you may use your
sqwarethat squares the given
Nat(Note the intended name misspelling!), WITHOUT using
nat*! You may use
Some basic setup:
(require 2htdp/image) (require 2htdp/universe) (define width 400) (define height 400)In this animation, a
Worldis a collection of
Rings, each of which has a size and a location.
; A World is a [listof Ring] ; A Ring is a (make-ring Nat Posn) (define-struct ring (size center))
grow-ringfunction that increases a
Ring's size by 1.
draw-ringfunction that takes a
ras input and simply returns an image of a circle with radius
r. (We'll make this more interesting later.)
place-ringfunction that draws a
Ringinto the given
Ring's location. (Use
draw-ringhere so that we can modify it later to change the animation.)
drawfunction that renders a
Sceneby drawing all the
Rings in their correct locations.
mousefunction that, when the mouse is clicked, adds a 0-size
Worldat the location of the click.
tickfunction that grows all the
Rings in the
Put it all together and see what you get:
(big-bang empty (on-tick tick .25) (to-draw draw) (on-mouse mouse))
draw-ring : Nat -> Imagefunction. Instead of making an image of a solid circle, let's make concentric rings of many circles. We can achieve this by overlaying many circles of increasing sizes:
(overlay ) =