;; Lecture 21 in-class problems ;; a CD is a (make-cd string string number number string) (define-struct cd(title artist price copies category)) ;; an inventory is a list-of-cd ;; a list-of-cd is either ;; empty, or ;; (cons cd list-of-cd) (define CDs (list (make-cd "greatest hits" "abba" 12.95 42 "rock") (make-cd "beach boys live" "beach boys" 10.00 120 "rock") (make-cd "yanni at the acropolis" "yanni" 5.00 0 "new age") (make-cd "marriage of figaro" "mozart" 20.00 50 "classical"))) ;; all-titles: list-of-cd -> list-of-string ;; consumes a list of cds and produces a list of all the CD titles (define (all-titles alocd) (map cd-title alocd)) ;; titles-in-stock: list-of-cd -> list-of-string ;; consumes a list-of-cd and produces the titles of all those cds with at least 1 copy in stock (define (titles-in-stock alocd) (map cd-title (filter more-than-zero? alocd))) ;; more-than-zero?: cd -> boolean ;; consumes a cd and returns true if there are more than 0 copies of the cd in stock (define (more-than-zero? acd) (> (cd-copies acd) 0)) ;; copies-in-stock: string string list-of-cd -> number ;; consumes a CD title, an artist name, and an inventory and produces the number of copies of that item that are in stock. ;; Return 0 if the named CD isn't in the inventory. (define (copies-in-stock title name alocd) (cond [(empty? alocd) 0] [(cons? alocd) (cond [(target-cd? (first alocd) title name) (cd-copies (first alocd))] [else (copies-in-stock title name (rest alocd))])])) ;; target-cd?: cd string string -> boolean ;; consumes a cd, and a title and artist, and returns true if the given cd has the given title and is by the given artist (define (target-cd? acd title artist) (and (string=? title (cd-title acd)) (string=? artist (cd-artist acd)))) ;; For practice, try re-writing copies-in-stock using filter/map. The answer is at the bottom of this handout. ;; restock: string number list-of-cd -> list-of-cd ;; consumes the name of a cd, a number of new copies, and a list of cds and produces a list the same as the original except that ;; the named cd has the given number of additional copies (define (restock name extras alocd) (cond [(empty? alocd) empty] [(cons? alocd) (cons (add-if-named name extras (first alocd)) (restock (rest alocd)))])) ;; add-if-named: string number cd -> cd ;; consumes the name of a cd, the number of additional copies, and a cd. ;; If the cd has the given name, the cd is returned with the additional number of copies added. ;; Otherwise, the cd is returned unchanged. (define (add-if-named name extras acd) (cond [(string=? name (cd-title acd)) (make-cd (cd-title acd) (cd-artist acd) (cd-price acd) (+ extras (cd-copies acd)) (cd-category acd))] [else acd])) ;;; restock can be done with map, but again, it's really not a huge improvement over the template-style approach ; ;;; the reason is because the restock function doesn't need to change every item in the list, just one of them. ;;; Here's a solution using map: ; ;;; restock: string number list-of-cd -> list-of-cd ;;; consumes the name of a cd, a number of new copies, and a list of cds and produces a list the same as the original ;;; except that the named cd has the given number of additional copies ;(define (restock name extras alocd) ; (local [(define (add-if-named acd) ; (cond [(string=? (cd-title acd) name) (make-cd (cd-title acd) ; (cd-artist acd) ; (cd-price acd) ; (+ extras (cd-copies acd)) ; (cd-category acd))] ; [else acd]))] ; (map add-if-named alocd))) ;; titles-by: string list-of-cd -> list-of-string ;; consumes an artist name and inventory and produces a list of titles of CDs by that artist (define (titles-by name alocd) (local [(define (name-match? acd) (string=? name (cd-artist acd)))] (map cd-title (filter name-match? alocd)))) ;;; an alternative definition to copies-in-stock using filter/map ;;; copies-in-stock: string string list-of-cd -> number ;;; consumes a CD title, an artist name, and an inventory and produces the number of copies of that item that are in stock. ;;; Return 0 if the named CD isn't in the inventory. ;(define (copies-in-stock title name alocd) ; (local [(define (target-cd? acd) (and (string=? title (cd-title acd)) (string=? name (cd-artist acd)))) ; (define apply-filter (filter target-cd? alocd))] ; (cond [(empty? apply-filter) 0] ; [(cons? apply-filter) ; (first (map cd-copies apply-filter))]))) ;