<#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#>
<#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#>.
<#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#>
<#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:
<#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.
<#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.~ Solution<#70210#><#70210#> <#58165#>Exercise 43.1.3<#58165#>
<#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:
<#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.
<#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>
<#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:
<#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#>
Computing the corresponding three-item average time series proceeds as
follows:
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
<#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.~ Solution<#70442#><#70442#>
<#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.~ Solution<#70393#><#70393#>
<#58962#>Exercise 43.1.7<#58962#>
<#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#>:
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>