On Mon, Jul 2, 2012 at 1:51 AM, Dave Yrueta <dyru...@gmail.com> wrote: > I should have been more explicit: "ensuring the function design conforms to > its contract" means testing it in the manner demonstrated by Matthias. > "Check-expect" is your friend :). > On Jul 1, 2012, at 4:12 PM, Matthias Felleisen wrote: > >> >> On Jul 1, 2012, at 4:17 PM, Sean Kemplay wrote: >> >>> Looking back, I am wondering if my solution is a bit of a cheat - >>> specifically : >>> >>> (define (insert-everwhere/in-one-word s word) >>> (make-words s word word)) >> >> >> It's not a cheat, it's wrong. I did you a favor and worked out a failing >> test case. See below. >> >> >> On Jul 1, 2012, at 6:46 PM, Dave Yrueta wrote: >> >>> Try working through this exercise by systematically applying the design >>> recipe. That is, take the time to make your data definitions explicit, and >>> begin the definition of each helper function with a contract, purpose >>> statement, and template. In my opinion, more than any other exercise in >>> HtDP, the solution to this exercise relies on paying very close attention >>> to how the data definitions, function contracts and function templates >>> interact. If you allow the data definitions to shape the function >>> templates, and are rigorous about ensuring the function designs conform to >>> their contracts, the solution should fall into place. >> >> >> The above is the best advice the list can give you. -- Matthias >> >> >> >> >> ;; World = [Listof Letter] ;; see chapter IV >> ;; Letter = Symbol >> >> ;; Letter Word -> [Listof Word] >> ;; the function says: insert _s_ in all positions in _word_ >> >> (check-expect (insert-everwhere/in-one-word 'a '(w o)) >> '((a w o) (w a o) (w o a))) >> (check-expect (insert-everwhere/in-one-word 'a '(w w o)) >> '((a w w o) (w a w o) (w w a o) (w w o a))) >> >> (define (insert-everwhere/in-one-word s word) >> (make-words s word word)) >> >> ;; Letter Word Word -> [Listof Word] >> ;; insert _s_ in all positions in _word2_ using _word1_ as a list of >> insertion points >> ;; intended usage: (make-words letter word word) i.e. word1 = word2 initially >> >> (check-expect (make-words 'a '(w o) '(w o)) '((a w o) (w a o) (w o a))) >> (check-expect (make-words 'a '(w w o) '(w w o)) '((a w w o) (w a w o) (w w a >> o) (w w o a))) >> >> (define (make-words s word1 word2) >> (cond >> [(empty? word1) (cons (append word2 (cons s empty)) empty)] >> [else (cons (insert-symbol s (first word1) word2) (make-words s (cdr >> word1) word2))])) >> >> >> ;; Letter Letter Word -> Word >> ;; add _new_ in front of each occurrence of _old_ in _word_ >> >> (check-expect (insert-symbol 'a 'b '(c d e)) '(c d e)) ;; running in BSL >> with .. >> (check-expect (insert-symbol 'a 'b '(b o b)) '(a b o a b)) >> >> (define (insert-symbol new old word) >> (cond >> [(empty? word) empty] >> [(symbol=? (first word) old) (cons new (cons old (insert-symbol new old >> (rest word))))] >> [else (cons (first word) (insert-symbol new old (rest word)))])) >> >> >> ____________________ >> Racket Users list: >> http://lists.racket-lang.org/users >
Ok, I think I have it this time - only took five days!! After lots of hear pulling, I started thinking about the actual steps required to make the arrangements and created a wish list - then it started to make sense. And yes the tests really do help. ; A split-word is a struct where left and right are list of words (define-struct split-word (left right)) ;; move-split split-word -> split-word ;; return a new split word with the list on the left having the first of the right list appended to the end and the rest of the right (define (move-split a-sw) (cond [(empty? (split-word-right a-sw)) a-sw] [else (make-split-word (append (split-word-left a-sw) (cons (first (split-word-right a-sw)) empty)) (rest (split-word-right a-sw)))])) (check-expect (move-split (make-split-word empty empty)) (make-split-word empty empty)) (check-expect (move-split (make-split-word '(a) empty)) (make-split-word '(a) empty)) (check-expect (move-split (make-split-word '(a) '(b))) (make-split-word '(a b) empty)) (check-expect (move-split (make-split-word '(a) '(b c))) (make-split-word '(a b) '(c))) (check-expect (move-split (make-split-word '(a b) '(c d))) (make-split-word '(a b c) '(d))) ;; insert-symbol symbol split-word -> word ;; Insert the sysmbo at the front of the left list and append the right if left is empty ;; Append to end of left if right list is empty ;; Otherrwise insert between - returning one list (define (insert-symbol s a-sw) (cond [(empty? (split-word-right a-sw)) (append (split-word-left a-sw) (cons s empty))] [(empty? (split-word-left a-sw)) (cons s (split-word-right a-sw))] [else (append (split-word-left a-sw) (cons s (split-word-right a-sw)))])) (check-expect (insert-symbol 'a (make-split-word empty empty)) '(a)) (check-expect (insert-symbol 'a (make-split-word '(b) empty)) '(b a)) (check-expect (insert-symbol 'a (make-split-word empty '(b))) '(a b)) (check-expect (insert-symbol 'a (make-split-word '(b) '(c))) '(b a c)) ;;insert-everywhere/in-one-word symbol split-word -> low ;; take a symbol and a split word and insert the symbol before and after each letter in the right hand side of the split ;; creating a list of new words with the symbol progressing through. (define (insert-everywhere/in-one-word s a-sw) (cond [(empty? (split-word-right a-sw)) (cons (insert-symbol s a-sw) empty)] [else (cons (insert-symbol s a-sw) (insert-everywhere/in-one-word s (move-split a-sw)))])) (check-expect (insert-everywhere/in-one-word 'a (make-split-word empty empty)) (list (list 'a))) (check-expect (insert-everywhere/in-one-word 'a (make-split-word '(b) empty)) (list (list 'b 'a))) (check-expect (insert-everywhere/in-one-word 'a (make-split-word empty '(b))) (list '(a b) '(b a))) (check-expect (insert-everywhere/in-one-word 'a (make-split-word empty '(b c))) (list '(a b c) '(b a c) '(b c a))) ;; insert-everywhere/in-all-words symbol list-of-words -> list of words ;; insert the symbol in all possible positions in each word returning an expanded list of words (define (insert-everywhere/in-all-words s a-low) (cond [(empty? a-low) empty] [else (append (insert-everywhere/in-one-word s (make-split-word empty (first a-low))) (insert-everywhere/in-all-words s (rest a-low)))])) (check-expect (insert-everywhere/in-all-words 'a (cons '(b) empty)) (list (list 'a 'b) (list 'b 'a))) (check-expect (insert-everywhere/in-all-words 'd (cons (cons 'e (cons 'r empty)) (cons (cons 'r (cons 'e empty)) empty))) '((d e r) (e d r) (e r d) (d r e) (r d e) (r e d))) (define (arrangements a-word) (cond [(empty? a-word) (cons empty empty)] [else (insert-everywhere/in-all-words (first a-word) (arrangements (rest a-word)))])) (check-expect (arrangements '(a)) (list '(a))) (check-expect (arrangements '(a b)) (list '(a b) '(b a))) Any feedback welcome. Again, a big thank you for the advice above. Sean ____________________ Racket Users list: http://lists.racket-lang.org/users