;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-beginner-reader.ss" "lang")((modname dist-lect04) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp") (lib "image.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "universe.ss" "teachpack" "2htdp") (lib "image.ss" "teachpack" "2htdp"))))) ;;; http://www.radford.edu/~itec380/2011fall-ibarland/Lectures/dist-lect04-before.rkt ;;; ;;; Outline ;;; Mon: contains99?; total-bridge-value; turn-all-to-spades ;;; Wed: mention hw; go over big-bang (w/ 'move-ball' ((if ...) ..) per law-of-scheme); max ;;; Fri: max; run it; define; alternately: as an accum. ;;; natnum data def'n; countdown, sum1-n ;;; nth ;;; Skip to "MON HERE" (inbetween is old cold we'll build on) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Code from last time: ;;; Since we're handling data that can be integer OR character, ;;; we'll use "cond", which is like if-else-if: #;(define (func-for-c-ranks a-cr) (cond [(integer? a-cr) ...] [(character? a-cr) ...])) ;;; In bridge: ;;; you assign "bridge values" to card-ranks: ;;; most cards are 0, but jack is 1, queen is 2, king is 3, ace is 4. ;;; test cases (write 'em first!) (check-expect (crank-bridge-value 5) 0) (check-expect (crank-bridge-value 'queen) 2) ; crank-value : c-rank -> int ; compute the bridge-playing value for a given c-rank. (define (crank-bridge-value a-cr) (cond [(integer? a-cr) 0] [(symbol? a-cr) (cond [(symbol=? a-cr 'jack) 1] [(symbol=? a-cr 'queen) 2] [(symbol=? a-cr 'king) 3] [(symbol=? a-cr 'ace) 4])])) (check-expect (crank->string 5) "5") (check-expect (crank->string 10) "10") (check-expect (crank->string 'queen) "Q") ; crank->string : c-rank -> string ; (define (crank->string a-cr) (cond [(integer? a-cr) (number->string a-cr)] [(symbol? a-cr) (symbol->string/initial a-cr)])) ; symbol->string/initial : symbol -> string ; (define (symbol->string/initial sym) (string (char-upcase (string-ref (symbol->string sym) 0)))) (check-expect (symbol->string/initial 'hello) "H") (check-expect (symbol->string/initial 'a) "A") (check-expect (symbol->string/initial 'A) "A") ; A c-rank is either: ; - an integer (2..10) ; or - a symbol ('jack, 'queen, 'king, 'ace) ; OPTIONAL: ; Btw, we can write: ; crank? ANY -> boolean ; (define (crank? any) (or (and (integer? any) (<= 2 any 10)) (symbol? any))) ;;;;;;;;;;;;;;;;; Next stage: define-struct (product type, compound) ; ; Example: (define-struct card (rank suit)) ; rank : card-rank ; AND ; suit : symbol (make-card 4 'spades) (make-card 'queen 'diamonds) #| The corresponding Java: class Card { CRank rank; String suit; } ... new Card( 4, "hearts" ) ... |# ; When I define-struct, racket creates four functions for me: ; make-card -- constructor ; card-rank -- accessor ; card-suit -- accessor ; card? -- predicate ; have-a-heart : c-rank -> card ; Return a card of the given rank, in hearts. (check-expect (have-a-heart 3) (make-card 3 'hearts)) (check-expect (have-a-heart 'jack) (make-card 'jack 'hearts)) #| In Java: Card haveAHeart( CardRank aCr ) { return new Card(aCr, "hearts"); } |# ; (define (have-a-heart a-cr) (make-card a-cr 'hearts)) (check-expect (have-a-heart 5) (make-card 5 'hearts)) (check-expect (have-a-heart 'queen) (make-card 'queen 'hearts)) ; turn-to-spades: Given a card, return a new card of the same rank, and suit 'spades. ; ; turn-to-spades : card -> card (define (turn-to-spades a-card) ;...(card-rank a-card)... ; type: card-rank ;...(card-suit a-card)... ; type: symbol (make-card (card-rank a-card) 'spades) ) (check-expect (turn-to-spades (make-card 7 'hearts)) (make-card 7 'spades)) (check-expect (turn-to-spades (make-card 7 'spades)) (make-card 7 'spades)) ; card-bridge-value : card -> natnum ; Return a card's point-value in bridge (initial hand valuation) ; (define (card-bridge-value a-card) (crank-bridge-value (card-rank a-card))) (check-expect (card-bridge-value (make-card 7 'hearts)) 0) (check-expect (card-bridge-value (make-card 'queen 'hearts)) 2) (check-expect (card-bridge-value (make-card 'queen 'spades)) 2) (check-expect (card-bridge-value (make-card 5 'spades)) 0) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Data Def'n: ; A list-of-numbers is: ; - empty, ; OR ; - (cons num lon) ; num : number ; lon : list-of-numbers ;; Template: #;(define (func-for-lon data) (cond [(empty? data) ...] [(cons? data) ...(first data)... ...(func-for-lon (rest data))... ])) ; Examples of the data: empty (cons 3 empty) (cons 7 (cons 3 empty)) (cons 5 (cons 7 (cons 3 empty))) (define five-nums (cons 4 (cons 99 (cons 5 (cons 7 (cons 3 empty)))))) ; sum: list-of-number -> number ; (define (sum data) (cond [(empty? data) 0] [(cons? data) (+ (first data) (sum (rest data)))])) (check-expect (sum empty) 0) (check-expect (sum (cons 7 empty)) 7) (check-expect (sum (cons 3 (cons 7 empty))) 10) (check-expect (sum (cons 99 (cons 3 (cons 7 empty)))) 109) (check-expect (sum five-nums) 118) ; ; ;;;;;;; begin MON HERE ;;;;;;;; ; contains-99? : list-of-num -> boolean ; Does `data` contain the number 99? ; (define (contains-99? data) (cond [(empty? data) false] [(cons? data) (or (= (first data) 99) (contains-99? (rest data))) ])) (check-expect (contains-99? empty) false) (check-expect (contains-99? (cons 7 empty)) false) (check-expect (contains-99? (cons 99 empty)) true) (check-expect (contains-99? (cons 7 (cons 99 empty))) true) (check-expect (contains-99? (cons 99 (cons 7 empty))) true) (check-expect (contains-99? (cons 3 (cons 99 (cons 7 empty)))) true) (check-expect (contains-99? (cons 3 (cons 9 (cons 7 empty)))) false) ; A list-of-cards is: ; - empty ; OR ; - (cons c loc) ; c : card ; loc: list-of-cards ;; total-bridge-value : list-of-cards -> int ;; Return the total of all the bridge-values of the cards. ;; (define (total-bridge-value data) (cond [(empty? data) 0] [(cons? data) (+ (card-bridge-value (first data)) (total-bridge-value (rest data)))])) ; Functions involving list-of-cards: ; total-bridge-value ; turn-all-to-spades (define 4s (make-card 4 'spades)) (define qd (make-card 'queen 'diamonds)) (check-expect (total-bridge-value empty) 0) (check-expect (total-bridge-value (cons 4s empty)) 0) (check-expect (total-bridge-value (cons qd empty)) 2) (check-expect (total-bridge-value (cons qd (cons 4s empty))) 2) (check-expect (total-bridge-value (cons 4s (cons qd empty))) 2) (check-expect (total-bridge-value (cons (make-card 'ace 'spades) (cons 4s (cons qd empty)))) 6) ; turn-all-to-spades : list-of-cards -> list-of-cards ; (define (turn-all-to-spades data) (cond [(empty? data) empty] [(cons? data) (cons (turn-to-spades (first data)) (turn-all-to-spades (rest data)))])) (check-expect (turn-all-to-spades empty) empty) (check-expect (turn-all-to-spades (cons 4s empty)) (cons 4s empty)) (check-expect (turn-all-to-spades (cons qd empty)) (cons (make-card 'queen 'spades) empty)) (check-expect (turn-all-to-spades (cons qd (cons 4s empty))) (cons (make-card 'queen 'spades) (cons 4s empty))) (check-expect (turn-all-to-spades (cons 4s (cons qd empty))) (cons 4s (cons (make-card 'queen 'spades) empty))) (check-expect (turn-all-to-spades (cons (make-card 'ace 'hearts) (cons 4s (cons qd empty)))) (cons (make-card 'ace 'spades) (cons 4s (cons (make-card 'queen 'spades) empty)))) (check-expect (turn-all-to-spades (cons (make-card 2 'hearts) (cons (make-card 'ace 'hearts) (cons 4s (cons qd empty))))) (cons (make-card 2 'spades) (cons (make-card 'ace 'spades) (cons 4s (cons (make-card 'queen 'spades) empty))))) ;;;;;;;;;;;; lect04b (Wed) ;;;;;;;;;;;;;;; ;; Look at setup of big-bang-example.rkt ;; Write: ;; my-min ;; "let" ;; revisit root1, using "let" ; my-min : list-of-numbers -> number ; (define (my-min data) (cond [(empty? data) +inf.0] [(cons? data) (if (< (first data) (my-min (rest data))) (first data) (my-min (rest data)))])) (check-expect (my-min (cons 4 (cons 7 empty))) 4) (check-expect (my-min (cons 7 empty)) 7) (check-expect (= (my-min empty) +inf.0) true) (check-expect (my-min (cons 7 (cons 2 (cons 7 empty)))) 2) (check-expect (my-min (cons -2 empty)) -2) (check-expect (my-min (cons -8 (cons -7 (cons -6 (cons -5 empty))))) -8) ;;; in truth: max should only be defined for *non*-empty lists. ;;; (max empty) is inherently undefined. ;;; (The '-inf.0' trick is okay, but you can't use the same trick ;;; for (say) min-string. ;;; ;;; One approach would involve using a modified data def'n: ;;; ;; A non-empty list of numbers is either: ;; (cons num empty) ;; OR ;; (cons num nelon) ;; ; num : number ;; ; nelon : non-empty list of number ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Some new data definition ; ;; A natnum is: ;; 0 ;; OR ;; (+ 1 n) ;; ; n : natnum ;; examples of natnums: ;; 0 1 2 3 4 .... ;; 0, S(0), S(S(0)), S(S(S(0))), .... ;; template: ;; func-for-natnum : natnum -> ??? #;(define (func-for-natnum k) (cond [(zero? k) ...] [(positive? k) ...(func-for-natnum (- k 1))...])) (define (countdown k) (cond [(zero? k) "liftoff!"] [(positive? k) (string-append (number->string k) ".." (countdown (- k 1)))])) (check-expect (countdown 3) "3..2..1..liftoff!") (check-expect (countdown 1) "1..liftoff!") (check-expect (countdown 0) "liftoff!") ; nums-from : natnum -> (list-of natnum) (check-expect (nums-from 0) empty) (check-expect (nums-from 1) (cons 1 empty)) (check-expect (nums-from 2) (cons 2 (cons 1 empty))) (check-expect (nums-from 3) (cons 3 (cons 2 (cons 1 empty)))) (define (nums-from k) (cond [(zero? k) empty] [(positive? k) (cons k (nums-from (- k 1)))])) (time (my-min (nums-from 10))) (time (my-min (nums-from 20))) (time (my-min (nums-from 21))) (define (my-min-v2 data) (cond [(empty? data) +inf.0] [(cons? data) (let {[mm (my-min-v2 (rest data))]} (if (< (first data) mm) (first data) mm))])) (check-expect (my-min-v2 (cons 4 (cons 7 empty))) 4) (check-expect (my-min-v2 (cons 7 empty)) 7) (check-expect (= (my-min-v2 empty) +inf.0) true) (check-expect (my-min-v2 (cons 7 (cons 2 (cons 7 empty)))) 2) (check-expect (my-min-v2 (cons -2 empty)) -2) (check-expect (my-min-v2 (cons -8 (cons -7 (cons -6 (cons -5 empty))))) -8) #| cond -- if-else-if cons -- the constructor for non-empty-lists... "for cons objects" (cons 3 empty) -- I'll say it *is* hte list, but it could also be "the constructor-call". Racket chooses to print out data *the same way* you would call its constructor. cons? -- a predicate any -> boolean |# ;; A filenode is ;; - a file, ;; OR ;; - a directory ;; OR ;; - a symlink ;; (directory-list) ;; (directory-list "/Users/ibarland")