<p>Hi Matthias, </p>
<p>Thanks for the feedback. Just a couple of questions before I give it another go if that&#39;s okay. I know there is something I need to learn from this exercise. </p>
<p>I am going through htdp first edition (at chapter 17 which refers to arrangements from chapter 12 which is why I revisited the exercise). Would you suggest continuing with this edition or moving to the draft second edition? </p>

<p>Do you mean the contract for insert-everywhere/word should be symbol word -&gt; list of words? And will the words returned be the same length? Ie am I aiming for the same result as the current definition? </p>
<p>Thanks Sean. </p>
<div class="gmail_quote">On Jul 5, 2012 9:15 PM, &quot;Matthias Felleisen&quot; &lt;<a href="mailto:matthias@ccs.neu.edu">matthias@ccs.neu.edu</a>&gt; wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Sean,<br>
<br>
1. I have re-arranged your program so that it becomes readable:<br>
<br>
-- the function that explains it all comes first<br>
-- if you need a helper function, it is placed below<br>
-- don&#39;t place functions at top that are called by functions further down<br>
        (roughly)<br>
<br>
-- make sure lines are at most 80 keystrokes wide<br>
<br>
2. I have separated the part you created with a == line from the one<br>
that is given.<br>
<br>
3. I added two comments in place where it becomes obvious that you<br>
didn&#39;t design according to the book but with an ad-hoc method.<br>
<br>
Overall, you discovered a design method that is introduced 2 chapters<br>
later. You used it when it is unnecessary to do so. The program is<br>
far more complicated (and thus slower) than needed.<br>
<br>
3a. It is possible that you have seen the exercise on creating a one-line<br>
editor (like Word or Notepad). At least the data structure suggests this<br>
is possible. IF SO (and I don&#39;t know whether this is true), then you might<br>
have designed by &quot;copy example, change until it works&quot;. IF SO, let me<br>
strongly discourage this approach or -- if you do follow it -- let me<br>
encourage you to be aware of it and to attempt a systematic approach,<br>
which tends to produce much better results.<br>
<br>
4. PLEASE feel encouraged to try again. Read the first piece of<br>
in-lined comment to just skip the whole split-word data structure.<br>
Follow the design recipe and you will find a wonderful solution.<br>
<br>
-- Matthias<br>
<br>
<br>
<br>
<br>
#lang racket<br>
<br>
(require test-engine/racket-tests)<br>
<br>
;; Word -&gt; [Listof Word]<br>
(check-expect (arrangements &#39;(a))  (list &#39;(a)))<br>
(check-expect (arrangements &#39;(a b)) (list &#39;(a b) &#39;(b a)))<br>
<br>
(define (arrangements a-word)<br>
  (cond<br>
    [(empty? a-word) (cons empty empty)]<br>
    [else<br>
     (insert-everywhere/in-all-words (first a-word) (arrangements (rest a-word)))]))<br>
<br>
;; =============================================================================<br>
<br>
; A split-word is a struct where left and right are list of words<br>
(define-struct split-word (left right))<br>
<br>
;; insert-everywhere/in-all-words symbol list-of-words -&gt; list of words<br>
;; insert the symbol in all possible positions in each word returning an<br>
;; expanded list of words<br>
<br>
(check-expect (insert-everywhere/in-all-words &#39;a (cons &#39;(b) empty))<br>
              (list (list &#39;a &#39;b) (list &#39;b &#39;a)))<br>
<br>
(check-expect (insert-everywhere/in-all-words &#39;d &#39;((e r) (r e)))<br>
              &#39;((d e r) (e d r) (e r d) (d r e) (r d e) (r e d)))<br>
<br>
(define (insert-everywhere/in-all-words s a-low)<br>
  (cond<br>
    [(empty? a-low) empty]<br>
    ;; MF: this is where it gets weird (from what you know):<br>
    ;; why do you introduce an intermediate data structure (split-word)<br>
    ;; to represent a word? It is *difficult* to justify this design with<br>
    ;; the material in the first three chapters.<br>
    ;; the function insert-everywhere/word should really just consume a word<br>
    [else (append (insert-everywhere/word s (make-split-word &#39;() (first a-low)))<br>
                  (insert-everywhere/in-all-words s (rest a-low)))]))<br>
<br>
;;insert-everywhere/in-one-word symbol split-word -&gt; low<br>
;; take a symbol and a split word and insert the symbol before and after each<br>
;; letter in the right hand side of the split creating a list of new words with<br>
;; the symbol progressing through.<br>
<br>
(check-expect (insert-everywhere/word &#39;a (make-split-word empty empty))<br>
              (list (list &#39;a)))<br>
(check-expect (insert-everywhere/word &#39;a (make-split-word &#39;(b) empty))<br>
              (list &#39;(b a)))<br>
(check-expect (insert-everywhere/word &#39;a (make-split-word empty &#39;(b)))<br>
              (list &#39;(a b) &#39;(b a)))<br>
(check-expect (insert-everywhere/word &#39;a (make-split-word empty &#39;(b c)))<br>
              (list &#39;(a b c) &#39;(b a c) &#39;(b c a)))<br>
<br>
(define (insert-everywhere/word s a-sw)<br>
  (cond<br>
    [(empty? (split-word-right a-sw)) (cons (insert-symbol s a-sw) empty)]<br>
    [else (cons (insert-symbol s a-sw)<br>
                ;; MF: this is where you go beyond what the design ideas you<br>
                ;; have seen in chapters 1 thru 3, and it makes the design<br>
                ;; utterly inelegant. Specifically, you are NOT applying<br>
                ;; insert-everywhere/word to a *piece* of a-sw but to a complete<br>
                ;; re-arrangement.<br>
                (insert-everywhere/word s (move-split a-sw)))]))<br>
<br>
;; move-split split-word -&gt; split-word<br>
;; return a new split word with the list on the left having the first of<br>
;; the right list appended to the end and the rest of the right<br>
(define (move-split a-sw)<br>
  (cond<br>
    [(empty? (split-word-right a-sw)) a-sw]<br>
    [else (make-split-word<br>
           (append (split-word-left a-sw) (list (first (split-word-right a-sw))))<br>
           (rest (split-word-right a-sw)))]))<br>
<br>
(check-expect (move-split (make-split-word empty empty))<br>
              (make-split-word empty empty))<br>
(check-expect (move-split (make-split-word &#39;(a) empty))<br>
              (make-split-word &#39;(a) empty))<br>
(check-expect (move-split (make-split-word &#39;(a) &#39;(b)))<br>
              (make-split-word &#39;(a b) empty))<br>
(check-expect (move-split (make-split-word &#39;(a) &#39;(b c)))<br>
              (make-split-word &#39;(a b) &#39;(c)))<br>
(check-expect (move-split (make-split-word &#39;(a b) &#39;(c d)))<br>
              (make-split-word &#39;(a b c) &#39;(d)))<br>
<br>
;; insert-symbol symbol split-word -&gt; word<br>
;; Insert the sysmbo at the front of the left list and append the right if left is empty<br>
;; Append to end of left if right list is empty<br>
;; Otherrwise insert between - returning one list<br>
<br>
(check-expect (insert-symbol &#39;a (make-split-word empty empty))<br>
              &#39;(a))<br>
(check-expect (insert-symbol &#39;a (make-split-word &#39;(b) empty))<br>
              &#39;(b a))<br>
(check-expect (insert-symbol &#39;a (make-split-word empty &#39;(b)))<br>
              &#39;(a b))<br>
(check-expect (insert-symbol &#39;a (make-split-word &#39;(b) &#39;(c)))<br>
              &#39;(b a c))<br>
<br>
(define (insert-symbol s a-sw)<br>
  (cond<br>
    [(empty? (split-word-right a-sw)) (append (split-word-left a-sw) (cons s empty))]<br>
    [(empty? (split-word-left a-sw)) (cons s (split-word-right a-sw))]<br>
    [else (append (split-word-left a-sw) (cons s (split-word-right a-sw)))]))<br>
<br>
</blockquote></div>