;; 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-advanced-reader.ss" "lang")((modname week8_tu_full) (read-case-sensitive #t) (teachpacks ((lib "image.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ((lib "image.ss" "teachpack" "2htdp"))))) ; ; ; ; ;;;; ; ; ; ;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ;;; ; ; ; ;;;; ;;; ;;;; ; ;;; ;;;; ;;; ; ;;;; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ; ; ; ;;;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;; ; ; ;;;; ;;; ;;;; ;;; ;;; ;;;; ;;; ; ; ; ;; Question #1 - structure definitions and an example descendant tree ; a family-tree is: ; (make-parent list-of-family-tree symbol number symbol) (define-struct parent (children name date eyes)) ; Youngest Generation: (define Gustav (make-parent empty 'Gustav 1988 'brown)) (define Fred&Eva (list Gustav)) ; Middle Generation: (define Adam (make-parent empty 'Adam 1950 'yellow)) (define Dave (make-parent empty 'Dave 1955 'black)) (define Eva (make-parent Fred&Eva 'Eva 1965 'blue)) (define Fred (make-parent Fred&Eva 'Fred 1966 'pink)) (define Carl&Bettina (list Adam Dave Eva)) ; Oldest Generation: (define Carl (make-parent Carl&Bettina 'Carl 1926 'green)) (define Bettina (make-parent Carl&Bettina 'Bettina 1926 'green)) ; Q1 : Write a function avg-uniq-years, which returns the ; average of the *unique* birth years found in a family tree ; wishlist: ; selects unique years from list ; average of list of numbers ; get all birth years from tree ; avg-uniq-years : family-tree -> number ; returns average of unique birth years for family tree (define (avg-uniq-years ft) (average (get-uniq-years ft))) (check-expect (avg-uniq-years Gustav) 1988) (check-expect (avg-uniq-years Eva) (/ (+ 1965 1988) 2)) ; average : list-of-numbers -> number ; returns the average of numbers in a list (define (average lon) (/ (foldr + 0 lon) (length lon)) ) ; length looks like (foldr (lambda (x y) (+ 1 y)) (check-expect (average (list 1 2 3)) 2) (check-expect (average (list 4 5 9)) 6) ; get-uniq-years : ft -> list-of-numbers ; returns a list of all unique birth years in tree ; assumes parent birth year differs from children (define (get-uniq-years ft) (cons (parent-date ft) (get-uniq-years-list (parent-children ft))) ) (check-expect (sort (get-uniq-years Eva) <) (list 1965 1988)) (check-expect (sort (get-uniq-years Carl) <) (list 1926 1950 1955 1965 1988)) ; get-uniq-years-list : list-of-ft -> list-of-numbers ; returns a list of unique birth years in trees in list (define (get-uniq-years-list loft) (cond [(empty? loft) empty] [else (dedup (append (get-uniq-years (first loft)) (get-uniq-years-list (rest loft))))] )) (check-expect (sort (get-uniq-years-list (list Eva)) <) (list 1965 1988)) ; dedup : list-of-X -> list-of-X ; removes duplicate elements in list (define (dedup lox) (foldr (lambda (x l) (cons x (remove x l))) empty lox) ) (check-expect (dedup (list 1 2 3 2)) (list 1 2 3)) ;; Question #2 ; an answer is either ; - 'too-low ; - 'just-right ; - 'too-high ; make-uniform-secret : integer integer -> secret ; Chooses a secret between `low' and `high' (inclusive) uniformly ; at random and returns a function that lets you guess the secret. (define (make-uniform-secret low high) (local [(define secret (uniform-between low high))] (lambda (guess) (check-guess guess secret)))) ; make-special-secret : integer integer -> (integer -> answer) ; Like `make-uniform-secret' but chooses `low' with probability .2, ; `high' with probability .2, and uniformly among the rest. (define (make-special-secret low high) (local [(define r (random)) (define secret (cond [(< r .2) low] [(< r .4) high] [else (uniform-between (+ 1 low) (- high 1))]))] (lambda (guess) (check-guess guess secret)))) ; check-guess : integer integer -> answer ; Checks a guess against a given secret (define (check-guess guess secret) (cond [(< guess secret) 'too-low] [(= guess secret) 'just-right] [(> guess secret) 'too-high])) (check-expect (check-guess 1 2) 'too-low) (check-expect (check-guess 2 2) 'just-right) (check-expect (check-guess 3 2) 'too-high) ; uniform-between : integer integer -> integer ; Chooses a random integer between `low' and `high' uniformly at random (define (uniform-between low high) (+ low (random (+ 1 (- high low))))) ; sample-average : (-> number) natural-number -> number ; Runs a randomized function `f' `n' times and returns the average of those runs (define (sample-average f n) (/ (sample-sum f n) n)) ; sample-sum : (-> number) natural-number -> number ; Runs a randomized function `f' `n' times and returns the sum of those runs (define (sample-sum f n) ; Need an accumulator-based definition to go beyond a few million runs (cond [(zero? n) 0] [else (+ (f) (sample-sum f (- n 1)))])) (check-within (sample-average (lambda () (uniform-between 2 4)) 100000) 3 .1) ; a guess-result is ; (make-guess-result integer natural-number) (define-struct guess-result (secret guesses)) ; run-game : integer integer secret-maker natural-number guesser -> numbers ; where secret-maker = (integer integer -> (integer -> answer)) ; and guesser = (integer -> answer) integer integer -> guess-result ; Plays guessing game `runs' times, using `make-secret' with bounds `low' and `high' ; to choose the secret and `guess-secret' to guess it. ; Returns the average number of attempts that `guess-secret' needed. (define (run-game low high make-secret runs guess-secret) (sample-average (lambda () (guess-result-guesses (guess-secret (make-secret low high) low high))) runs)) ; guess-with-linear-search : (integer -> answer) integer integer -> guess-result ; Guesses a secret using linear search. (define (guess-with-linear-search secret low high) (local [(define answer (secret low))] (cond [(symbol=? answer 'just-right) (make-guess-result low 1)] [(symbol=? answer 'too-low) (increment-guesses (guess-with-linear-search secret (+ low 1) high))]))) ; increment-guesses : guess-result -> guess-result ; Increments guesses (define (increment-guesses r) (make-guess-result (guess-result-secret r) (+ 1 (guess-result-guesses r)))) (check-within (run-game 1 100 make-uniform-secret 1000 guess-with-linear-search) 50 3) (check-within (run-game 1 100 make-special-secret 1000 guess-with-linear-search) 50 3) ; Q2 : write a function that guesses randomly. Does it perform better ; or worse than linear search? Why? ; guess-with-random-search : (integer-> answer) integer integer -> ; guess-result ; guesses with random search ( define (guess-with-random-search secret low high) (local [(define answer (secret (uniform-between low high)))] (cond [(symbol=? answer 'just-right) (make-guess-result answer 1)] [else (increment-guesses (guess-with-random-search secret low high))])))