;; 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-intermediate-reader.ss" "lang")((modname lect27-dist-ancestor-tree) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) ; data def'n: ; an anc-tree (ancestor tree) is: ; - 'unknown, OR ; - (make-child [string] [int] [symbol] [anc-tree] [anc-tree]) (define-struct child (name yob eye ma pa)) ; template ; func-for-anc-tree : anc-tree -> ?? (define (func-for-anc-tree a-tree) (cond [(symbol? a-tree) ...] [(child? a-tree) (...(child-name a-tree) (child-yob a-tree) (child-eye a-tree) (func-for-anc-tree (child-ma a-tree)) (func-for-anc-tree (child-pa a-tree)))])) ; Give me some examples of anc-trees: 'unknown (define abe (make-child "abe" 1921 'brown 'unknown 'unknown)) (define mona (make-child "mona" 1928 'blue 'unknown 'unknown)) (make-child "homer" 1954 'green (make-child "mona" 1928 'blue 'unknown 'unknown) (make-child "abe" 1921 'brown 'unknown 'unknown)) ; OR: (define homer (make-child "homer" 1954 'green mona abe)) ; marge's mother is jacquie, and her father is unknown. (define jackie (make-child "jacquie" 1918 'green 'unknown 'unknown)) (define marge (make-child "marge" 1954 'blue (make-child "jacquie" 1918 'green 'unknown 'unknown) 'unknown)) (make-child "bart" 1979 'brown (make-child "marge" 1954 'blue (make-child "jacquie" 1918 'green 'unknown 'unknown) 'unknown) (make-child "homer" 1954 'green (make-child "mona" 1928 'blue 'unknown 'unknown) (make-child "abe" 1921 'brown 'unknown 'unknown))) ; OR: (define bart (make-child "bart" 1979 'brown marge homer)) (check-expect (size 'unknown) 0) (check-expect (size abe) 1) (check-expect (size marge) 2) (check-expect (size homer) 3) (check-expect (size bart) 6) ; size : anc-tree -> natnum ; Return how many `child`s are in the anc-tree. ; (define (size a-tree) (cond [(symbol? a-tree) 0] [(child? a-tree) (+ (size (child-ma a-tree)) 1 (size (child-pa a-tree)))])) (define (func-for-ancTree tr) (cond [(symbol? tr) ...] [(child? tr) (...(child-name tr) ...(child-yob tr) ...(child-eye tr) ...(func-for-ancTree (child-ma tr)) ...(func-for-ancTree (child-pa tr)) )])) (check-expect (size 'unknown) 0) (check-expect (size (make-child "Abe" 1901 'brown 'unknown 'unknown)) 1) (check-expect (size (make-child "Homer" 1949 'brown 'unknown (make-child "Abe" 1901 'brown 'unknown 'unknown))) 2) ; unknown? ANY -> boolean ; Is x [a representation of] the unknown Anc-Tree? ; ;(define (unknown? x) (equal? x 'unknown)) ; Recall `define`, in the version used for functions, expands to: ;(define unknown? (λ (x) (equal? x 'unknown))) ; why not symbol? why not symbol=? (define (unknown? x) (and (symbol? x) (symbol=? x 'unknown))) ; why not symbol? why not symbol=? ; ; Cf.: and example of using and/f: ;(define unknown? (and/f symbol? (λ (s) (symbol=? s 'unknown)))) ; anc-tree? : ANY -> boolean ; (define (anc-tree? blah) (or (unknown? blah) (child? blah))) ; note how the code mirrors the data-def'n. ;; fun-for-anc-tree : anc-tree --> ??? ;; ;(define (fun-for-anc-tree anc) ; (cond [(unknown? anc) ...] ; [(child? anc) ...(child-name anc) ; ...(child-yob anc) ; ...(child-eye anc) ; ...(fun-for-anc-tree (child-ma anc)) ; ...(fun-for-anc-tree (child-pa anc))]) (check-expect (change-name 'unknown "joe" "joline") 'unknown) (check-expect (change-name bart "joe" "joline") bart) (check-expect (change-name (make-child "joe" 1995 'brown (make-child "joe" 1970 'blue 'unknown 'unknown) (make-child "fred" 1971 'brown (make-child "joe" 1940 'blue 'unknown 'unknown) (make-child "joe" 1942 'brown 'unknown 'unknown))) "joe" "joline") (make-child "joline" 1995 'brown (make-child "joline" 1970 'blue 'unknown 'unknown) (make-child "fred" 1971 'brown (make-child "joline" 1940 'blue 'unknown 'unknown) (make-child "joline" 1942 'brown 'unknown 'unknown)))) ; change-name : anc-tree string string -> anc-tree ; Return an anc-tree like `anc`, except any name `name1` ; has been replaced with `name2`, everywhere. ; (define (change-name anc old-name new-name) (cond [(unknown? anc) 'unknown] [(child? anc) (make-child (if (string=? (child-name anc) old-name) new-name (child-name anc)) (child-yob anc) (child-eye anc) (change-name (child-ma anc) old-name new-name) (change-name (child-pa anc) old-name new-name))])) ; all-names : anc-tree -> (listof string) ; Return a list of all the names in a tree. ; (define (all-names anc) (cond [(unknown? anc) empty] [(child? anc) (append (all-names (child-ma anc)) (cons (child-name anc) (all-names (child-pa anc)))])) ; all-childs : anc-tree -> (listof child) ; Return a list of all the childs in a tree. ; ;; (define (all-childs anc) (cond [(unknown? anc) empty] [(child? anc) (append (all-childs (child-ma anc)) (list anc) (all-childs (child-pa anc)))])) (check-expect (all-childs 'unknown) empty) (check-expect (all-childs abe) (list abe)) (check-expect (all-childs homer) (list mona homer abe)) (check-expect (all-childs bart) (list jackie marge bart mona homer abe)) #| ; contains? : AncTree, string -> boolean ; Does the tree contain the given name, anywhere? ; (check-expect (contains? ... "Bart") ...) (check-expect (contains? bart "Bart") true) (check-expect (contains? bart "Homer") true) (check-expect (contains? bart "Abe") true) (check-expect (contains? homer "Bart") false) (check-expect (contains? bart "Marge") true) (check-expect (contains? bart "Mona") true) (check-expect (contains? mona "Bart") false) ; challenge: write my-append: list, list -> list ; (Hint: follow the template for a list, ; but only take first/rest of arg1.) ; any-time-travelers? : anc-tree -> boolean ; (anybody born before their parents?)(*) ; Return all time-travelers. ; (define (any-time-travelers? anc) (any-time-travelers-help? anc +inf.0)) ; child-born-before-yr-or-any-time-travelers? ; (define (any-time-travelers-help? anc parent-yob) (cond [(unknown? anc) false] [(child? anc) (or (> (child-yob anc) parent-yob) (any-time-travelers-help? (child-ma anc) (child-yob anc)) (any-time-travelers-help? (child-pa anc) (child-yob anc)))])) (check-expect (any-time-travelers? 'unknown) false) (check-expect (any-time-travelers? abe) false) (check-expect (any-time-travelers? (make-child "lexxor" 1801 "orange" (make-child "Scully" 1970 "brown" 'unknown 'unknown) 'unknown)) true) ; (*) Okay, if somebody was born before their parents, it means their *parents* ; were the time travelers. But for this exercise, we'll ignore that, ; and just return the child who was born before the parents. ; entitle: AncTree -> AncTree ; Add "Mr." in front of each father's name, and "Ms." to each mother's. ; (Cf. walking an html tree and making some transform.) ; ;; entitle : anc-tree --> anc-tree ;; (define (entitle anc) (entitle-help anc "Baby")) (define (entitle-help anc title-for-root) (cond [(unknown? anc) 'unknown] [(child? anc) (make-child (string-append title-for-root " " (child-name anc)) (child-yob anc) (child-eye anc) (entitle-help (child-ma anc) "Ms.") (entitle-help (child-pa anc) "Mr."))])) (check-expect (entitle 'unknown) 'unknown) (check-expect (entitle homer) (make-child "Baby Homer" 1951 'brown (make-child "Ms. Mona" 1929 'blue 'unknown 'unknown) (make-child "Mr. Abe" 1920 'brown 'unknown 'unknown))) #| /** How would we write this same data structure (and programs) in Java? */ abstract class AncTree { } class Unknown extends AncTree { } class Child extends AncTree { String name; int yob; // year-of-birth String eye; // eye-color, e.g. "brown" AncTree ma, pa; // mother, father /** standard constructor */ public Child( String _name, int _yob, String _eye, AncTree _ma, AncTree _pa ) { this.name = _name; this.yob = _yob; this.eye = _eye; this.ma = _ma; this.pa = _pa; } /** @Override */ public String toString( /* Child this */ ) { return "new Child" + "( " + this.name.toString() + ", " + this.yob + ", " + this.eye.toString() + ", " + this.ma.toString() + ", " + this.pa.toString() + " )"; } public static void main( String[] args ) { AncTree abe = new Child( "Abe", 1920, "brown", new Unknown(), new Unknown() ); AncTree mona = new Child( "Mona", 1929, "blue", new Unknown(), new Unknown() ); AncTree homer = new Child( "Homer", 1951, "brown", mona, abe ); System.out.println( "Actual: " + abe.toString() ); System.out.println( "Expect: " + "new Child( \"Abe\", 1920, \"brown\", new Unknown(), new Unknown() )" ); System.out.println( "Actual: " + homer.toString() ); System.out.println( "Expect: " + "??" ); } } |# ; anctree->string: ;(check-expect (anctree->string abe) "[? Abe ?]") ;(check-expect (anctree->string abe) "new Child(Abe,") ;(check-expect (anctree->string abe) "new Child(Abe,") ; Mon: Define anc-tree. examples; template; size; all-names ; ; Wed: ; q: more examples of using map (w/ lambda) ; qz: what is the data-def'n of a FamTree ; self-quiz: toString ; start Java version of famTree ; ; Fri: ; Write: change-all-names (add a "Mr" or "Ms" to each name) ; ; Java: write `size` ; Note: the analog to `cond` is handled by the OO, which is good. ; If you're ever using 'instanceof' or using 'if ...== null', it's not really OO. ; Java: write `allNames` ; term: "composite design pattern" ; Java: write change-all-names ; ; Writing `equals` (in racket, then in Java) is interesting, ; -- especially ; ; ...backquote ; ...desc tree? No. Directories? ; ...parsing? Lang def? |#