$19
Purpose: The purpose of this lab is to you some hands-on experience with lists of structures, structures of lists, and abstracting similarities.
Textbook references: Chapter 14: Similarities Everywhere, Chapter 15: Designing Abstractions
Exercise (Reviewed) 1 Consider the following two data definitions:
; A ListOfString (LOS) is one of:
; - empty
; - (cons String LOS)
; A ListOfNumber (LON) is one of:
; - empty
; - (cons Number LON)
Design a data definition which abstracts these two definitions. Redefine ListOfString and ListOfNumber using your abstraction.
Exercise 2 Consider the following two data definitions:
; A MaybeString is one of:
; - #false
; - String
; A MaybePosn is one of:
; - #false
; - Posn
Design a data definition which abstracts these two definitions. Redefine MaybeString and MaybePosn using your abstraction.
Exercise (Reviewed) 3 Consider the following two function definitions:
; matching-x-posn : [List-of Posn] Number Posn -> Posn
; Find the first Posn in the list with the given x-coordinate or return the given Posn
; if no such position can be found
(check-expect (matching-x-posn '() 10 (make-posn 0 0)) (make-posn 0 0))
(check-expect
(matching-x-posn
(cons (make-posn 1 2) (cons (make-posn 3 4) '())) 3 (make-posn 5 6))
(make-posn 3 4))
(define (matching-x-posn lop desired-x default)
(cond [(empty? lop) default]
[(cons? lop)
(if (= (posn-x (first lop)) desired-x)
(first lop)
(matching-x-posn (rest lop) desired-x default))]))
; string-with-length : [List-of String] Nat -> String
; Returns the first String in the given list with the given length or "no such string" if no
; such string can be found
(check-expect (string-with-length '() 10) "no such string")
(check-expect (string-with-length (cons "hi" (cons "hello" (cons "aloha" '()))) 5) "hello")
(define (string-with-length los desired-length)
(cond [(empty? los) "no such string"]
[(cons? los)
(if (= (string-length (first los)) desired-length)
(first los)
(string-with-length (rest los) desired-length))]))
Design the function find-first-match which abstracts these two functions. Be sure to redefine matching-x-posn and string-with-length using your abstraction.
Designing with Self-Referential Data (Revisited)
Consider the following self-referential data definition for natural numbers:
; A Nat is one of:
; - 0
; - (add1 Nat)
Note that this definition is different from one you may have seen in lecture. Your TAs will discuss the parallels at the start of the lab.
Exercise 4 Create a template for the data definition given above. If you are struggling with this please see the design recipe page on the course website.
Exercise 5 Design the function even-nat? which takes a Nat and returns #true if the Nat is an even number. Yes, zero is even. You may not use even? or odd? to write this function.
Exercise 6 Design the function nat+ which takes two Nats and returns their sum. You may not use + to write this function.
Counters
Starter Code: Consider the following data definitions and functions:
; A Pair is a (make-pair String PosInt)
; and represents an element with a non-zero count
(define-struct pair [element value])
(define (pair-temp p)
(... (pair-element p) ... (pair-value p) ...))
; A Counter is one of:
; - '()
; - (cons Pair Counter)
; and represents a multiset (a set of elements where
; an element can appear more than once)
(define (counter-temp counter)
(cond [(empty? counter) ...]
[(cons? counter) (... (pair-temp (first counter))
... (counter-temp (rest counter))
...)]))
(define marble-bag (list (make-pair "green" 2) (make-pair "red" 5)))
; marble-bag represents a bag with 2 "green" marbles and 5 "red" ones
; get : Counter String -> PosInt
; Get the count of the given element
(define (get counter element)
(cond [(empty? counter) (error "not found")]
[else (if (counts-element? (first counter) element)
(pair-value (first counter))
(get (rest counter) element))]))
(check-error (get (list (make-pair "cats" 3)) "dogs") "not found")
(check-expect (get (list (make-pair "cats" 3) (make-pair "dogs" 4)) "dogs") 4)
; counts-element? : Pair String -> Boolean
; Does the pair hold a count for the element?
(define (counts-element? pair element)
(string=? element (pair-element pair)))
(check-expect (counts-element? (make-pair "green" 2) "green") #true)
(check-expect (counts-element? (make-pair "red" 5) "blue") #false)
Sample Problem Design the function add-to-counter, which given a Counter and an element will add 1 to the previously associated count. If that element was not present, its count will be 1.
; add-to-counter : Counter String -> Counter
; Add one to the count associated with element or set it to 1
; if it hasn't been seen before
(check-expect (add-to-counter '() "blue") (list (make-pair "blue" 1)))
(check-expect (add-to-counter marble-bag "red")
(list (make-pair "green" 2) (make-pair "red" 6)))
(check-expect (add-to-counter marble-bag "green")
(list (make-pair "green" 3) (make-pair "red" 5)))
(define (add-to-counter counter element)
(cond
[(empty? counter) (list (make-pair element 1))]
[(cons? counter) (if (counts-element? (first counter) element)
(cons (increment-value (first counter))
(rest counter))
(cons (first counter)
(add-to-counter (rest counter) element)))]))
; increment-value : Pair -> Pair
; Increment the value in pair
(check-expect (increment-value (make-pair "green" 2)) (make-pair "green" 3))
(check-expect (increment-value (make-pair "red" 5)) (make-pair "red" 6))
(define (increment-value pair)
(make-pair (pair-element pair) (add1 (pair-value pair))))
Exercise 7 Design the function total-size, which grabs the total count of elements in a Counter (there are 7 in marble-bag).
Exercise 8 Design the function initiate-counter, which given a String creates a Counter with one copy of that element. Be sure to follow the data definition.
Exercise 9 Design the function all-elements, which outputs a ListOfString containing all of the elements a Counter has counted so far. For example, the output of (all-elements marble-bag) would be (list "green" "green" "red" "red" "red" "red" "red").
Hint: Notice that every PosInt is also a Nat; this may be helpful.
Exercise 10 Design the function highest-count, which returns the highest count for a single element in a Counter. If the counter is empty, return 0.