Problem set 8: Abstraction
This assignment is due on Wednesday, October 19 at 11:59pm. Submit it using Handin as assignment ps8. Corrections can be presented until Friday, November 11.
This problem set builds on the skills that we introduced in Lectures 2−9 and 11−16. To encourage you to review those lectures, your grade on this assignment will be capped by your grade on those lectures at the time you submit (or correct) this assignment. You can resubmit lecture exercises at any time.
Remember to follow the design recipe whenever you design or write a function. In particular, every type mentioned in a signature must be introduced by a data definition, except for these well-known types: Number, Image, String, Color, Boolean, KeyEvent, MouseEvent, Anything, Posn, NaturalNumber, ListOfNumbers, 1String, [ListOf X].
Note: Use the “Intermediate Student” language or the “Intermediate Student with lambda” language on this assignment.
Design at least 2 similar functions.
Identify inessential differences and revise functions to remove them. (Helpers are often useful for removing inessential differences.)
Circle essential differences and pick input names for each of them.
Design the abstraction by replacing differences with input names. (The new abstraction should have its own signature and purpose statement. If the original tests do not provide sufficient coverage for the abstraction, include additional tests.)
Redefine the original functions using the new abstraction. (You don’t need to submit the original versions.) The redefined functions should not be commented out. They should have the same signatures and purpose statements as before as well as pass the same tests as before.
; abstraction : ... [Number Number -> Number] ... -> ...
1 Images
(require 2htdp/image) ; A Mode is one of: ; - "outline" ; - "solid" ; A Color is one of: ; - "red" ; - "yellow" ; - "blue" ; - "magenta" ; - "white" ; - "black" ; - ... ; overlay : Image Image -> Image ; text : String Number Color -> Image ; rectangle : Number Number Mode Color -> Image ; star : Number Mode Color -> Image ; square : Number Mode Color -> Image ; triangle : Number Mode Color -> Image ; circle : Number Mode Color -> Image
; notice : String -> Image ; typeset a calm notice (check-expect (notice "This is fine") (overlay (text "This is fine" 20 "black") (rectangle 200 100 "solid" "white"))) (define (notice s) (overlay (text s 20 "black") (rectangle 200 100 "solid" "white"))) ; alert : String -> Image ; display a frantic alert (check-expect (alert "It's on fire") (overlay (text "It's on fire" 20 "yellow") (rectangle 200 100 "solid" "red"))) (define (alert s) (overlay (text s 20 "yellow") (rectangle 200 100 "solid" "red")))
; outlined-star : Number Color Color -> Image ; draw an outlined star of the given size, ; the given stroke color, and the given fill color (check-expect (outlined-star 30 "blue" "magenta") (overlay (star 30 "outline" "blue") (star 30 "solid" "magenta"))) (define (outlined-star size stroke fill) (overlay (star size "outline" stroke) (star size "solid" fill))) ; outlined-square : Number Color Color -> Image ; draw an outlined square of the given size, ; the given stroke color, and the given fill color (check-expect (outlined-square 50 "red" "yellow") (overlay (square 50 "outline" "red") (square 50 "solid" "yellow"))) (define (outlined-square size stroke fill) (overlay (square size "outline" stroke) (square size "solid" fill)))
2 Lists
; remove-positive : ListOfNumbers -> ListOfNumbers ; remove all positive numbers from the given list (check-expect (remove-positive empty) empty) (check-expect (remove-positive (list 0 1 -3 2)) (list 0 -3)) (check-expect (remove-positive (list 1 -3 2)) (list -3)) (define (remove-positive lon) (cond [(empty? lon) empty] [(positive? (first lon)) (remove-positive (rest lon))] [else (cons (first lon) (remove-positive (rest lon)))]))
Exercise 4. Use your new abstraction rid to design a function remove-multiples-of-3 that takes a list of numbers and removes all numbers divisible by 3.
; tab-sin : NaturalNumber -> ListOfNumbers ; tabulates sin between n and 0 (inclusive) in a list (define (tab-sin n) (cond [(= n 0) (list (sin 0))] [else (cons (sin n) (tab-sin (sub1 n)))])) ; tab-sqrt : NaturalNumber -> ListOfNumbers ; tabulates sqrt between n and 0 (inclusive) in a list (define (tab-sqrt n) (cond [(= n 0) (list (sqrt 0))] [else (cons (sqrt n) (tab-sqrt (sub1 n)))]))
Exercise 6. Abstract from tab-sin and tab-sqrt. Call your new abstraction tabulate. Again, it should have its own signature and purpose statement. Don’t forget to redefine the original functions using it.
Exercise 7. Use your new abstraction tabulate to design a function tab-sqr that tabulates sqr between the input n and 0 (inclusive) in a list.
3 Non-empty lists
;; A NEListOfStrings is one of: ;; - (cons String empty) ;; - (cons String NEListOfStrings)
;; A NEListOfImages is one of: ;; - (cons Image empty) ;; - (cons Image NEListOfImages)
Exercise 8. Write down the template for processing a NEListOfStrings. Make it look like a function called process-nelos, and do not put it in a comment. Hint: If you need a refresher about writing processing templates, review Lecture 12: Unlimited data Exercise 3. As usual, because the data definition says “one of” two cases, the template should be cond with two cases. Each of the two cond questions should pick out one of the two cases depicted in the data definition.
Exercise 9. Design a function commas that takes a non-empty list of strings as input and joins them into a single string, adding commas in between. For example, (commas (list "water" "yeast" "flour")) should produce the string "water,yeast,flour".
Exercise 10. Design a function beside-all that takes a non-empty list of images as input and joins them into a single image, as a horizontal row beside each other.
Exercise 11. Abstract from NEListOfStrings and NEListOfImages. Call your new abstraction [NEListOf X]. Don’t forget to redefine NEListOfStrings and NEListOfImages using NEListOf.
Exercise 12. Abstract from commas and beside-all. Call your new abstraction join. Again, it should have its own signature and purpose statement. Don’t forget to redefine the original functions using it.
Exercise 13. Using NEListOf and join, design a function smallest-number that takes a non-empty list of numbers as input and returns the smallest number. (If multiple numbers are equally small, return any of them.)
4 Challenges
Exercise 14. Abstract from the functions weight, lighten, and enlarge in Problem set 6: Unions and recursion.
Hint: All these functions follow the template for processing a Mobile, but they fill in the template’s dots in different ways. Introduce helper functions to reduce each difference to one word.
(check-expect (mul-table empty) empty) (check-expect (mul-table (list 2 3 5 10)) (list (list 4 6 10 20) (list 6 9 15 30) (list 10 15 25 50) (list 20 30 50 100)))