More Practice with Vectors

Programming with mutable vectors is hardly ever needed in the kinds of programs that we encountered. Still, because it is far more prevelant in conventional languages, it is an important skill and deserves more practice than section~#secdesignmutex1#57425> suggests. This section covers sorting with vectors, but its goal is to practice reasoning about intervals when processing vectors. We encountered the idea of sorting as early as in section~#secsortI#57426>, where we designed the <#70074#><#57427#>sort<#57427#><#70074#> function. It consumes a list of numbers and produces a list of numbers with the same items in sorted (ascending or descending) order. An analogous function for vectors consumes a vector and produces a new vector. But, using vector mutation, we can also design a function that changes the vector so that it contains the same items as before, in a sorted order. Such a function is called an <#57428#>in-place sort<#57428#> because it leaves all the items inside the existing vector. An in-place-sort function exclusively relies on effects on its input vector to accomplish its task:
<#72053#>;; <#70075#><#57433#>in-place-sort<#57433#> <#57434#>:<#57434#> <#57435#>(vectorof<#57435#> <#57436#>number)<#57436#> <#57437#><#57437#><#57438#>-;SPMgt;<#57438#><#57439#><#57439#> <#57440#>void<#57440#><#70075#><#72053#>
<#72054#>;; effect: to modify <#70076#><#57441#>V<#57441#><#70076#> such that it contains the same items <#72054#> 
<#57442#>;; as before but in ascending order <#57442#> 
<#57443#>(define<#57443#> <#57444#>(in-place-sort<#57444#> <#57445#>V)<#57445#> <#57446#>...)<#57446#> 
Examples must demonstrate the effect:
<#57454#>(l<#57454#><#57455#>ocal<#57455#> <#57456#>((define<#57456#> <#57457#>v1<#57457#> <#57458#>(vector<#57458#> <#57459#>7<#57459#> <#57460#>3<#57460#> <#57461#>0<#57461#> <#57462#>4<#57462#> <#57463#>1)))<#57463#>
  <#57464#>(b<#57464#><#57465#>egin<#57465#> 
    <#57466#>(in-place-sort<#57466#> <#57467#>v1)<#57467#> 
    <#57468#>(equal?<#57468#> <#57469#>v1<#57469#> <#57470#>(vector<#57470#> <#57471#>0<#57471#> <#57472#>1<#57472#> <#57473#>3<#57473#> <#57474#>4<#57474#> <#57475#>7))))<#57475#> 
Of course, given that <#70077#><#57479#>in-place-sort<#57479#><#70077#> consumes a vector, the true problem is to design the auxiliary function that works on specific segments of the vector. The standard template for a vector-processing function uses an auxiliary function:
<#57484#>(d<#57484#><#57485#>efine<#57485#> <#57486#>(in-place-sort<#57486#> <#57487#>V)<#57487#>
  <#57488#>(l<#57488#><#57489#>ocal<#57489#> <#57490#>((d<#57490#><#57491#>efine<#57491#> <#57492#>(sort-aux<#57492#> <#57493#>V<#57493#> <#57494#>i)<#57494#> 
            <#57495#>(c<#57495#><#57496#>ond<#57496#> 
              <#57497#>[<#57497#><#57498#>(zero?<#57498#> <#57499#>i)<#57499#> <#57500#>...]<#57500#> 
              <#57501#>[<#57501#><#57502#>e<#57502#><#57503#>lse<#57503#> 
                <#57504#>...<#57504#> <#57505#>(vector-ref<#57505#> <#57506#>V<#57506#> <#57507#>(sub1<#57507#> <#57508#>i))<#57508#> <#57509#>...<#57509#> 
                <#57510#>...<#57510#> <#57511#>(sort-aux<#57511#> <#57512#>V<#57512#> <#57513#>(sub1<#57513#> <#57514#>i))<#57514#> <#57515#>...]<#57515#><#57516#>)))<#57516#> 
    <#57517#>(sort-aux<#57517#> <#57518#>V<#57518#> <#57519#>(vector-length<#57519#> <#57520#>V))))<#57520#> 
Following the design ideas of intermezzo~5, the auxiliary function consumes a natural number and uses it as an index into the vector. Because the initial argument is <#70078#><#57524#>(vector-length<#57524#>\ <#57525#>V)<#57525#><#70078#>, the accessible index is always <#70079#><#57526#>(sub1<#57526#>\ <#57527#>i)<#57527#><#70079#>. Recall that the key to designing functions such as <#70080#><#57528#>sort-aux<#57528#><#70080#> is to formulate a rigorous purpose and/of effect statement. The statement must clarify on which interval of the possible vector indices the function works and what exactly it accomplishes. One natural effect statement follows:
<#72055#>;; <#70081#><#57533#>sort-aux<#57533#> <#57534#>:<#57534#> <#57535#>(vectorof<#57535#> <#57536#>number)<#57536#> <#57537#>N<#57537#> <#57538#><#57538#><#57539#>-;SPMgt;<#57539#><#57540#><#57540#> <#57541#>void<#57541#><#70081#><#72055#>
<#72056#>;; effect: to sort the interval [<#70082#><#57542#>0<#57542#><#70082#>,<#70083#><#57543#>i<#57543#><#70083#>) of <#70084#><#57544#>V<#57544#><#70084#> in place <#72056#> 
<#57545#>(define<#57545#> <#57546#>(sort-aux<#57546#> <#57547#>V<#57547#> <#57548#>i)<#57548#> <#57549#>...)<#57549#> 
To understand this effect statement in the larger context, let's adapt our original example:
<#57557#>(l<#57557#><#57558#>ocal<#57558#> <#57559#>((define<#57559#> <#57560#>v1<#57560#> <#57561#>(vector<#57561#> <#57562#>7<#57562#> <#57563#>3<#57563#> <#57564#>0<#57564#> <#57565#>4<#57565#> <#57566#>1)))<#57566#>
  <#57567#>(b<#57567#><#57568#>egin<#57568#> 
    <#57569#>(sort-aux<#57569#> <#57570#>v1<#57570#> <#57571#>5)<#57571#> 
    <#57572#>(equal?<#57572#> <#57573#>v1<#57573#> <#57574#>(vector<#57574#> <#57575#>0<#57575#> <#57576#>1<#57576#> <#57577#>3<#57577#> <#57578#>4<#57578#> <#57579#>7))))<#57579#> 
If <#70085#><#57583#>sort-aux<#57583#><#70085#> is applied to a vector's length, it should sort the entire vector. This statement implies that if the first argument is less than the vector's length only some initial segment of the vector is sorted:
<#57588#>(l<#57588#><#57589#>ocal<#57589#> <#57590#>((define<#57590#> <#57591#>v1<#57591#> <#57592#>(vector<#57592#> <#57593#>7<#57593#> <#57594#>3<#57594#> <#57595#>0<#57595#> <#57596#>4<#57596#> <#57597#>1)))<#57597#>
  <#57598#>(b<#57598#><#57599#>egin<#57599#> 
    <#57600#>(sort-aux<#57600#> <#57601#>v1<#57601#> <#57602#>4)<#57602#> 
    <#57603#>(equal?<#57603#> <#57604#>v1<#57604#> <#57605#>(vector<#57605#> <#57606#>0<#57606#> <#57607#>3<#57607#> <#57608#>4<#57608#> <#57609#>7<#57609#> <#57610#>1))))<#57610#> 
In this particular example, the last number remains in its original place, and only the first four vector items are sorted.
<#72057#>;; <#70086#><#57618#>in-place-sort<#57618#> <#57619#>:<#57619#> <#57620#>(vectorof<#57620#> <#57621#>number)<#57621#> <#57622#><#57622#><#57623#>-;SPMgt;<#57623#><#57624#><#57624#> <#57625#>void<#57625#><#70086#><#72057#>
<#72058#>;; effect: to modify <#70087#><#57626#>V<#57626#><#70087#> such that it contains the same items <#72058#> 
<#57627#>;; as before but in ascending order <#57627#> 
<#57628#>(d<#57628#><#57629#>efine<#57629#> <#57630#>(in-place-sort<#57630#> <#57631#>V)<#57631#> 
  <#57632#>(l<#57632#><#57633#>ocal<#57633#> <#57634#>(<#57634#><#72059#>;; <#70088#><#57635#>sort-aux<#57635#> <#57636#>:<#57636#> <#57637#>(vectorof<#57637#> <#57638#>number)<#57638#> <#57639#>N<#57639#> <#57640#><#57640#><#57641#>-;SPMgt;<#57641#><#57642#><#57642#> <#57643#>void<#57643#><#70088#><#72059#> 
          <#72060#>;; effect: to sort the interval [<#70089#><#57644#>0<#57644#><#70089#>,<#70090#><#57645#>i<#57645#><#70090#>) of <#70091#><#57646#>V<#57646#><#70091#> in place <#72060#> 
          <#57647#>(d<#57647#><#57648#>efine<#57648#> <#57649#>(sort-aux<#57649#> <#57650#>V<#57650#> <#57651#>i)<#57651#> 
            <#57652#>(c<#57652#><#57653#>ond<#57653#> 
              <#57654#>[<#57654#><#57655#>(zero?<#57655#> <#57656#>i)<#57656#> <#57657#>(<#57657#><#57658#>void<#57658#><#57659#>)]<#57659#> 
              <#57660#>[<#57660#><#57661#>else<#57661#> <#57662#>(b<#57662#><#57663#>egin<#57663#> 
                      <#72061#>;; sort the segment [<#70092#><#57664#>0<#57664#><#70092#>,<#70093#><#57665#>(sub1<#57665#> <#57666#>i)<#57666#><#70093#>):<#72061#> 
                      <#57667#>(sort-aux<#57667#> <#57668#>V<#57668#> <#57669#>(sub1<#57669#> <#57670#>i))<#57670#> 
                      <#72062#>;; insert <#70094#><#57671#>(vector-ref<#57671#> <#57672#>V<#57672#> <#57673#>(sub1<#57673#> <#57674#>i))<#57674#><#70094#> into the segment <#72062#> 
                      <#72063#>;; [<#70095#><#57675#>0<#57675#><#70095#>,<#70096#><#57676#>i<#57676#><#70096#>) so that it becomes sorted''<#72063#> 
                      <#57677#>(insert<#57677#> <#57678#>(sub1<#57678#> <#57679#>i)<#57679#> <#57680#>V))]<#57680#><#57681#>))<#57681#> 
          
          <#72064#>;; <#70097#><#57682#>insert<#57682#> <#57683#>:<#57683#> <#57684#>N<#57684#> <#57685#>(vectorof<#57685#> <#57686#>number)<#57686#> <#57687#><#57687#><#57688#>-;SPMgt;<#57688#><#57689#><#57689#> <#57690#>void<#57690#><#70097#><#72064#> 
          <#72065#>;; to place the value in the <#70098#><#57691#>i<#57691#><#70098#>-th into its proper place <#72065#> 
          <#72066#>;; in the segement [<#70099#><#57692#>0<#57692#><#70099#>,<#70100#><#57693#>i<#57693#><#70100#>] of <#70101#><#57694#>V<#57694#><#70101#><#72066#> 
          <#72067#>;; assume: the segment [<#70102#><#57695#>0<#57695#><#70102#>,<#70103#><#57696#>i<#57696#><#70103#>) of <#70104#><#57697#>V<#57697#><#70104#> is sorted<#72067#> 
          <#57698#>(d<#57698#><#57699#>efine<#57699#> <#57700#>(insert<#57700#> <#57701#>i<#57701#> <#57702#>V)<#57702#> 
            <#57703#>...))<#57703#> 
    <#57704#>(sort-aux<#57704#> <#57705#>V<#57705#> <#57706#>(vector-length<#57706#> <#57707#>V))))<#57707#> 
<#70105#>Figure: An <#57711#>in-place<#57711#> sort function: first part<#70105#>
Now we can analyze each case in the template of <#70106#><#57713#>sort-aux<#57713#><#70106#>:
  1. If <#70107#><#57715#>i<#57715#><#70107#> is <#70108#><#57716#>0<#57716#><#70108#>, the interval of the effect statement is [<#70109#><#57717#>0<#57717#><#70109#>,<#70110#><#57718#>0<#57718#><#70110#>). This means that the interval is empty and that the function has nothing to do.
  2. The second clause in the template contains two expressions:
    <#57723#>(vector-ref<#57723#> <#57724#>V<#57724#> <#57725#>(sub1<#57725#> <#57726#>i))<#57726#>
    <#57727#>;and<#57727#> 
    <#57728#>(sort-aux<#57728#> <#57729#>V<#57729#> <#57730#>(sub1<#57730#> <#57731#>i))<#57731#> 
    
    The first reminds us that we can use the i-1-st field of <#70111#><#57735#>V<#57735#><#70111#>; the second one reminds us of the natural recursion. In this case, the natural recursion sorts the interval [<#70112#><#57736#>0<#57736#><#70112#>,<#70113#><#57737#>(sub1<#57737#>\ <#57738#>i)<#57738#><#70113#>). To finish the task, we must insert the value of the i-1-st field into its proper place in the interval [<#70114#><#57739#>0<#57739#><#70114#>,<#70115#><#57740#>i<#57740#><#70115#>). The above examples make this case concrete. When we evaluate <#70116#><#57741#>(sort-aux<#57741#><#57742#> <#57742#><#57743#>v1<#57743#>\ <#57744#>4)<#57744#><#70116#>, the number in the last field of <#70117#><#57745#>v1<#57745#><#70117#> remains at its place. The first four items in the vectors are: <#70118#><#57746#>0<#57746#><#70118#>, <#70119#><#57747#>3<#57747#><#70119#>, <#70120#><#57748#>4<#57748#><#70120#>, and <#70121#><#57749#>7<#57749#><#70121#>. To sort the entire interval [<#70122#><#57750#>0<#57750#><#70122#>,<#70123#><#57751#>5<#57751#><#70123#>), we must insert <#70124#><#57752#>1<#57752#><#70124#>, which is <#70125#><#57753#>(vector-ref<#57753#>\ <#57754#>V<#57754#>\ <#57755#>(sub1<#57755#>\ <#57756#>5))<#57756#><#70125#>, between <#70126#><#57757#>0<#57757#><#70126#> and <#70127#><#57758#>3<#57758#><#70127#>.
In short, the design of <#70128#><#57760#>in-place-sort<#57760#><#70128#> follows the same pattern as that of the function <#70129#><#57761#>sort<#57761#><#70129#> in section~#secsortI#57762> up to this point. For <#70130#><#57763#>sort<#57763#><#70130#>, we also designed the main function only to find out that we needed to design an auxiliary function for inserting one more item into its proper place. Figure~#figinplacesort1#57764> gathers what we have discussed about <#70131#><#57765#>in-place-sort<#57765#><#70131#> so far. It also includes a specification of <#70132#><#57766#>insert<#57766#><#70132#>, the second auxiliary function. To understand its effect statement, we reformulate the example for the second clause of <#70133#><#57767#>sort-aux<#57767#><#70133#>:
<#57772#>(l<#57772#><#57773#>ocal<#57773#> <#57774#>((define<#57774#> <#57775#>v1<#57775#> <#57776#>(vector<#57776#> <#57777#>0<#57777#> <#57778#>3<#57778#> <#57779#>4<#57779#> <#57780#>7<#57780#> <#57781#>1)))<#57781#>
  <#57782#>(b<#57782#><#57783#>egin<#57783#> 
    <#57784#>(insert<#57784#> <#57785#>4<#57785#> <#57786#>v1)<#57786#> 
    <#57787#>(equal?<#57787#> <#57788#>v1<#57788#> <#57789#>(vector<#57789#> <#57790#>0<#57790#> <#57791#>1<#57791#> <#57792#>3<#57792#> <#57793#>4<#57793#> <#57794#>7))))<#57794#> 
In this case, <#70134#><#57798#>insert<#57798#><#70134#> moves <#70135#><#57799#>1<#57799#><#70135#> over three numbers: first <#70136#><#57800#>7<#57800#><#70136#>, then <#70137#><#57801#>4<#57801#><#70137#>, and finally <#70138#><#57802#>3<#57802#><#70138#>. It stops when the next number in the leftwards direction, that is, <#70139#><#57803#>0<#57803#><#70139#>, is smaller than the number that is being inserted. Let's look at a second example for <#70140#><#57804#>insert<#57804#><#70140#>:
<#57809#>(l<#57809#><#57810#>ocal<#57810#> <#57811#>((define<#57811#> <#57812#>v1<#57812#> <#57813#>(vector<#57813#> <#57814#>7<#57814#> <#57815#>3<#57815#> <#57816#>0<#57816#> <#57817#>4<#57817#> <#57818#>1)))<#57818#>
  <#57819#>(b<#57819#><#57820#>egin<#57820#> 
    <#57821#>(insert<#57821#> <#57822#>1<#57822#> <#57823#>v1)<#57823#> 
    <#57824#>(equal?<#57824#> <#57825#>v1<#57825#> <#57826#>(vector<#57826#> <#57827#>3<#57827#> <#57828#>7<#57828#> <#57829#>0<#57829#> <#57830#>4<#57830#> <#57831#>1))))<#57831#> 
Here the problem is to insert <#70141#><#57835#>3<#57835#><#70141#> into a segment that contains only one number: <#70142#><#57836#>7<#57836#><#70142#>. This means that insert must swap the values in the first two fields and must stop then, because <#70143#><#57837#>3<#57837#><#70143#> can't move any further to the left.
<#57842#>(d<#57842#><#57843#>efine<#57843#> <#57844#>(in-place-sort<#57844#> <#57845#>V)<#57845#>
  <#57846#>(l<#57846#><#57847#>ocal<#57847#> <#57848#>(<#57848#><#72068#>;; <#70144#><#57849#>sort-aux<#57849#> <#57850#>:<#57850#> <#57851#>(vectorof<#57851#> <#57852#>number)<#57852#> <#57853#>N<#57853#> <#57854#><#57854#><#57855#>-;SPMgt;<#57855#><#57856#><#57856#> <#57857#>void<#57857#><#70144#><#72068#> 
          <#72069#>;; effect: to sort the interval [<#70145#><#57858#>0<#57858#><#70145#>,<#70146#><#57859#>i<#57859#><#70146#>) of <#70147#><#57860#>V<#57860#><#70147#> in place <#72069#> 
          <#57861#>(d<#57861#><#57862#>efine<#57862#> <#57863#>(sort-aux<#57863#> <#57864#>V<#57864#> <#57865#>i)<#57865#> 
            <#57866#>...)<#57866#> 
          
          <#72070#>;; <#70148#><#57867#>insert<#57867#> <#57868#>:<#57868#> <#57869#>N<#57869#> <#57870#>(vectorof<#57870#> <#57871#>number)<#57871#> <#57872#><#57872#><#57873#>-;SPMgt;<#57873#><#57874#><#57874#> <#57875#>void<#57875#><#70148#><#72070#> 
          <#72071#>;; to place the value in the <#70149#><#57876#>i<#57876#><#70149#>-th into its proper place <#72071#> 
          <#72072#>;; in the [<#70150#><#57877#>0<#57877#><#70150#>,<#70151#><#57878#>i<#57878#><#70151#>] segement of <#70152#><#57879#>V<#57879#><#70152#><#72072#> 
          <#57880#>(d<#57880#><#57881#>efine<#57881#> <#57882#>(insert<#57882#> <#57883#>i<#57883#> <#57884#>V)<#57884#> 
            <#57885#>(c<#57885#><#57886#>ond<#57886#> 
              <#57887#>[<#57887#><#57888#>(zero?<#57888#> <#57889#>i)<#57889#> <#57890#>(<#57890#><#57891#>void<#57891#><#57892#>)]<#57892#> 
              <#57893#>[<#57893#><#57894#>else<#57894#> <#57895#>(c<#57895#><#57896#>ond<#57896#> 
                      <#57897#>[<#57897#><#57898#>(;SPMgt;<#57898#> <#57899#>(vector-ref<#57899#> <#57900#>V<#57900#> <#57901#>(sub1<#57901#> <#57902#>i))<#57902#> <#57903#>(vector-ref<#57903#> <#57904#>V<#57904#> <#57905#>i))<#57905#> 
                       <#57906#>(b<#57906#><#57907#>egin<#57907#> 
                         <#57908#>(swap<#57908#> <#57909#>V<#57909#> <#57910#>(-<#57910#> <#57911#>i<#57911#> <#57912#>1)<#57912#> <#57913#>i)<#57913#> 
                         <#57914#>(insert<#57914#> <#57915#>(sub1<#57915#> <#57916#>i)<#57916#> <#57917#>V))]<#57917#> 
                      <#57918#>[<#57918#><#57919#>else<#57919#> <#57920#>(<#57920#><#57921#>void<#57921#><#57922#>)]<#57922#><#57923#>)]<#57923#><#57924#>))<#57924#> 
          
          <#72073#>;; <#70153#><#57925#>swap<#57925#> <#57926#>:<#57926#> <#57927#>(vectorof<#57927#> <#57928#>X)<#57928#> <#57929#>N<#57929#> <#57930#>N<#57930#> <#57931#><#57931#><#57932#>-;SPMgt;<#57932#><#57933#><#57933#> <#57934#>void<#57934#> <#70153#><#72073#> 
          <#57935#>(d<#57935#><#57936#>efine<#57936#> <#57937#>(swap<#57937#> <#57938#>V<#57938#> <#57939#>i<#57939#> <#57940#>j)<#57940#> 
            <#57941#>(l<#57941#><#57942#>ocal<#57942#> <#57943#>((define<#57943#> <#57944#>temp<#57944#> <#57945#>(vector-ref<#57945#> <#57946#>V<#57946#> <#57947#>i)))<#57947#> 
              <#57948#>(b<#57948#><#57949#>egin<#57949#> 
                <#57950#>(vector-set!<#57950#> <#57951#>V<#57951#> <#57952#>i<#57952#> <#57953#>(vector-ref<#57953#> <#57954#>V<#57954#> <#57955#>j))<#57955#> 
                <#57956#>(vector-set!<#57956#> <#57957#>V<#57957#> <#57958#>j<#57958#> <#57959#>temp)))))<#57959#> 
    <#57960#>(sort-aux<#57960#> <#57961#>V<#57961#> <#57962#>(vector-length<#57962#> <#57963#>V))))<#57963#> 
<#70154#>Figure: An <#57967#>in-place<#57967#> sort function: second part<#70154#>
Now take a look at the template for <#70155#><#57969#>insert<#57969#><#70155#>:
<#57974#>(d<#57974#><#57975#>efine<#57975#> <#57976#>(insert<#57976#> <#57977#>i<#57977#> <#57978#>V)<#57978#> 
  <#57979#>(c<#57979#><#57980#>ond<#57980#> 
    <#57981#>[<#57981#><#57982#>(zero?<#57982#> <#57983#>i)<#57983#> <#57984#>...]<#57984#> 
    <#57985#>[<#57985#><#57986#>e<#57986#><#57987#>lse<#57987#> 
      <#57988#>...<#57988#> <#57989#>(vector-ref<#57989#> <#57990#>V<#57990#> <#57991#>(sub1<#57991#> <#57992#>i))<#57992#> <#57993#>...<#57993#> 
      <#57994#>...<#57994#> <#57995#>(insert<#57995#> <#57996#>(sub1<#57996#> <#57997#>i)<#57997#> <#57998#>V)<#57998#> <#57999#>...<#57999#> <#58000#>]<#58000#><#58001#>))<#58001#> 
It is the standard template for a vector-processing auxiliary function. As usual we distinguish two cases:
  1. If <#70156#><#58006#>i<#58006#><#70156#> is <#70157#><#58007#>0<#58007#><#70157#>, the goal is to insert <#70158#><#58008#>(vector-ref<#58008#>\ <#58009#>V<#58009#>\ <#58010#>0)<#58010#><#70158#> into the segment [<#70159#><#58011#>0<#58011#><#70159#>,<#70160#><#58012#>0<#58012#><#70160#>]. Since this interval contains only one number, <#70161#><#58013#>insert<#58013#><#70161#> has accomplished its task.
  2. If <#70162#><#58014#>i<#58014#><#70162#> is positive, the template implies that we may consider another item in <#70163#><#58015#>V<#58015#><#70163#>, namely <#70164#><#58016#>(vector-ref<#58016#>\ <#58017#>V<#58017#>\ <#58018#>(sub1<#58018#>\ <#58019#>i))<#58019#><#70164#>, and that we can perform a natural recursion. The immediate question is whether <#70165#><#58020#>(vector-ref<#58020#>\ <#58021#>V<#58021#>\ <#58022#>(sub1<#58022#>\ <#58023#>i))<#58023#><#70165#> is smaller or larger than <#70166#><#58024#>(vector-ref<#58024#><#58025#> <#58025#><#58026#>V<#58026#>\ <#58027#>i)<#58027#><#70166#>, the item that is to be moved around. If so, <#70167#><#58028#>V<#58028#><#70167#> is sorted on the entire interval [<#70168#><#58029#>0<#58029#><#70168#>,<#70169#><#58030#>i<#58030#><#70169#>], because <#70170#><#58031#>V<#58031#><#70170#> is sorted on [<#70171#><#58032#>0<#58032#><#70171#>,<#70172#><#58033#>i<#58033#><#70172#>) by assumption. If not, the item at <#70173#><#58034#>i<#58034#><#70173#> is out of order still. The <#58035#>cond<#58035#>-expression\ that employs the necessary conditions is
    <#58040#>(c<#58040#><#58041#>ond<#58041#>
      <#58042#>[<#58042#><#58043#>(;SPMgt;<#58043#> <#58044#>(vector-ref<#58044#> <#58045#>V<#58045#> <#58046#>(sub1<#58046#> <#58047#>i))<#58047#> <#58048#>(vector-ref<#58048#> <#58049#>V<#58049#> <#58050#>i))<#58050#> <#58051#>...]<#58051#> 
      <#58052#>[<#58052#><#58053#>(;SPMlt;=<#58053#> <#58054#>(vector-ref<#58054#> <#58055#>V<#58055#> <#58056#>(sub1<#58056#> <#58057#>i))<#58057#> <#58058#>(vector-ref<#58058#> <#58059#>V<#58059#> <#58060#>i))<#58060#> <#58061#>(<#58061#><#58062#>void<#58062#><#58063#>)]<#58063#><#58064#>)<#58064#> 
    
    The second clause contains <#70174#><#58068#>(<#58068#><#58069#>void<#58069#><#58070#>)<#58070#><#70174#> because nothing is left to do. In the first clause, <#70175#><#58071#>insert<#58071#><#70175#> must---at a minimum---swap the values in the two fields. That is, <#70176#><#58072#>insert<#58072#><#70176#> must place <#70177#><#58073#>(vector-ref<#58073#>\ <#58074#>V<#58074#>\ <#58075#>i)<#58075#><#70177#> into field~<#70178#><#58076#>(sub1<#58076#>\ <#58077#>i)<#58077#><#70178#> and <#70179#><#58078#>(vector-ref<#58078#>\ <#58079#>V<#58079#>\ <#58080#>(sub1<#58080#>\ <#58081#>i))<#58081#><#70179#> into field~<#70180#><#58082#>i<#58082#><#70180#>. But even that may not be enough. After all, the value in the <#70181#><#58083#>i<#58083#><#70181#>-th field may have to wander over several fields as the first example demonstarted. Fortunately, we can easily solve this problem with the natural recursion, which inserts the <#70182#><#58084#>(vector-ref<#58084#>\ <#58085#>V<#58085#>\ <#58086#>(sub1<#58086#>\ <#58087#>i))<#58087#><#70182#> into its proper place in [0,<#70183#><#58088#>(sub1<#58088#>\ <#58089#>i)<#58089#><#70183#>] after the swapping has taken place.
Figure~#figinplacesort2#58091> contains the complete definition of <#70184#><#58092#>insert<#58092#><#70184#> and <#70185#><#58093#>swap<#58093#><#70185#>. This second function is responsible for swaping the value of two fields.
<#58096#>Exercise 43.1.1<#58096#> Test the auxiliary functions for <#70186#><#58098#>in-place-sort<#58098#><#70186#> from figures~#figinplacesort1#58099> and~#figinplacesort2#58100>. Formulate the tests as boolean-valued expressions. Develop and test more examples for <#70187#><#58101#>in-place-sort<#58101#><#70187#>. Integrate the pieces. Test the integrated function. Eliminate superflous arguments from the auxiliary programs in the integrated definition, step by step, testing the complete function after each step. Finally, change <#70188#><#58102#>in-place-sort<#58102#><#70188#> so that its result is the modified vector.~ external Solution<#70189#><#70189#>
rawhtml65 <#58108#>Figure: Inserting an item into a sorted vector segment<#58108#>
<#58110#>Exercise 43.1.2<#58110#> The <#70190#><#58112#>insert<#58112#><#70190#> function of figure~#figinplacesort2#58113> performs two vector mutations for each time the function recurs. Each of these mutations pushed <#70191#><#58114#>(vector-ref<#58114#>\ <#58115#>V<#58115#>\ <#58116#>i)<#58116#><#70191#>, for the original value of <#70192#><#58117#>i<#58117#><#70192#>, to the left in <#70193#><#58118#>V<#58118#><#70193#> until its proper place is found. Figure~#figsortinplace#58119> illustrates a slightly better solution. The situation in the top row assumes that the values <#70194#><#58120#>a<#58120#><#70194#>, <#70195#><#58121#>b<#58121#><#70195#>, and <#70196#><#58122#>c<#58122#><#70196#> are properly arranged, that is,
<#58127#>(;SPMlt;<#58127#> <#58128#>a<#58128#> <#58129#>b<#58129#> <#58130#>...<#58130#> <#58131#>c)<#58131#>
holds. Furthermore, <#70197#><#58135#>d<#58135#><#70197#> is to be inserted and its place is between <#70198#><#58136#>a<#58136#><#70198#> and <#70199#><#58137#>b<#58137#><#70199#>, that is,
<#58142#>(;SPMlt;<#58142#> <#58143#>a<#58143#> <#58144#>d<#58144#> <#58145#>b)<#58145#>
holds, too. The solution is to compare <#70200#><#58149#>d<#58149#><#70200#> with all the items in k+1 through i and to shift the items to the right if they are larger than <#70201#><#58150#>d<#58150#><#70201#>. Eventually, we find <#70202#><#58151#>a<#58151#><#70202#> (or the left end of the vector) and have a ``hole'' in the vector, where <#70203#><#58152#>d<#58152#><#70203#> must be inserted. (The hole actually contains <#70204#><#58153#>b<#58153#><#70204#>.) This situation is illustrated in the middle row. The last one shows how <#70205#><#58154#>d<#58154#><#70205#> is placed in between <#70206#><#58155#>a<#58155#><#70206#> and <#70207#><#58156#>b<#58156#><#70207#>. Develop a function <#70208#><#58157#>insert<#58157#><#70208#> that implements its desired effect according to this description. <#58158#>Hint:<#58158#> \ The new function must consume <#70209#><#58159#>d<#58159#><#70209#> as an additional argument.~ external Solution<#70210#><#70210#> <#58165#>Exercise 43.1.3<#58165#> For many other programs, we could swap the order of the subexpressions in <#70211#><#58167#>begin<#58167#>-expression<#70211#>s and still get a working program. Let's consider this idea for <#70212#><#58168#>sort-aux<#58168#><#70212#>:
 
<#72074#>;; <#70213#><#58173#>sort2-aux<#58173#> <#58174#>:<#58174#> <#58175#>(vectorof<#58175#> <#58176#>number)<#58176#> <#58177#>N<#58177#> <#58178#><#58178#><#58179#>-;SPMgt;<#58179#><#58180#><#58180#> <#58181#>void<#58181#><#70213#><#72074#> 
<#58182#>(d<#58182#><#58183#>efine<#58183#> <#58184#>(sort2-aux<#58184#> <#58185#>V<#58185#> <#58186#>i)<#58186#> 
  <#58187#>(c<#58187#><#58188#>ond<#58188#> 
    <#58189#>[<#58189#><#58190#>(zero?<#58190#> <#58191#>i)<#58191#> <#58192#>(<#58192#><#58193#>void<#58193#><#58194#>)]<#58194#> 
    <#58195#>[<#58195#><#58196#>else<#58196#> <#58197#>(b<#58197#><#58198#>egin<#58198#> 
            <#58199#>(insert2<#58199#> <#58200#>(sub1<#58200#> <#58201#>i)<#58201#> <#58202#>V)<#58202#> 
            <#58203#>(sort2-aux<#58203#> <#58204#>V<#58204#> <#58205#>(sub1<#58205#> <#58206#>i)))]<#58206#><#58207#>))<#58207#> 
The order implies that <#70214#><#58211#>sort2-aux<#58211#><#70214#> first inserts the item from <#70215#><#58212#>(sub1<#58212#>\ <#58213#>i)<#58213#><#70215#> into some already-sorted part of <#70216#><#58214#>V<#58214#><#70216#> and then sorts the remainder of <#70217#><#58215#>V<#58215#><#70217#>. Here is a picture that illustrates the situation graphically: rawhtml66 The depicted vector consists of three pieces: <#70218#><#58216#>a<#58216#><#70218#>, the item in field~<#70219#><#58217#>(sub1<#58217#>\ <#58218#>i)<#58218#><#70219#>, the left fragment, and the right fragment. The questions are which of the two fragments is sorted and into which fragment <#70220#><#58219#>a<#58219#><#70220#> should be inserted. Considering that <#70221#><#58220#>sort2-aux<#58220#><#70221#> decreases its first argument and thus sweeps over the vector from right to left, the answers are that the right fragment is initially empty and thus sorted in ascending order by default; the left fragment is still unordered; and <#70222#><#58221#>a<#58221#><#70222#> must be inserted into its proper place in the right fragment. Develop a precise effect statement for <#70223#><#58222#>sort-aux<#58222#><#70223#> based on these observations. Then develop the function <#70224#><#58223#>insert2<#58223#><#70224#> so that <#70225#><#58224#>sort2-aux<#58224#><#70225#> sorts vectors properly.~ external Solution<#70226#><#70226#>
In section~#secsortII#58232>, we got to know <#70227#><#58233#>quicksort<#58233#><#70227#>, a function based on generative recursion. Given a list, <#70228#><#58234#>quicksort<#58234#><#70228#> constructs a sorted version in three steps:
  1. choose an item from the list, call it <#70229#><#58236#>pivot<#58236#><#70229#>;
  2. create two sublists: one with all those items strictly smaller than <#70230#><#58237#>pivot<#58237#><#70230#>, another one with all those items strictly larger than <#70231#><#58238#>pivot<#58238#><#70231#>;
  3. sort each of the two sublists, using the same steps, and then append the two lists with the pivot item in the middle.
It isn't difficult to see why the result is sorted, why it contains all the items from the original list, and why the process stops. After all, at every stage, the function removes at least one item from the list so that the two sublists are shorter than the given one; eventually the list must be empty.
rawhtml67 <#58240#>Figure: A partitioning step for in-place quick-sort<#58240#>
Figure~#figpartqsort#58242> illustrates how this idea can be adapted for an in-place version that works on vectors. At each stage, the algorithm works on a specific fragment of the vector. It picks the first item as the <#70232#><#58243#>pivot<#58243#><#70232#> item and rearranges the fragment so that all items smaller than the pivot appear to the left of <#70233#><#58244#>pivot<#58244#><#70233#> and all those items larger than <#70234#><#58245#>pivot<#58245#><#70234#> appear to its right. Then <#70235#><#58246#>quicksort<#58246#><#70235#> is used twice: once for the fragment between <#70236#><#58247#>left1<#58247#><#70236#> and <#70237#><#58248#>right1<#58248#><#70237#> and another time for the fragment between <#70238#><#58249#>left2<#58249#><#70238#> and <#70239#><#58250#>right2<#58250#><#70239#>. Because each of these two intervals is shorter than the originally given interval, <#70240#><#58251#>quicksort<#58251#><#70240#> eventually encounters the empty interval and stops. After <#70241#><#58252#>quicksort<#58252#><#70241#> has sorted each fragment, there is nothing left to do; the partitioning arranged the vector into fragments of ascending order. Here is the definition of <#70242#><#58253#>qsort<#58253#><#70242#>, an in-place sorting algorithm for vectors:
<#72075#>;; <#70243#><#58258#>qsort<#58258#> <#58259#>:<#58259#> <#58260#>(vectorof<#58260#> <#58261#>number)<#58261#> <#58262#><#58262#><#58263#>-;SPMgt;<#58263#><#58264#><#58264#> <#58265#>(vectorof<#58265#> <#58266#>number)<#58266#><#70243#><#72075#>
<#72076#>;; to sort <#70244#><#58267#>V<#58267#><#70244#> in ascending order<#72076#> 
<#72077#>;; effect: to modify <#70245#><#58268#>V<#58268#><#70245#> such that it contains the same items <#72077#> 
<#58269#>;; as before but in ascending order <#58269#> 
<#58270#>(d<#58270#><#58271#>efine<#58271#> <#58272#>(qsort<#58272#> <#58273#>V)<#58273#> 
  <#58274#>(qsort-aux<#58274#> <#58275#>V<#58275#> <#58276#>0<#58276#> <#58277#>(sub1<#58277#> <#58278#>(vector-length<#58278#> <#58279#>V))))<#58279#> 
<#72078#>;; <#70246#><#58280#>qsort-aux<#58280#> <#58281#>:<#58281#> <#58282#>(vectorof<#58282#> <#58283#>number)<#58283#> <#58284#>N<#58284#> <#58285#>N<#58285#> <#58286#><#58286#><#58287#>-;SPMgt;<#58287#><#58288#><#58288#> <#58289#>(vectorof<#58289#> <#58290#>number)<#58290#><#70246#><#72078#> 
<#72079#>;; to sort <#70247#><#58291#>V<#58291#><#70247#> in ascending order, between left and right<#72079#> 
<#72080#>;; effect: sort the interval [<#70248#><#58292#>left<#58292#><#70248#>,<#70249#><#58293#>right<#58293#><#70249#>] of vector <#70250#><#58294#>V<#58294#><#70250#><#72080#> 
<#58295#>;; generative recursion<#58295#> 
<#58296#>(d<#58296#><#58297#>efine<#58297#> <#58298#>(qsort-aux<#58298#> <#58299#>V<#58299#> <#58300#>left<#58300#> <#58301#>right)<#58301#> 
  <#58302#>(c<#58302#><#58303#>ond<#58303#> 
    <#58304#>[<#58304#><#58305#>(;SPMgt;=<#58305#> <#58306#>left<#58306#> <#58307#>right)<#58307#> <#58308#>V]<#58308#> 
    <#58309#>[<#58309#><#58310#>else<#58310#> <#58311#>(l<#58311#><#58312#>ocal<#58312#> <#58313#>((define<#58313#> <#58314#>new-pivot-position<#58314#> <#58315#>(partition<#58315#> <#58316#>V<#58316#> <#58317#>left<#58317#> <#58318#>right)))<#58318#> 
            <#58319#>(b<#58319#><#58320#>egin<#58320#> 
              <#58321#>(qsort-aux<#58321#> <#58322#>V<#58322#> <#58323#>left<#58323#> <#58324#>(sub1<#58324#> <#58325#>new-pivot-position))<#58325#> 
              <#58326#>(qsort-aux<#58326#> <#58327#>V<#58327#> <#58328#>(add1<#58328#> <#58329#>new-pivot-position)<#58329#> <#58330#>right)))]<#58330#><#58331#>))<#58331#> 
The main function's input is a vector, so it uses an auxiliary function to do its job. As suggested above, the auxiliary function consumes the vector and two boundaries. Each boundary is an index into the vector. Initially, the boundaries are <#70251#><#58335#>0<#58335#><#70251#> and <#70252#><#58336#>(sub1<#58336#>\ <#58337#>(vector-length<#58337#>\ <#58338#>V))<#58338#><#70252#>, which means that <#70253#><#58339#>qsort-aux<#58339#><#70253#> is to sort the entire vector. The definition of <#70254#><#58340#>qsort-aux<#58340#><#70254#> closely follows the algoritm's description. If <#70255#><#58341#>left<#58341#><#70255#> and <#70256#><#58342#>right<#58342#><#70256#> describe a boundary of size~1 or less, its task is done. Otherwise, it partitions the vector. Because the partitioning step is a separate complex process, it requires a separate function. It must have both an effect and a result proper, the new index for the pivot item, which is now at its proper place. Given this index, <#70257#><#58343#>qsort-aux<#58343#><#70257#> continues to sort <#70258#><#58344#>V<#58344#><#70258#> on the intervals [<#70259#><#58345#>left<#58345#><#70259#>,<#70260#><#58346#>(sub1<#58346#>\ <#58347#>new-pivot-position)<#58347#><#70260#>] and [<#70261#><#58348#>(add1<#58348#>\ <#58349#>new-pivot-position)<#58349#><#70261#>, <#70262#><#58350#>right<#58350#><#70262#>]. Both intervals are at least one item shorter than the original, which is the termination argument for <#70263#><#58351#>qsort-aux<#58351#><#70263#>. Naturally, the key problem here is the partitioning step, which is implemented by <#70264#><#58352#>partition<#58352#><#70264#>:
<#72081#>;; <#70265#><#58357#>partition<#58357#> <#58358#>:<#58358#> <#58359#>(vectorof<#58359#> <#58360#>number)<#58360#> <#58361#>N<#58361#> <#58362#>N<#58362#> <#58363#><#58363#><#58364#>-;SPMgt;<#58364#><#58365#><#58365#> <#58366#>N<#58366#><#70265#><#72081#>
<#72082#>;; to determine the proper position <#70266#><#58367#>p<#58367#><#70266#> of the pivot-item <#72082#> 
<#58368#>;; effect: rearrange the so that <#58368#> 
<#72083#>;; -- all items in <#70267#><#58369#>V<#58369#><#70267#> in [<#70268#><#58370#>left<#58370#><#70268#>,<#70269#><#58371#>p<#58371#><#70269#>) are smaller than the pivot item<#72083#> 
<#72084#>;; -- all items of <#70270#><#58372#>V<#58372#><#70270#> in (<#70271#><#58373#>p<#58373#><#70271#>,<#70272#><#58374#>right<#58374#><#70272#>] are larger than the pivot item<#72084#> 
<#58375#>(define<#58375#> <#58376#>(partition<#58376#> <#58377#>V<#58377#> <#58378#>left<#58378#> <#58379#>right)<#58379#> <#58380#>...)<#58380#> 
For simplicity, we choose the leftmost item in the given interval as the pivot item. The question is how <#70273#><#58384#>partition<#58384#><#70273#> can accomplish its task, for example, whether it is a function based on structural recursion or whether it is based on generative recursion. Furthermore, if it is based on generative recursion, the question is what the generative step accomplishes.
rawhtml68 <#58385#>Figure: A partitioning step for in-place quick-sort<#58385#>
The best strategy is to consider an example and to see how the partitioning step could be accomplished. The first example is a small vector with six numbers:
<#58391#>(vector<#58391#> <#58392#>1.1<#58392#> <#58393#>0.75<#58393#> <#58394#>1.9<#58394#> <#58395#>0.35<#58395#> <#58396#>0.58<#58396#> <#58397#>2.2)<#58397#>
The pivot's position is <#70274#><#58401#>0<#58401#><#70274#>; the pivot item is <#70275#><#58402#>1.1<#58402#><#70275#>. The boundaries are <#70276#><#58403#>0<#58403#><#70276#> and <#70277#><#58404#>5<#58404#><#70277#>. One item, <#70278#><#58405#>1.9<#58405#><#70278#> is obviously out of place. If we swap it with <#70279#><#58406#>0.58<#58406#><#70279#>, then the vector is almost perfectly partitioned:
<#58411#>(vector<#58411#> <#58412#>1.1<#58412#> <#58413#>0.75<#58413#> <#58414#>0.58<#58414#> <#58415#>0.35<#58415#> <#58416#>1.9<#58416#> <#58417#>2.2)<#58417#>
In this modified vector, the only item out of place is the pivot item itself. Figure~#figpartswap#58421> illustrates the swapping process that we just described. First, we must find two items to swap. To do that, we search <#70280#><#58422#>V<#58422#><#70280#> for the first item to the right of <#70281#><#58423#>left<#58423#><#70281#> that is larger than the pivot item. Analogously, we search <#70282#><#58424#>V<#58424#><#70282#> for the first item to the left of <#70283#><#58425#>right<#58425#><#70283#> that is smaller than the pivot item. These searcges yield two indices: <#70284#><#58426#>new-left<#58426#><#70284#> and <#70285#><#58427#>new-right<#58427#><#70285#>. Second, we swap the items in fields <#70286#><#58428#>new-left<#58428#><#70286#> and <#70287#><#58429#>new-right<#58429#><#70287#>. The result is that the item at <#70288#><#58430#>new-left<#58430#><#70288#> is now smaller than the pivot item and the one at <#70289#><#58431#>new-right<#58431#><#70289#> is larger. Finally, we can continue the swapping process with the new, smaller interval. When the first step yields values for <#70290#><#58432#>new-left<#58432#><#70290#> and <#70291#><#58433#>new-right<#58433#><#70291#> that are out of order, as in the bottom row of figure~#figpartswap#58434>, then we have a mostly partitioned vector (fragment). Working through this first example suggests that <#70292#><#58435#>partition<#58435#><#70292#> is an algorithm, that is, a function based on generative recursion. Following our recipe, we must ask and answer four questions:
  1. What is a trivially solvable problem?
  2. What is a corresponding solution?
  3. How do we generate new problems that are more easily solvable than the original problem? Is there one new problem that we generate or are there several?
  4. Is the solution of the given problem the same as the solution of (one of) the new problems? Or, do we need to perform an additional computation to combine these solutions before we have a final solution? And, if so, do we need anything from the original problem data?
The example addressed issues~1, 3 and~4. The first step is to determine the <#70293#><#58438#>new-left<#58438#><#70293#> and <#70294#><#58439#>new-right<#58439#><#70294#> indices. If <#70295#><#58440#>new-left<#58440#><#70295#> is smaller than <#70296#><#58441#>new-right<#58441#><#70296#>, the generative work is to swap items in the two fields. Then the process recurs with the two new boundaries. If <#70297#><#58442#>new-left<#58442#><#70297#> is larger than <#70298#><#58443#>new-right<#58443#><#70298#>, the partitioning process is finished with the exception of the placement of the pivot item; placing the pivot item answers question~2. Assuming we can solve this ``trivially solvable'' problem, we also know that the overall problem is solved Let's study question~2 with some examples. We stopped working on the first example when the vector had been changed to
<#58448#>(vector<#58448#> <#58449#>1.1<#58449#> <#58450#>0.75<#58450#> <#58451#>0.58<#58451#> <#58452#>0.35<#58452#> <#58453#>1.9<#58453#> <#58454#>2.2)<#58454#>
and the interval had been narrowed down to [<#70299#><#58458#>2<#58458#><#70299#>,<#70300#><#58459#>4<#58459#><#70300#>]. The search for <#70301#><#58460#>new-left<#58460#><#70301#> and <#70302#><#58461#>new-right<#58461#><#70302#> now yields <#70303#><#58462#>4<#58462#><#70303#> and <#70304#><#58463#>3<#58463#><#70304#>, respectively. That is,
<#58468#>(;SPMlt;=<#58468#> <#58469#>new-right<#58469#> <#58470#>new-left)<#58470#>
holds. Switching the item in field <#70305#><#58474#>new-right<#58474#><#70305#> with the original left-most boundary places the pivot item in the proper spot:
<#58479#>(vector<#58479#> <#58480#>0.35<#58480#> <#58481#>0.75<#58481#> <#58482#>0.58<#58482#>  <#58483#>1.1<#58483#> <#58484#>1.9<#58484#> <#58485#>2.2)<#58485#>
because <#70306#><#58489#>new-right<#58489#><#70306#> points at the right-most item that is smaller than the pivot item. Before we accept this seemingly simple solution, we must check it with some additional examples, especially examples where the pivot item is the largest or smallest item in the vector fragment of interest. Here is one such example:
<#58494#>(vector<#58494#> <#58495#>1.1<#58495#> <#58496#>0.1<#58496#> <#58497#>0.5<#58497#> <#58498#>0.4)<#58498#>
Assuming the initial interval is [<#70307#><#58502#>0<#58502#><#70307#>,<#70308#><#58503#>3<#58503#><#70308#>], the pivot item is <#70309#><#58504#>1.1<#58504#><#70309#>. Thus, all other items in the vector are smaller than the pivot item, which means that it should end up in the right most position. Our process clearly yields <#70310#><#58505#>3<#58505#><#70310#> for <#70311#><#58506#>new-right<#58506#><#70311#>. After all, <#70312#><#58507#>0.4<#58507#><#70312#> is smaller than pivot. The search for <#70313#><#58508#>new-left<#58508#><#70313#>, though, works differently. Since none of the items in the vector are larger than the pivot item, it eventually generates <#70314#><#58509#>3<#58509#><#70314#> as an index, which is the largest legal index for this vector. At this point the search must stop. Fortunately, <#70315#><#58510#>new-left<#58510#><#70315#> and <#70316#><#58511#>new-right<#58511#><#70316#> are equal at this point, which implies that the partitioning process can stop and which means that we can still swap the pivot item with the one in field <#70317#><#58512#>new-right<#58512#><#70317#>. If we do that, we get
<#58517#>(vector<#58517#> <#58518#>0.4<#58518#> <#58519#>0.1<#58519#> <#58520#>0.5<#58520#> <#58521#>0.4<#58521#> <#58522#>1.1)<#58522#>
which is a perfectly well-partitioned vector. The third example uses a vector whose items are all larger than the pivot item:
<#58530#>(vector<#58530#> <#58531#>1.1<#58531#> <#58532#>1.2<#58532#> <#58533#>3.3<#58533#> <#58534#>2.4)<#58534#>
In this case, the pivot item is already in the right spot, and the search for <#70318#><#58538#>new-left<#58538#><#70318#> and <#70319#><#58539#>new-right<#58539#><#70319#> should discover this fact. On one hand, the search for <#70320#><#58540#>new-left<#58540#><#70320#> ends at field~1, which is the first field that contains an item larger than the pivot item. On the other hand, the search for <#70321#><#58541#>new-right<#58541#><#70321#> ends with <#70322#><#58542#>0<#58542#><#70322#>, because it is the smallest legal index and the search must stop there. As before, the search for the swapping points suggests that the process must stop, and <#70323#><#58543#>new-right<#58543#><#70323#> once again points to that field in the vector that must contain the pivot item for the vector (fragment) to be properly partitioned. In short, the examples suggest several things:
  1. The termination condition for <#70324#><#58545#>partition<#58545#><#70324#> is <#70325#><#58546#>(;SPMlt;=<#58546#><#58547#> <#58547#><#58548#>new-right<#58548#>\ <#58549#>new-left)<#58549#><#70325#>.
  2. The value of <#70326#><#58550#>new-right<#58550#><#70326#> is the final position of the pivot item, which is in the original left-most point of the interval of interest. It is always acceptable to swap the contents of the two fields.
  3. The search for <#70327#><#58551#>new-right<#58551#><#70327#> starts at the right-most boundary and continues until it either finds an item that is smaller than the pivot item or until it hits the left-most boundary.
  4. Dually, the search for <#70328#><#58552#>new-left<#58552#><#70328#> starts at the left-most boundary and continues until it either finds an item that is larger than the pivot item or until it hits the right-most boundary.
And, the two searches are complex tasks that deserve their own function. We can now gradually translate our discussion into Scheme. First, the partitioning process is a function of not just the vector and some interval, but also of the original leftmost position of the vector and its content. This suggests the use of <#70329#><#58554#>local<#58554#><#70329#>ly defined functions and variables:
<#58559#>(d<#58559#><#58560#>efine<#58560#> <#58561#>(partition<#58561#> <#58562#>V<#58562#> <#58563#>left<#58563#> <#58564#>right)<#58564#>
  <#58565#>(l<#58565#><#58566#>ocal<#58566#> <#58567#>(<#58567#><#58568#>(define<#58568#> <#58569#>pivot-position<#58569#> <#58570#>left)<#58570#> 
          <#58571#>(define<#58571#> <#58572#>the-pivot<#58572#> <#58573#>(vector-ref<#58573#> <#58574#>V<#58574#> <#58575#>left))<#58575#> 
          <#58576#>(d<#58576#><#58577#>efine<#58577#> <#58578#>(partition-aux<#58578#> <#58579#>left<#58579#> <#58580#>right)<#58580#> 
            <#58581#>...))<#58581#> 
    <#58582#>(partition-aux<#58582#> <#58583#>left<#58583#> <#58584#>right)))<#58584#> 
The alternative is to use an auxiliary function that consumes the pivot's original position in addition to the vector and the current interval. Second, the auxiliary function's consumes an interval's boundaries. It immediately generates a new pair of indices from these boundaries: <#70330#><#58588#>new-left<#58588#><#70330#> and <#70331#><#58589#>new-right<#58589#><#70331#>. As mentioned, the search for the two new boundaries are complex tasks and deserve their own functions:
<#72085#>;; <#70332#><#58594#>find-new-right<#58594#> <#58595#>:<#58595#> <#58596#>(vectorof<#58596#> <#58597#>number)<#58597#> <#58598#>number<#58598#> <#58599#>N<#58599#> <#58600#>N<#58600#> <#58601#>[<#58601#><#58602#>;SPMgt;=<#58602#> <#58603#>left]<#58603#> <#58604#><#58604#><#58605#>-;SPMgt;<#58605#><#58606#><#58606#> <#58607#>N<#58607#><#70332#><#72085#>
<#72086#>;; to determine an index <#70333#><#58608#>i<#58608#><#70333#> between <#70334#><#58609#>right<#58609#><#70334#> and <#70335#><#58610#>left<#58610#><#70335#> (inclusive)<#72086#> 
<#72087#>;; such that <#70336#><#58611#>(;SPMlt;<#58611#> <#58612#>(vector-ref<#58612#> <#58613#>V<#58613#> <#58614#>i)<#58614#> <#58615#>the-pivot)<#58615#><#70336#> holds<#72087#> 
<#58616#>(define<#58616#> <#58617#>(find-new-right<#58617#> <#58618#>V<#58618#> <#58619#>the-pivot<#58619#> <#58620#>right<#58620#> <#58621#>left)<#58621#> <#58622#>...)<#58622#> 
<#72088#>;; <#70337#><#58623#>find-new-left<#58623#> <#58624#>:<#58624#> <#58625#>(vectorof<#58625#> <#58626#>number)<#58626#> <#58627#>number<#58627#> <#58628#>N<#58628#> <#58629#>N<#58629#> <#58630#>[<#58630#><#58631#>;SPMlt;=<#58631#> <#58632#>right]<#58632#> <#58633#><#58633#><#58634#>-;SPMgt;<#58634#><#58635#><#58635#> <#58636#>N<#58636#><#70337#><#72088#> 
<#72089#>;; to determine an index <#70338#><#58637#>i<#58637#><#70338#> between <#70339#><#58638#>left<#58638#><#70339#> and <#70340#><#58639#>right<#58639#><#70340#> (inclusive)<#72089#> 
<#72090#>;; such that <#70341#><#58640#>(;SPMgt;<#58640#> <#58641#>(vector-ref<#58641#> <#58642#>V<#58642#> <#58643#>i)<#58643#> <#58644#>the-pivot)<#58644#><#70341#> holds<#72090#> 
<#58645#>(define<#58645#> <#58646#>(find-new-left<#58646#> <#58647#>V<#58647#> <#58648#>the-pivot<#58648#> <#58649#>left<#58649#> <#58650#>right)<#58650#> <#58651#>...)<#58651#> 
Using these two functions, <#70342#><#58655#>partition-aux<#58655#><#70342#> can generate the new boundaries:
<#58660#>(d<#58660#><#58661#>efine<#58661#> <#58662#>(partition<#58662#> <#58663#>V<#58663#> <#58664#>left<#58664#> <#58665#>right)<#58665#>
  <#58666#>(l<#58666#><#58667#>ocal<#58667#> <#58668#>(<#58668#><#58669#>(define<#58669#> <#58670#>pivot-position<#58670#> <#58671#>left)<#58671#> 
          <#58672#>(define<#58672#> <#58673#>the-pivot<#58673#> <#58674#>(vector-ref<#58674#> <#58675#>V<#58675#> <#58676#>left))<#58676#> 
          <#58677#>(d<#58677#><#58678#>efine<#58678#> <#58679#>(partition-aux<#58679#> <#58680#>left<#58680#> <#58681#>right)<#58681#> 
            <#58682#>(l<#58682#><#58683#>ocal<#58683#> <#58684#>(<#58684#><#58685#>(define<#58685#> <#58686#>new-right<#58686#> <#58687#>(find-new-right<#58687#> <#58688#>V<#58688#> <#58689#>the-pivot<#58689#> <#58690#>right<#58690#> <#58691#>left))<#58691#> 
                    <#58692#>(define<#58692#> <#58693#>new-left<#58693#> <#58694#>(find-new-left<#58694#> <#58695#>V<#58695#> <#58696#>the-pivot<#58696#> <#58697#>left<#58697#> <#58698#>right)))<#58698#> 
              <#58699#>...<#58699#> <#58700#>)))<#58700#> 
    <#58701#>(partition<#58701#> <#58702#>left<#58702#> <#58703#>right)))<#58703#> 
Finally, from here the rest of the definition is a plain transliteration of our discussion into Scheme.
<#72091#>;; <#70343#><#58711#>partition<#58711#> <#58712#>:<#58712#> <#58713#>(vectorof<#58713#> <#58714#>number)<#58714#> <#58715#>N<#58715#> <#58716#>N<#58716#> <#58717#><#58717#><#58718#>-;SPMgt;<#58718#><#58719#><#58719#> <#58720#>N<#58720#><#70343#><#72091#>
<#72092#>;; to determine the proper position <#70344#><#58721#>p<#58721#><#70344#> of the pivot-item <#72092#> 
<#58722#>;; effect: rearrange the so that <#58722#> 
<#72093#>;; -- all items in <#70345#><#58723#>V<#58723#><#70345#> in [<#70346#><#58724#>left<#58724#><#70346#>,<#70347#><#58725#>p<#58725#><#70347#>) are smaller than the pivot item<#72093#> 
<#72094#>;; -- all items of <#70348#><#58726#>V<#58726#><#70348#> in (<#70349#><#58727#>p<#58727#><#70349#>,<#70350#><#58728#>right<#58728#><#70350#>] are larger than the pivot item<#72094#> 
<#58729#>;; generative recursion<#58729#> 
<#58730#>(d<#58730#><#58731#>efine<#58731#> <#58732#>(partition<#58732#> <#58733#>V<#58733#> <#58734#>left<#58734#> <#58735#>right)<#58735#> 
  <#58736#>(l<#58736#><#58737#>ocal<#58737#> <#58738#>(<#58738#><#58739#>(define<#58739#> <#58740#>pivot-position<#58740#> <#58741#>left)<#58741#> 
          <#58742#>(define<#58742#> <#58743#>the-pivot<#58743#> <#58744#>(vector-ref<#58744#> <#58745#>V<#58745#> <#58746#>left))<#58746#> 
          <#58747#>(d<#58747#><#58748#>efine<#58748#> <#58749#>(partition-aux<#58749#> <#58750#>left<#58750#> <#58751#>right)<#58751#> 
            <#58752#>(l<#58752#><#58753#>ocal<#58753#> <#58754#>(<#58754#><#58755#>(define<#58755#> <#58756#>new-right<#58756#> <#58757#>(find-new-right<#58757#> <#58758#>V<#58758#> <#58759#>the-pivot<#58759#> <#58760#>right<#58760#> <#58761#>left))<#58761#> 
                    <#58762#>(define<#58762#> <#58763#>new-left<#58763#> <#58764#>(find-new-left<#58764#> <#58765#>V<#58765#> <#58766#>the-pivot<#58766#> <#58767#>left<#58767#> <#58768#>right)))<#58768#> 
              <#58769#>(c<#58769#><#58770#>ond<#58770#> 
                <#58771#>[<#58771#><#58772#>(;SPMgt;=<#58772#> <#58773#>new-left<#58773#> <#58774#>new-right)<#58774#> 
                 <#58775#>(b<#58775#><#58776#>egin<#58776#> 
                   <#58777#>(swap<#58777#> <#58778#>V<#58778#> <#58779#>pivot-position<#58779#> <#58780#>new-right)<#58780#> 
                   <#58781#>new-right)]<#58781#> 
                <#58782#>[<#58782#><#58783#>else<#58783#> <#72095#>; <#70351#><#58784#>(;SPMlt;<#58784#> <#58785#>new-left<#58785#> <#58786#>new-right)<#58786#><#70351#><#72095#> 
                 <#58787#>(b<#58787#><#58788#>egin<#58788#> 
                   <#58789#>(swap<#58789#> <#58790#>V<#58790#> <#58791#>new-left<#58791#> <#58792#>new-right)<#58792#> 
                   <#58793#>(partition-aux<#58793#> <#58794#>new-left<#58794#> <#58795#>new-right))]<#58795#><#58796#>))))<#58796#> 
    <#58797#>(partition<#58797#> <#58798#>left<#58798#> <#58799#>right)))<#58799#> 
<#72096#>;; <#70352#><#58800#>find-new-right<#58800#> <#58801#>:<#58801#> <#58802#>(vectorof<#58802#> <#58803#>number)<#58803#> <#58804#>number<#58804#> <#58805#>N<#58805#> <#58806#>N<#58806#> <#58807#>[<#58807#><#58808#>;SPMgt;=<#58808#> <#58809#>left]<#58809#> <#58810#><#58810#><#58811#>-;SPMgt;<#58811#><#58812#><#58812#> <#58813#>N<#58813#><#70352#><#72096#> 
<#72097#>;; to determine an index <#70353#><#58814#>i<#58814#><#70353#> between <#70354#><#58815#>right<#58815#><#70354#> and <#70355#><#58816#>left<#58816#><#70355#> (inclusive)<#72097#> 
<#72098#>;; such that <#70356#><#58817#>(;SPMlt;<#58817#> <#58818#>(vector-ref<#58818#> <#58819#>V<#58819#> <#58820#>i)<#58820#> <#58821#>the-pivot)<#58821#><#70356#> holds<#72098#> 
<#58822#>;; structural recursion: see text<#58822#> 
<#58823#>(d<#58823#><#58824#>efine<#58824#> <#58825#>(find-new-right<#58825#> <#58826#>V<#58826#> <#58827#>the-pivot<#58827#> <#58828#>left<#58828#> <#58829#>right)<#58829#> 
  <#58830#>(c<#58830#><#58831#>ond<#58831#> 
    <#58832#>[<#58832#><#58833#>(=<#58833#> <#58834#>right<#58834#> <#58835#>left)<#58835#> <#58836#>right]<#58836#> 
    <#58837#>[<#58837#><#58838#>else<#58838#> <#58839#>(c<#58839#><#58840#>ond<#58840#> 
            <#58841#>[<#58841#><#58842#>(;SPMlt;<#58842#> <#58843#>(vector-ref<#58843#> <#58844#>V<#58844#> <#58845#>right)<#58845#> <#58846#>the-pivot)<#58846#> <#58847#>right]<#58847#> 
            <#58848#>[<#58848#><#58849#>else<#58849#> <#58850#>(find-new-right<#58850#> <#58851#>V<#58851#> <#58852#>the-pivot<#58852#> <#58853#>left<#58853#> <#58854#>(sub1<#58854#> <#58855#>right))]<#58855#><#58856#>)]<#58856#><#58857#>))<#58857#> 
<#58861#>Figure: Rearranging a vector fragment into two partitions<#58861#>
Figure~#figpartip#58863> contains the complete definition of <#70357#><#58864#>partition<#58864#><#70357#>, <#70358#><#58865#>partition-aux<#58865#><#70358#>, and <#70359#><#58866#>find-new-right<#58866#><#70359#>; the function <#70360#><#58867#>swap<#58867#><#70360#> is defined in figure~#figinplacesort2#58868>. The definition of the search function uses an unusual structural recursion based on subclasses of natural numbers whose limits are parameters of the function. Because the search functions are based on a rarely used design recipe, it is best to design them separately. Still, they are only useful in the context of <#70361#><#58869#>partition<#58869#><#70361#>, which means that they should be integrated into its definition when their design is completed.
<#58872#>Exercise 43.1.4<#58872#> Complete the definition of <#70362#><#58874#>find-new-left<#58874#><#70362#>. The two definitions have the same structure; develop the common abstraction. Use the definitions of <#70363#><#58875#>find-new-right<#58875#><#70363#> and <#70364#><#58876#>find-new-left<#58876#><#70364#> to provide a termination argument for <#70365#><#58877#>partition-aux<#58877#><#70365#>. Use the examples to develop tests for <#70366#><#58878#>partition<#58878#><#70366#>. Recall that the function computes the proper place for the pivot item and rearranges a fragment of the vector. Formulate the tests as boolean-valued expressions. When the functions are properly tested, integrate <#70367#><#58879#>find-new-right<#58879#><#70367#> and <#70368#><#58880#>find-new-left<#58880#><#70368#> into <#70369#><#58881#>partition<#58881#><#70369#> and eliminate superfluous parameters. Finally, test <#70370#><#58882#>qsort<#58882#><#70370#> and produce a single function definition for the in-place quick-sort algorithm.~ external Solution<#70371#><#70371#> <#58888#>Exercise 43.1.5<#58888#> Develop the function <#70372#><#58890#>vector-reverse!<#58890#><#70372#>. It inverts the contents of a vector; its result is the modified vector. <#58891#>Hint:<#58891#> \ Swap items from both ends until there are no more items to swap.~ external Solution<#70373#><#70373#> <#58897#>Exercise 43.1.6<#58897#> Economists, meteorologists, and many others consistently measure various things and obtain time series. All of them need to understand the idea of ``n-item averages'' or ``smoothing''. Suppose we have weekly prices for some basket of groceries:

#tabular58900#

Computing the corresponding three-item average time series proceeds as follows:

#picture58905#

There are no averages for the end points, which means a series with k items turns into k-2 averages. Develop the function <#70390#><#58928#>list-3-average<#58928#><#70390#>, which computes the 3-item sliding averages of a list of numbers. That is, we represent a series of grocesry prices with lists and <#70391#><#58929#>list-3-averages<#58929#><#70391#> consumes a list such as

<#58934#>(list<#58934#> <#58935#>1.10<#58935#> <#58936#>1.10<#58936#> <#58937#>1.12<#58937#> <#58938#>1.08<#58938#> <#58939#>1.09<#58939#> <#58940#>1.11)<#58940#>
and produces
<#58948#>(list<#58948#> <#58949#>1.10<#58949#> <#58950#>329/300<#58950#> <#58951#>328/300)<#58951#>
in return. Develop the function <#70392#><#58955#>vector<#58955#>-<#58956#>3-averages<#58956#><#70392#>, which computes the 3-item sliding averages of a vector of numbers. Since vectors are mutable, this gives us the alternative of producing a new vector or of mutating the existing one. Develop both versions of the function: one that produces a new vector and another one that mutates the vector it is handed. Compare all three versions and the complexity of designing them.~ external Solution<#70393#><#70393#> <#58962#>Exercise 43.1.7<#58962#> All the examples in this section deal with vector fragments, that is, intervals of natural numbers. Processing an interval requires a starting point for an interval, an end point, and, as the definitions of <#70394#><#58964#>find-new-right<#58964#><#70394#> and <#70395#><#58965#>find-new-left<#58965#><#70395#> show, a direction of traversal. In addition, processing means applying some function to each point in the interval. Here is a function for processing intervals:
<#72099#>;; <#70396#><#58970#>for-interval<#58970#> <#58971#>:<#58971#> <#58972#>N<#58972#> <#58973#>(<#58973#><#58974#>N<#58974#> <#58975#><#58975#><#58976#>-;SPMgt;<#58976#><#58977#><#58977#> <#58978#>N<#58978#><#58979#>)<#58979#> <#58980#>(<#58980#><#58981#>N<#58981#> <#58982#><#58982#><#58983#>-;SPMgt;<#58983#><#58984#><#58984#> <#58985#>N<#58985#><#58986#>)<#58986#> <#58987#>(<#58987#><#58988#>N<#58988#> <#58989#><#58989#><#58990#>-;SPMgt;<#58990#><#58991#><#58991#> <#58992#>X)<#58992#> <#58993#><#58993#><#58994#>-;SPMgt;<#58994#><#58995#><#58995#> <#58996#>X<#58996#><#70396#><#72099#>
<#72100#>;; to evaluate <#70397#><#58997#>(action<#58997#> <#58998#>i<#58998#> <#58999#>(vector-ref<#58999#> <#59000#>V<#59000#> <#59001#>i))<#59001#><#70397#> for <#70398#><#59002#>i<#59002#><#70398#>, <#70399#><#59003#>(step<#59003#> <#59004#>i)<#59004#><#70399#>, ...<#72100#> 
<#72101#>;; until <#70400#><#59005#>(end?<#59005#> <#59006#>i)<#59006#><#70400#> holds (inclusive)<#72101#> 
<#72102#>;; generative recursion: <#70401#><#59007#>step<#59007#><#70401#> generates new value, <#70402#><#59008#>end?<#59008#><#70402#> detects end<#72102#> 
<#59009#>;; termination is not guaranteed <#59009#> 
<#59010#>(d<#59010#><#59011#>efine<#59011#> <#59012#>(for-interval<#59012#> <#59013#>i<#59013#> <#59014#>end?<#59014#> <#59015#>step<#59015#> <#59016#>action)<#59016#> 
  <#59017#>(b<#59017#><#59018#>egin<#59018#> 
    <#59019#>(action<#59019#> <#59020#>i)<#59020#> 
    <#59021#>(c<#59021#><#59022#>ond<#59022#> 
      <#59023#>[<#59023#><#59024#>(end?<#59024#> <#59025#>i)<#59025#> <#59026#>(action<#59026#> <#59027#>i)]<#59027#> 
      <#59028#>[<#59028#><#59029#>else<#59029#> <#59030#>(for-interval<#59030#> <#59031#>(step<#59031#> <#59032#>i)<#59032#> <#59033#>end?<#59033#> <#59034#>step<#59034#> <#59035#>action)]<#59035#><#59036#>)))<#59036#> 
It consumes a starting index, called <#70403#><#59040#>i<#59040#><#70403#>, a function for determining whether the end of the interval has been reached, a function that generates the next index, and a function that is applied to each point in between. Assuming <#70404#><#59041#>(end?<#59041#>\ <#59042#>(step<#59042#>\ <#59043#>(step<#59043#>\ <#59044#>...<#59044#>\ <#59045#>(step<#59045#>\ <#59046#>i)<#59046#>\ <#59047#>...)))<#59047#><#70404#> holds, <#70405#><#59048#>for-interval<#59048#><#70405#> satisfies the following equation:
  <#59053#>(for-interval<#59053#> <#59054#>i<#59054#> <#59055#>end?<#59055#> <#59056#>step<#59056#> <#59057#>action)<#59057#>
<#59058#>=<#59058#> <#59059#>(begin<#59059#> <#59060#>(action<#59060#> <#59061#>i)<#59061#> 
         <#59062#>(action<#59062#> <#59063#>(step<#59063#> <#59064#>i))<#59064#> 
         <#59065#>...<#59065#> 
         <#59066#>(action<#59066#> <#59067#>(step<#59067#> <#59068#>(step<#59068#> <#59069#>...<#59069#> <#59070#>(step<#59070#> <#59071#>i)<#59071#> <#59072#>...))))<#59072#> 
Compare the function definition and the equation with those for <#70406#><#59076#>map<#59076#><#70406#>. With <#70407#><#59077#>for-interval<#59077#><#70407#> we can develop (some) functions on vectors without the traditional detour through an auxiliary function. Instead, we use <#70408#><#59078#>for-interval<#59078#><#70408#> the way we used <#70409#><#59079#>map<#59079#><#70409#> for processing each item on a list. Here is a function that adds <#70410#><#59080#>1<#59080#><#70410#> to each vector field:
<#72103#>;; <#70411#><#59085#>increment-vec-rl<#59085#> <#59086#>:<#59086#> <#59087#>(vector<#59087#> <#59088#>number)<#59088#> <#59089#><#59089#><#59090#>-;SPMgt;<#59090#><#59091#><#59091#> <#59092#>void<#59092#><#70411#><#72103#>
<#72104#>;; effect: to increment each item in V by <#70412#><#59093#>1<#59093#><#70412#><#72104#> 
<#59094#>(d<#59094#><#59095#>efine<#59095#> <#59096#>(increment-vec-rl<#59096#> <#59097#>V)<#59097#> 
  <#59098#>(for-interval<#59098#> <#59099#>(sub1<#59099#> <#59100#>(vector-length<#59100#> <#59101#>V))<#59101#> <#59102#>zero?<#59102#> <#59103#>sub1<#59103#> 
                <#59104#>(l<#59104#><#59105#>ambda<#59105#> <#59106#>(i)<#59106#> 
                  <#59107#>(vector-set!<#59107#> <#59108#>V<#59108#> <#59109#>i<#59109#> <#59110#>(+<#59110#> <#59111#>(vector-ref<#59111#> <#59112#>V<#59112#> <#59113#>i)<#59113#> <#59114#>1)))))<#59114#> 
It processes the interval [<#70413#><#59118#>0<#59118#><#70413#>,<#70414#><#59119#>(sub1<#59119#>\ <#59120#>(vector-length<#59120#>\ <#59121#>V))<#59121#><#70414#>], where the left boundary is determined by <#70415#><#59122#>zero?<#59122#><#70415#>, the termination test. The starting point, however, is <#70416#><#59123#>(sub1<#59123#>\ <#59124#>(vector-length<#59124#>\ <#59125#>V))<#59125#><#70416#>, which is the rightmost legal vector index. The third argument to <#70417#><#59126#>for-interval<#59126#><#70417#>, <#70418#><#59127#>sub1<#59127#><#70418#>, determines the traversal direction, which is from right to left, until the index is <#70419#><#59128#>0<#59128#><#70419#>. Finally, the action is to mutate the contents of the <#70420#><#59129#>i<#59129#><#70420#>-th field by adding <#70421#><#59130#>1<#59130#><#70421#>. Here is a function with the same visible effect on vectors but a different processing order:
<#72105#>;; <#70422#><#59135#>increment-vec-lr<#59135#> <#59136#>:<#59136#> <#59137#>(vector<#59137#> <#59138#>number)<#59138#> <#59139#><#59139#><#59140#>-;SPMgt;<#59140#><#59141#><#59141#> <#59142#>void<#59142#><#70422#><#72105#>
<#72106#>;; effect: to increment each item in V by <#70423#><#59143#>1<#59143#><#70423#><#72106#> 
<#59144#>(d<#59144#><#59145#>efine<#59145#> <#59146#>(increment-vec-lr<#59146#> <#59147#>V)<#59147#> 
  <#59148#>(for-interval<#59148#> <#59149#>0<#59149#> <#59150#>(lambda<#59150#> <#59151#>(i)<#59151#> <#59152#>(=<#59152#> <#59153#>(sub1<#59153#> <#59154#>(vector-length<#59154#> <#59155#>V))<#59155#> <#59156#>i))<#59156#> <#59157#>add1<#59157#> 
                <#59158#>(l<#59158#><#59159#>ambda<#59159#> <#59160#>(i)<#59160#> 
                  <#59161#>(vector-set!<#59161#> <#59162#>V<#59162#> <#59163#>i<#59163#> <#59164#>(+<#59164#> <#59165#>(vector-ref<#59165#> <#59166#>V<#59166#> <#59167#>i)<#59167#> <#59168#>1)))))<#59168#> 
Its starting point is <#70424#><#59172#>0<#59172#><#70424#> and the end point is the rightmost legal index of <#70425#><#59173#>V<#59173#><#70425#>. The <#70426#><#59174#>add1<#59174#><#70426#> function determines that the vector is processed from left to right. Develop the following functions, using <#70427#><#59175#>for-interval<#59175#><#70427#>:
  1. <#70428#><#59177#>rotate-left<#59177#><#70428#>, which moves all items in vector into the adjacent field to the left, except for the first item, which moves to the last field;
  2. <#70429#><#59178#>insert-i-j<#59178#><#70429#>, which moves all items between two indices <#70430#><#59179#>i<#59179#><#70430#> and <#70431#><#59180#>j<#59180#><#70431#> to the right, except for the rightmost one, which gets inserted into the <#70432#><#59181#>i<#59181#><#70432#>-th field (cmp. figure~#figsortinplace#59182>);
  3. <#70433#><#59183#>vector-reverse!<#59183#><#70433#>, which swaps the left half of a vector with its right half;
  4. <#70434#><#59184#>find-new-right<#59184#><#70434#>, that is, an alternative to the definition in figure~#figpartip#59185>;
  5. <#70435#><#59186#>vector-sum!<#59186#><#70435#>, which computes the sum of the numbers in a vector using <#70436#><#59187#>set!<#59187#><#70436#> (<#59188#>Hint:<#59188#> \ see section~#secrepeatstate#59189>).
The last two tasks show that <#70437#><#59191#>for-interval<#59191#><#70437#> is useful for computations that have no visible effects. Of course, exercise~#secvector1#59192> shows that there is no need for a clumsy formulation such as <#70438#><#59193#>vector-sum!<#59193#><#70438#>. Which of these functions can be defined in terms of <#70439#><#59194#>vec-for-all<#59194#><#70439#> from exercise~#exabsvec#59195>?

<#59196#>Looping Constructs<#59196#>:\ Many programming languages (must) provide functions like <#70440#><#59197#>for-interval<#59197#><#70440#> as built-in constructs, and force programmers to use them for processing vectors. As a result, many more programs than necessary use <#70441#><#59198#>set!<#59198#><#70441#> and require complex temporal reasoning.~ external Solution<#70442#><#70442#>