#lang planet dyoo/whalesong/cs019 (define-struct f (x)) (define-struct g (a b)) (check-expect (build-list 5 add1) (list 1 2 3 4 5)) (check-expect (make-g 1 2) (make-g 1 2)) (check-expect (make-g 'b empty) (make-g 'b empty)) (check-expect (cond [(memq 'x (list 'a 'x 'b)) 1] [else 2]) 1) (define i (open-image-url "http://racket-lang.org/logo.png")) (check-expect (image-height i) 85) (check-expect (image-width i) 88) ;; Whalesong currently has no support for hashes. ;(define ht (hash)) ;(define ht2 (hash-set ht "x" 10)) ;(check-expect(hash-ref ht2 "x") 10) ;(check-error (hash-ref ht "x") "hash-ref: no value found for key: \"x\"") ;; INSERTION SORT (define: (isort [l : (Listof: Number$)]) -> (Listof: Number$) (cond [(empty? l) l] [(cons? l) (insert (first l) (isort (rest l)))])) (define: (insert [e : Number$] [l : (Listof: Number$)]) -> (Listof: Number$) (cond [(empty? l) (cons e l)] [(cons? l) (if (<= e (first l)) (cons e l) (cons (first l) (insert e (rest l))))])) (check-expect (isort (list 3 1 2 4)) (list 1 2 3 4)) ;; TREE ZIP ;(struct: None ()) ;(struct: (a) Some ([v : a])) ;(define-type (Opt a) (U None (Some a))) (define-struct: None ()) (define-struct: Some ([v : Any$])) (define Opt$ (or: None$ Some$)) ;(struct: (a) Node ([value : a] [kids : (Listof (Tree a))]) #:transparent) ;(struct: MtNode () #:transparent) ;(define-type Tree (All (a) (U (Node a) MtNode))) (define-struct: Node ([value : Any$] [kids : (Listof: Tree$)])) (define-struct: MtNode ()) (define Tree$ (or: Node$ MtNode$)) ;(struct: (a) BackPtr ([n : (Node a)] [p : Integer]) #:transparent) ;(struct: (a) Cursor ([below : (Tree a)] [above : (Listof (BackPtr a))]) #:transparent) (define-struct: BackPtr ([n : Node$] [p : (Sig: integer?)])) (define-struct: Cursor ([below : Tree$] [above : (Listof: BackPtr$)])) (define Opt-Cursor$ (Sig: (lambda (v) (or (None? v) (and (Some? v) (Cursor? (Some-v v))))))) ;(: find (All (a) ((Tree a) (a -> Boolean) -> (Cursor a)))) (define: (find [t : Tree$] [p : (Any$ -> Boolean$)]) -> Cursor$ (local [ ;(: find-helper (All (a) ((Tree a) (Listof (BackPtr a)) -> (Opt (Cursor a))))) (define: (find-helper [t : Tree$] [above : (Listof: BackPtr$)]) -> Opt-Cursor$ (cond [(MtNode? t) (make-None)] [(Node? t) (if (p (Node-value t)) (make-Some (make-Cursor t above)) (let ([v (search-kids (Node-kids t) 0 t above)]) (if (Some? v) v (make-None))))])) ; (: search-kids (All (a) ((Listof (Tree a)) ; Integer ; (Node a) ; (Listof (BackPtr a)) -> (Opt (Cursor a))))) (define: (search-kids [kids : (Listof: Tree$)] [n : (Sig: integer?)] [first-above : Node$] [rest-above : (Listof: BackPtr$)]) -> Opt-Cursor$ (cond [(empty? kids) (make-None)] [(cons? kids) (let ([v (find-helper (first kids) (cons (make-BackPtr first-above n) rest-above))]) (if (Some? v) v (search-kids (rest kids) (add1 n) first-above rest-above)))])) ] (let ([v (find-helper t empty)]) (if (None? v) (error 'find "no such node") (Some-v v))))) ;(: down (All (a) ((Cursor a) Integer -> (Cursor a)))) (define: (down [c : Cursor$] [n : (Sig: integer?)]) -> Cursor$ (let ([v (Cursor-below c)]) (cond [(MtNode? v) (error 'down "impossible to go down")] [(Node? v) (if (empty? (Node-kids v)) (error 'down "impossible to go down") (make-Cursor (list-ref (Node-kids v) n) (cons (make-BackPtr v n) (Cursor-above c))))]))) ;(: replace (All (a) ((Cursor a) (Tree a) -> (Cursor a)))) (define: (replace [c : Any$] [t : Tree$]) -> Cursor$ (make-Cursor t (Cursor-above c))) ;(: reconstruct/1 (All (a) ((BackPtr a) (Tree a) -> (Node a)))) (define: (reconstruct/1 [one-up : BackPtr$] [replace-with : Tree$]) -> Node$ (let ([node (BackPtr-n one-up)] [posn (BackPtr-p one-up)]) (let ([val (Node-value node)] [kids (Node-kids node)]) (make-Node val (build-list (length kids) (lambda: ([i : (Sig: integer?)]) -> Tree$ (if (= i posn) replace-with (list-ref kids i)))))))) ;(: up (All (a) ((Cursor a) -> (Cursor a)))) (define: (up [c : Cursor$]) -> Cursor$ (if (empty? (Cursor-above c)) (error 'up "impossible to go up") (make-Cursor (reconstruct/1 (first (Cursor-above c)) (Cursor-below c)) (rest (Cursor-above c))))) ;(: ->tree (All (a) ((Cursor a) -> (Tree a)))) (define: (->tree [c : Cursor$]) -> Tree$ (if (empty? (Cursor-above c)) (Cursor-below c) (->tree (up c)))) (define T (make-Node 7 (list (make-Node 3 empty) (make-MtNode) (make-Node 5 empty)))) (define c0 (find T (lambda: ([n : (Sig: integer?)]) -> Boolean$ (= n 3)))) (define c2 (find T (lambda: ([n : (Sig: integer?)]) -> Boolean$ (= n 5)))) (define c3 (replace (down (up c0) 1) T) ) (define c4 (replace (down (replace (down (up c0) 1) T) 0) (make-MtNode))) (check-expect T (->tree c0)) (check-expect T (->tree c2)) (check-expect (->tree c3) (make-Node 7 (list (make-Node 3 empty) (make-Node 7 (list (make-Node 3 empty) (make-MtNode) (make-Node 5 empty))) (make-Node 5 empty)))) (check-expect (->tree c4) (make-Node 7 (list (make-Node 3 empty) (make-Node 7 (list (make-MtNode) (make-MtNode) (make-Node 5 empty))) (make-Node 5 empty))))