Extended Exercise: Rearranging Words

Newspapers often contain exercises that ask readers to find all possible words made up from some letters. One way to play this game is to form all possible arrangements of the letters in a systematic manner and to see which arrangements are dictionary words. Suppose the letters ``a'', ``d'', ``e'', and ``r'' are given. There are twenty-four possible arrangements of these letters:

#tabular14871#

The three legitimate words in this list are ``read'', ``dear'', and ``dare.'' The systematic enumeration of all possible arrangements is clearly a task for a computer program. It consumes a word and produces a list of the word's letter-by-letter rearrangements. A simple representation of a word is a list of symbols. Each item in the input represents a letter: <#63134#><#14890#>'<#14890#><#14891#>a<#14891#><#63134#>, <#63135#><#14892#>'<#14892#><#14893#>b<#14893#><#63135#>, ..., <#63136#><#14894#>'<#14894#><#14895#>z<#14895#><#63136#>. Here is the data definition for the class of words:
A <#63137#><#14897#>word<#14897#><#63137#> is either
  1. <#63138#><#14899#>empty<#14899#><#63138#>, or
  2. <#63139#><#14900#>(cons<#14900#>\ <#14901#>a<#14901#>\ <#14902#>w)<#14902#><#63139#> where <#63140#><#14903#>a<#14903#><#63140#> is a symbol (<#63141#><#14904#>'<#14904#><#14905#>a<#14905#><#63141#>, <#63142#><#14906#>'<#14906#><#14907#>b<#14907#><#63142#>, ..., <#63143#><#14908#>'<#14908#><#14909#>z<#14909#><#63143#>) and <#63144#><#14910#>w<#14910#><#63144#> is a word.

<#14915#>Exercise 12.4.1<#14915#> Formulate the data definition for lists of words. Systematically make up examples of words and lists of words.~ external Solution<#63145#><#63145#> Let us call the function <#63146#><#14922#>arrangements<#14922#><#63146#>. Its template is that of a list-processing function:
<#71040#>;; <#63148#><#14928#>arrangements<#14928#> <#14929#>:<#14929#> <#14930#>word<#14930#> <#14931#><#14931#><#14932#>-;SPMgt;<#14932#><#14933#><#14933#> <#14934#>list-of-words<#14934#><#63148#><#71040#>
<#71041#>;; to create a list of all re-arrangements of the letters in <#63149#><#14935#>a-word<#14935#><#63149#><#71041#> 
<#14936#>(d<#14936#><#14937#>efine<#14937#> <#14938#>(arrangements<#14938#> <#14939#>a-word)<#14939#> 
  <#14940#>(c<#14940#><#14941#>ond<#14941#> 
    <#14942#>[<#14942#><#14943#>(empty?<#14943#> <#14944#>a-word)<#14944#> <#14945#>...]<#14945#> 
    <#14946#>[<#14946#><#14947#>else<#14947#> <#14948#>...<#14948#> <#14949#>(first<#14949#> <#14950#>a-word)<#14950#> <#14951#>...<#14951#> <#14952#>(arrangements<#14952#> <#14953#>(rest<#14953#> <#14954#>a-word))<#14954#> <#14955#>...]<#14955#><#14956#>))<#14956#> 
Given the contract, the supporting data definitions, and the examples, we can now look at each <#63150#><#14960#>cond<#14960#><#63150#>-line in the template:
  1. If the input is <#63151#><#14962#>empty<#14962#><#63151#>, there is only one possible re-arrangement of the input: the <#63152#><#14963#>empty<#14963#><#63152#> word. Hence, the result is <#63153#><#14964#>(cons<#14964#><#14965#> <#14965#><#14966#>empty<#14966#>\ <#14967#>empty)<#14967#><#63153#>, the list that contains the empty list as the only item.
  2. Otherwise there is a first letter in the word, and <#63154#><#14968#>(first<#14968#><#14969#> <#14969#><#14970#>a-word)<#14970#><#63154#> is that letter and the recursion produces the list of all possible re-arrangements for the rest of the word. For example, if the list is
    <#14975#>(cons<#14975#> <#14976#>'<#14976#><#14977#>d<#14977#> <#14978#>(cons<#14978#> <#14979#>'<#14979#><#14980#>e<#14980#> <#14981#>(cons<#14981#> <#14982#>'<#14982#><#14983#>r<#14983#> <#14984#>empty)))<#14984#>
    
    then the recursion is <#63155#><#14988#>(arrangements<#14988#>\ <#14989#>(cons<#14989#>\ <#14990#>'<#14990#><#14991#>e<#14991#>\ <#14992#>(cons<#14992#>\ <#14993#>'<#14993#><#14994#>r<#14994#><#14995#> <#14995#><#14996#>empty)))<#14996#><#63155#>. It will produce the result
    <#15001#>(c<#15001#><#15002#>ons<#15002#> <#15003#>(cons<#15003#> <#15004#>'<#15004#><#15005#>e<#15005#> <#15006#>(cons<#15006#> <#15007#>'<#15007#><#15008#>r<#15008#> <#15009#>empty))<#15009#>
      <#15010#>(c<#15010#><#15011#>ons<#15011#> <#15012#>(cons<#15012#> <#15013#>'<#15013#><#15014#>r<#15014#> <#15015#>(cons<#15015#> <#15016#>'<#15016#><#15017#>e<#15017#> <#15018#>empty))<#15018#> 
        <#15019#>empty))<#15019#> 
    
    To obtain all possible re-arrangements for the entire list, we must now insert the first item, <#63156#><#15023#>'<#15023#><#15024#>d<#15024#><#63156#> in our case, into all of these words between all possible letters and at the beginning and end.
The task of inserting a letter into many different words requires processing an arbitrarily large list. So, we need another function, call it <#63157#><#15026#>insert-everywhere/in-all-words<#15026#><#63157#>, to complete the definition of <#63158#><#15027#>arrangements<#15027#><#63158#>:
<#15032#>(d<#15032#><#15033#>efine<#15033#> <#15034#>(arrangements<#15034#> <#15035#>a-word)<#15035#>
  <#15036#>(c<#15036#><#15037#>ond<#15037#> 
    <#15038#>[<#15038#><#15039#>(empty?<#15039#> <#15040#>a-word)<#15040#> <#15041#>(cons<#15041#> <#15042#>empty<#15042#> <#15043#>empty)]<#15043#> 
    <#15044#>[<#15044#><#15045#>else<#15045#> <#15046#>(i<#15046#><#15047#>nsert-everywhere/in-all-words<#15047#> <#15048#>(first<#15048#> <#15049#>a-word)<#15049#> 
            <#15050#>(arrangements<#15050#> <#15051#>(rest<#15051#> <#15052#>a-word)))]<#15052#><#15053#>))<#15053#> 
<#15057#>Exercise 12.4.2<#15057#> Develop the function <#63159#><#15059#>insert-everywhere/in-all-words<#15059#><#63159#>. It consumes a symbol and a list of words. The result is a list of words like its second argument, but with the first argument inserted between all letters and at the beginning and the end of all words of the second argument. <#15060#>Hint:<#15060#> \ Re-consider the example from above. We stopped and decided that we needed to insert <#63160#><#15061#>'<#15061#><#15062#>d<#15062#><#63160#> into the words <#63161#><#15063#>(cons<#15063#>\ <#15064#>'<#15064#><#15065#>e<#15065#>\ <#15066#>(cons<#15066#>\ <#15067#>'<#15067#><#15068#>r<#15068#><#15069#> <#15069#><#15070#>empty))<#15070#><#63161#> and <#63162#><#15071#>(cons<#15071#>\ <#15072#>'<#15072#><#15073#>r<#15073#>\ <#15074#>(cons<#15074#>\ <#15075#>'<#15075#><#15076#>e<#15076#>\ <#15077#>empty))<#15077#><#63162#>. The following is therefore a natural candidate
<#15082#>(i<#15082#><#15083#>nsert-everywhere/in-all-words<#15083#> <#15084#>'<#15084#><#15085#>d<#15085#>
  <#15086#>(c<#15086#><#15087#>ons<#15087#> <#15088#>(cons<#15088#> <#15089#>'<#15089#><#15090#>e<#15090#> <#15091#>(cons<#15091#> <#15092#>'<#15092#><#15093#>r<#15093#> <#15094#>empty))<#15094#> 
    <#15095#>(c<#15095#><#15096#>ons<#15096#> <#15097#>(cons<#15097#> <#15098#>'<#15098#><#15099#>r<#15099#> <#15100#>(cons<#15100#> <#15101#>'<#15101#><#15102#>e<#15102#> <#15103#>empty))<#15103#> 
      <#15104#>empty)))<#15104#> 
for the ``function examples'' step. Keep in mind that the second input corresponds to the sequence of (partial) words ``er'' and ``re''. external Solution<#63163#><#63163#>