<#71547#>;; <#67059#><#38291#>neighbors<#38291#> <#38292#>:<#38292#> <#38293#>node<#38293#> <#38294#>graph<#38294#> <#38295#><#38295#><#38296#>-;SPMgt;<#38296#><#38297#><#38297#> <#38298#>(listof<#38298#> <#38299#>node)<#38299#><#67059#><#71547#> <#71548#>;; to lookup the <#67060#><#38300#>node<#38300#><#67060#> in <#67061#><#38301#>graph<#38301#><#67061#><#71548#> <#38302#>(d<#38302#><#38303#>efine<#38303#> <#38304#>(neighbors<#38304#> <#38305#>node<#38305#> <#38306#>graph)<#38306#> <#38307#>(c<#38307#><#38308#>ond<#38308#> <#38309#>[<#38309#><#38310#>(empty?<#38310#> <#38311#>graph)<#38311#> <#38312#>(error<#38312#> <#38313#>'<#38313#><#38314#>neighbors<#38314#> <#38315#>``can'<#38315#><#38316#>t<#38316#> <#38317#>happen'')]<#38317#> <#38318#>[<#38318#><#38319#>else<#38319#> <#38320#>(c<#38320#><#38321#>ond<#38321#> <#38322#>[<#38322#><#38323#>(symbol=?<#38323#> <#38324#>(first<#38324#> <#38325#>(first<#38325#> <#38326#>graph))<#38326#> <#38327#>node)<#38327#> <#38328#>(second<#38328#> <#38329#>(first<#38329#> <#38330#>graph))]<#38330#> <#38331#>[<#38331#><#38332#>else<#38332#> <#38333#>(neighbors<#38333#> <#38334#>node<#38334#> <#38335#>(rest<#38335#> <#38336#>graph))]<#38336#><#38337#>)]<#38337#><#38338#>))<#38338#>The function is similar to <#67062#><#38342#>contains-doll?<#38342#><#67062#> and has roughly the same behavior. More concretely, <#67063#><#38343#>neighbors<#38343#><#67063#> is O(N) when we assume that <#67064#><#38344#>graph<#38344#><#67064#> is a list of <#38345#>N<#38345#> nodes. Considering that <#67065#><#38346#>neighbors<#38346#><#67065#> is used at every stage of the evaluation of <#67066#><#38347#>find-route<#38347#><#67066#>, <#67067#><#38348#>neighbors<#38348#><#67067#> is possibly a bottleneck. As a matter of fact, if the route we are looking for involves <#67068#><#38349#>N<#38349#><#67068#> nodes (the maximum), <#67069#><#38350#>neighbors<#38350#><#67069#> is applied <#38351#>N<#38351#> times, so the algorithm requires
a class of compound values size with constant lookup time,Because the problem is so common, Scheme and most other languages offer at least one built-in solution. Here we study the class of <#67071#><#38355#>vector<#38355#><#67071#>s. A vector is a well-defined mathematical class of data with specific basic operations. For our purposes, it suffices to know how to construct them, how to extract values, and how to recognize them:
based on ``keys.''
<#38371#>(build-vector<#38371#> <#38372#>N<#38372#> <#38373#>f)<#38373#> <#38374#>=<#38374#> <#38375#>(vector<#38375#> <#38376#>(f<#38376#> <#38377#>0)<#38377#> <#38378#>...<#38378#> <#38379#>(f<#38379#> <#38380#>(-<#38380#> <#38381#>N<#38381#> <#38382#>1)))<#38382#>That is, <#67079#><#38386#>build-vector<#38386#><#67079#> consumes a natural number <#67080#><#38387#>N<#38387#><#67080#> and a function <#67081#><#38388#>f<#38388#><#67081#> on natural numbers. It then builds a vector of <#67082#><#38389#>N<#38389#><#67082#> items by applying <#67083#><#38390#>f<#38390#><#67083#> to <#67084#><#38391#>0<#38391#><#67084#>, ..., <#67085#><#38392#>N-1<#38392#><#67085#>.
<#38398#>(vector-ref<#38398#> <#38399#>(vector<#38399#> <#38400#>V-0<#38400#> <#38401#>...<#38401#> <#38402#>V-n)<#38402#> <#38403#>i)<#38403#> <#38404#>=<#38404#> <#38405#>V-i<#38405#>where <#67087#><#38409#>i<#38409#><#67087#> is between <#67088#><#38410#>0<#38410#><#67088#> and <#67089#><#38411#>n<#38411#><#67089#> (inclusive). If <#67090#><#38412#>vector-ref<#38412#><#67090#> is applied to a vector and a natural number that is smaller than <#67091#><#38413#>0<#38413#><#67091#> or larger than <#67092#><#38414#>n<#38414#><#67092#>, <#67093#><#38415#>vector-ref<#38415#><#67093#> signals an error.
<#38421#>(vector-length<#38421#> <#38422#>(vector<#38422#> <#38423#>V-0<#38423#> <#38424#>...<#38424#> <#38425#>V-n))<#38425#> <#38426#>=<#38426#> <#38427#>(+<#38427#> <#38428#>n<#38428#> <#38429#>1)<#38429#>
<#38440#>(vector?<#38440#> <#38441#>(vector<#38441#> <#38442#>V-0<#38442#> <#38443#>...<#38443#> <#38444#>V-n))<#38444#> <#38445#>=<#38445#> <#38446#>true<#38446#> <#38447#>(vector?<#38447#> <#38448#>U)<#38448#> <#38449#>=<#38449#> <#38450#>false<#38450#>if <#67098#><#38454#>U<#38454#><#67098#> is a value that isn't created with <#67099#><#38455#>vector<#38455#><#67099#>.
Using this translation, we can also produce a <#38466#>vector<#38466#>-based representation of
the graph in figure~#figgraph#38467>
Using <#67310#><#39525#>build-board<#39525#><#67310#>, develop the function <#67311#><#39526#>transpose<#39526#><#67311#>, which
creates a mirror image of the matrix along its diagonal from the upper-left
corner to the lower-right one. For example, the given matrix turns into
More generally, the item at (i,j) becomes the item at (j,i).~ Solution<#67312#><#67312#>
<#38472#>(d<#38472#><#38473#>efine<#38473#> <#38474#>Graph-as-list<#38474#>
<#38475#>'<#38475#><#38476#>(<#38476#><#38477#>(A<#38477#> <#38478#>(B<#38478#> <#38479#>E))<#38479#>
<#38480#>(B<#38480#> <#38481#>(E<#38481#> <#38482#>F))<#38482#>
<#38483#>(C<#38483#> <#38484#>(D))<#38484#>
<#38485#>(D<#38485#> <#38486#>())<#38486#>
<#38487#>(E<#38487#> <#38488#>(C<#38488#> <#38489#>F))<#38489#>
<#38490#>(F<#38490#> <#38491#>(D<#38491#> <#38492#>G))<#38492#>
<#38493#>(G<#38493#> <#38494#>())))<#38494#>
<#38500#>(d<#38500#><#38501#>efine<#38501#> <#38502#>Graph-as-vector<#38502#>
<#38503#>(vector<#38503#> <#38504#>(list<#38504#> <#38505#>1<#38505#> <#38506#>4)<#38506#>
<#38507#>(list<#38507#> <#38508#>4<#38508#> <#38509#>5)<#38509#>
<#38510#>(list<#38510#> <#38511#>3)<#38511#>
<#38512#>empty<#38512#>
<#38513#>(list<#38513#> <#38514#>2<#38514#> <#38515#>5)<#38515#>
<#38516#>(list<#38516#> <#38517#>3<#38517#> <#38518#>6)<#38518#>
<#38519#>empty))<#38519#>
The definition on the left is the original list-based representation; the
one on the right is a vector representation. The vector's <#67100#><#38523#>i<#38523#><#67100#>-th
field contains the list of neighbors of the <#67101#><#38524#>i<#38524#><#67101#>-th node.
The data definitions for <#67102#><#38525#>node<#38525#><#67102#> and <#67103#><#38526#>graph<#38526#><#67103#> change in the
expected manner. Let's assume that N is the number of nodes in the given
graph:
A <#67104#><#38528#>node<#38528#><#67104#> is an natural number between 0 and N-1.
A <#67105#><#38531#>graph<#38531#><#67105#> is a vector of <#67106#><#38532#>node<#38532#><#67106#>s: <#67107#><#38533#>(vectorof<#38533#><#38534#> <#38534#><#38535#>(listof<#38535#>\ <#38536#>node))<#38536#><#67107#>.
The notation <#67108#><#38538#>(vectorof<#38538#>\ <#38539#>X)<#38539#><#67108#> is similar to <#67109#><#38540#>(listof<#38540#><#38541#> <#38541#><#38542#>X)<#38542#><#67109#>. It denotes a vector that contains items from some undetermined class
of data <#67110#><#38543#>X<#38543#><#67110#>.
Now we can re-define <#67111#><#38544#>neighbors<#38544#><#67111#>:
<#71549#>;; <#67112#><#38549#>neighbors<#38549#> <#38550#>:<#38550#> <#38551#>node<#38551#> <#38552#>graph<#38552#> <#38553#><#38553#><#38554#>-;SPMgt;<#38554#><#38555#><#38555#> <#38556#>(listof<#38556#> <#38557#>node)<#38557#><#67112#><#71549#>
<#71550#>;; to lookup the <#67113#><#38558#>node<#38558#><#67113#> in <#67114#><#38559#>graph<#38559#><#67114#><#71550#>
<#38560#>(d<#38560#><#38561#>efine<#38561#> <#38562#>(neighbors<#38562#> <#38563#>node<#38563#> <#38564#>graph)<#38564#>
<#38565#>(vector-ref<#38565#> <#38566#>graph<#38566#> <#38567#>node))<#38567#>
As a result, looking up the neighbors of a node just became a constant-time
operation, and we can truly ignore it when we study the abstract running
time of <#67115#><#38571#>find-route<#38571#><#67115#>.
<#38574#>Exercise 29.3.1<#38574#>
Before we can truly program with vectors, we must understand the data
definition. The situation is comparable to that when we first encountered
lists. We know that <#67125#><#38609#>vector<#38609#><#67125#>, like <#67126#><#38610#>cons<#38610#><#67126#>, is provided by
Scheme, but we don't have a data definition that directs our program
development efforts.
So, let us take a look at vectors. Roughly speaking, <#67127#><#38611#>vector<#38611#><#67127#> is
like <#67128#><#38612#>cons<#38612#><#67128#>. The <#67129#><#38613#>cons<#38613#><#67129#> primitive constructs lists, the
<#67130#><#38614#>vector<#38614#><#67130#> primitive creates vectors. Since programming with lists
usually means programming with the selectors <#67131#><#38615#>first<#38615#><#67131#> and
<#67132#><#38616#>rest<#38616#><#67132#>, programming with vectors must mean programming with
<#67133#><#38617#>vector-ref<#38617#><#67133#>. Unlike <#67134#><#38618#>first<#38618#><#67134#> and <#67135#><#38619#>rest<#38619#><#67135#>, however,
<#67136#><#38620#>vector-ref<#38620#><#67136#> requires manipulating the vector and an index into a
vector. This suggests that programming with vectors really means thinking
about indices, which are natural numbers.
Let's look at some simple examples to confirm this abstract judgement. Here
is the first one:
<#71551#>;; <#67137#><#38625#>vector-sum-for-3<#38625#> <#38626#>:<#38626#> <#38627#>(vector<#38627#> <#38628#>number<#38628#> <#38629#>number<#38629#> <#38630#>number)<#38630#> <#38631#><#38631#><#38632#>-;SPMgt;<#38632#><#38633#><#38633#> <#38634#>number<#38634#><#67137#><#71551#>
<#38635#>(d<#38635#><#38636#>efine<#38636#> <#38637#>(vector-sum-for-3<#38637#> <#38638#>v)<#38638#>
<#38639#>(+<#38639#> <#38640#>(vector-ref<#38640#> <#38641#>v<#38641#> <#38642#>0)<#38642#>
<#38643#>(vector-ref<#38643#> <#38644#>v<#38644#> <#38645#>1)<#38645#>
<#38646#>(vector-ref<#38646#> <#38647#>v<#38647#> <#38648#>2)))<#38648#>
The function <#67138#><#38652#>vector-sum-for-3<#38652#><#67138#> consumes vectors of three numbers
and produces their sum. It uses <#67139#><#38653#>vector-ref<#38653#><#67139#> to extract the three
numbers and adds them up. What varies in the three selector expressions is
the index; the vector remains the same.
Consider a second, more interesting example: <#67140#><#38654#>vector-sum<#38654#><#67140#>, a
generalization of <#67141#><#38655#>vector-sum-for-3<#38655#><#67141#>. It consumes an arbitrarily
large vector of numbers and produces the sum of the numbers:
<#71552#>;; <#67142#><#38660#>vector-sum<#38660#> <#38661#>:<#38661#> <#38662#>(vectorof<#38662#> <#38663#>number)<#38663#> <#38664#><#38664#><#38665#>-;SPMgt;<#38665#><#38666#><#38666#> <#38667#>number<#38667#><#67142#><#71552#>
<#71553#>;; to sum up the numbers in <#67143#><#38668#>v<#38668#><#67143#><#71553#>
<#38669#>(define<#38669#> <#38670#>(vector-sum<#38670#> <#38671#>v)<#38671#> <#38672#>...)<#38672#>
Here are some examples:
<#38680#>(vector-sum<#38680#> <#38681#>(vector<#38681#> <#38682#>-1<#38682#> <#38683#>3/4<#38683#> <#38684#>1/4))<#38684#>
<#38685#>=<#38685#> <#38686#>0<#38686#>
<#38687#>(vector-sum<#38687#> <#38688#>(vector<#38688#> <#38689#>.1<#38689#> <#38690#>.1<#38690#> <#38691#>.1<#38691#> <#38692#>.1<#38692#> <#38693#>.1<#38693#> <#38694#>.1<#38694#> <#38695#>.1<#38695#> <#38696#>.1<#38696#> <#38697#>.1<#38697#> <#38698#>.1))<#38698#>
<#38699#>=<#38699#> <#38700#>1<#38700#>
<#38701#>(vector-sum<#38701#> <#38702#>(vector))<#38702#>
<#38703#>=<#38703#> <#38704#>0<#38704#>
The last example suggests that we want a reasonable answer even if the
vector is empty. As with <#67144#><#38708#>empty<#38708#><#67144#>, we use <#67145#><#38709#>0<#38709#><#67145#> as the answer in
this case.
The problem is that the one natural number associated with <#67146#><#38710#>v<#38710#><#67146#>, its
length, is not an argument of <#67147#><#38711#>vector-sum<#38711#><#67147#>. The length of <#67148#><#38712#>v<#38712#><#67148#>
is of course just an indication of how many items in <#67149#><#38713#>v<#38713#><#67149#> are to be
processed, which in turn refers to legal indices of <#67150#><#38714#>v<#38714#><#67150#>. This
reasoning forces us to develop an auxiliary function that consumes the
vector and a natural number:
<#71554#>;; <#67151#><#38719#>vector-sum-aux<#38719#> <#38720#>:<#38720#> <#38721#>(vectorof<#38721#> <#38722#>number)<#38722#> <#38723#>N<#38723#> <#38724#><#38724#><#38725#>-;SPMgt;<#38725#><#38726#><#38726#> <#38727#>number<#38727#><#67151#><#71554#>
<#71555#>;; to sum up the numbers in <#67152#><#38728#>v<#38728#><#67152#> relative to <#67153#><#38729#>i<#38729#><#67153#> <#71555#>
<#38730#>(define<#38730#> <#38731#>(vector-sum-aux<#38731#> <#38732#>v<#38732#> <#38733#>i)<#38733#> <#38734#>...)<#38734#>
The natural choice for the initial value of <#67154#><#38738#>i<#38738#><#67154#> is the length of
<#67155#><#38739#>v<#38739#><#67155#>, which suggests the following completion of <#67156#><#38740#>vector-sum<#38740#><#67156#>:
<#38745#>(d<#38745#><#38746#>efine<#38746#> <#38747#>(vector-sum<#38747#> <#38748#>v)<#38748#>
<#38749#>(vector-sum-aux<#38749#> <#38750#>v<#38750#> <#38751#>(vector-length<#38751#> <#38752#>v)))<#38752#>
Based on this definition, we can also adapt the examples for
<#67157#><#38756#>vector-sum<#38756#><#67157#> to <#67158#><#38757#>vector-sum-aux<#38757#><#67158#>:
<#38762#>(vector-sum-aux<#38762#> <#38763#>(vector<#38763#> <#38764#>-1<#38764#> <#38765#>3/4<#38765#> <#38766#>1/4)<#38766#> <#38767#>3)<#38767#>
<#38768#>=<#38768#> <#38769#>0<#38769#>
<#38770#>(vector-sum-aux<#38770#> <#38771#>(vector<#38771#> <#38772#>.1<#38772#> <#38773#>.1<#38773#> <#38774#>.1<#38774#> <#38775#>.1<#38775#> <#38776#>.1<#38776#> <#38777#>.1<#38777#> <#38778#>.1<#38778#> <#38779#>.1<#38779#> <#38780#>.1<#38780#> <#38781#>.1)<#38781#> <#38782#>10)<#38782#>
<#38783#>=<#38783#> <#38784#>1<#38784#>
<#38785#>(vector-sum-aux<#38785#> <#38786#>(vector)<#38786#> <#38787#>0)<#38787#>
<#38788#>=<#38788#> <#38789#>0<#38789#>
Unfortunately, this doesn't clarify the role of the second argument. To do
that, we need to proceed to the next stage of the design process: the
template development.
When we develop templates for functions of two arguments, we must first
decide which of the arguments must be processed, that is, which of the two
will vary in the course of a computation. The <#67159#><#38793#>vector-sum-for-3<#38793#><#67159#>
example suggests that it is the second argument in this case. Because this
argument belongs to the class of natural numbers, we follow the design recipe
for those:
<#38798#>(d<#38798#><#38799#>efine<#38799#> <#38800#>(vector-sum-aux<#38800#> <#38801#>v<#38801#> <#38802#>i)<#38802#>
<#38803#>(c<#38803#><#38804#>ond<#38804#>
<#38805#>[<#38805#><#38806#>(zero?<#38806#> <#38807#>i)<#38807#> <#38808#>...]<#38808#>
<#38809#>[<#38809#><#38810#>else<#38810#> <#38811#>...<#38811#> <#38812#>(vector-sum-aux<#38812#> <#38813#>v<#38813#> <#38814#>(sub1<#38814#> <#38815#>i))<#38815#> <#38816#>...]<#38816#><#38817#>))<#38817#>
Although we considered <#67160#><#38821#>i<#38821#><#67160#> to be the length of the vector initially,
the template suggests that we should consider it the number of items of
<#67161#><#38822#>v<#38822#><#67161#> that <#67162#><#38823#>vector-sum-aux<#38823#><#67162#> must consider and thus as an index
into <#67163#><#38824#>v<#38824#><#67163#>.
The elaboration of <#67164#><#38825#>i<#38825#><#67164#>'s use naturally leads to a better purpose
statement for <#67165#><#38826#>vector-sum-aux<#38826#><#67165#>:
<#71556#>;; <#67166#><#38831#>vector-sum-aux<#38831#> <#38832#>:<#38832#> <#38833#>(vectorof<#38833#> <#38834#>number)<#38834#> <#38835#>N<#38835#> <#38836#><#38836#><#38837#>-;SPMgt;<#38837#><#38838#><#38838#> <#38839#>number<#38839#><#67166#><#71556#>
<#71557#>;; to sum up the numbers in <#67167#><#38840#>v<#38840#><#67167#> with index in [<#67168#><#38841#>0<#38841#><#67168#>, <#67169#><#38842#>i<#38842#><#67169#>)<#71557#>
<#38843#>(d<#38843#><#38844#>efine<#38844#> <#38845#>(vector-sum-aux<#38845#> <#38846#>v<#38846#> <#38847#>i)<#38847#>
<#38848#>(c<#38848#><#38849#>ond<#38849#>
<#38850#>[<#38850#><#38851#>(zero?<#38851#> <#38852#>i)<#38852#> <#38853#>...]<#38853#>
<#38854#>[<#38854#><#38855#>else<#38855#> <#38856#>...<#38856#> <#38857#>(vector-sum-aux<#38857#> <#38858#>v<#38858#> <#38859#>(sub1<#38859#> <#38860#>i))<#38860#> <#38861#>...]<#38861#><#38862#>))<#38862#>
Excluding <#67170#><#38866#>i<#38866#><#67170#> is natural because it is initially
<#67171#><#38867#>(vector-length<#38867#>\ <#38868#>v)<#38868#><#67171#> and thus not an index.
<#71558#>;; <#67172#><#38873#>vector-sum<#38873#> <#38874#>:<#38874#> <#38875#>(vectorof<#38875#> <#38876#>number)<#38876#> <#38877#><#38877#><#38878#>-;SPMgt;<#38878#><#38879#><#38879#> <#38880#>number<#38880#><#67172#><#71558#>
<#71559#>;; to compute the sum of the numbers in <#67173#><#38881#>v<#38881#><#67173#><#71559#>
<#38882#>(d<#38882#><#38883#>efine<#38883#> <#38884#>(vector-sum<#38884#> <#38885#>v)<#38885#>
<#38886#>(vector-sum-aux<#38886#> <#38887#>(vector-length<#38887#> <#38888#>v)<#38888#> <#38889#>v))<#38889#>
<#71560#>;; <#67174#><#38897#>vector-sum-aux<#38897#> <#38898#>:<#38898#> <#38899#>(vectorof<#38899#> <#38900#>number)<#38900#> <#38901#>N<#38901#> <#38902#><#38902#><#38903#>-;SPMgt;<#38903#><#38904#><#38904#> <#38905#>number<#38905#><#67174#><#71560#>
<#71561#>;; to sum the numbers in <#67175#><#38906#>v<#38906#><#67175#> with index in [<#67176#><#38907#>0<#38907#><#67176#>, <#67177#><#38908#>i<#38908#><#67177#>)<#71561#>
<#38909#>(d<#38909#><#38910#>efine<#38910#> <#38911#>(vector-sum-aux<#38911#> <#38912#>v<#38912#> <#38913#>i)<#38913#>
<#38914#>(c<#38914#><#38915#>ond<#38915#>
<#38916#>[<#38916#><#38917#>(zero?<#38917#> <#38918#>i)<#38918#> <#38919#>0]<#38919#>
<#38920#>[<#38920#><#38921#>else<#38921#> <#38922#>(+<#38922#> <#38923#>(vector-ref<#38923#> <#38924#>v<#38924#> <#38925#>(sub1<#38925#> <#38926#>i))<#38926#>
<#38927#>(vector-sum-aux<#38927#> <#38928#>v<#38928#> <#38929#>(sub1<#38929#> <#38930#>i)))]<#38930#><#38931#>))<#38931#>
<#38935#>Figure: Summing up the numbers in a vector (version 1)<#38935#> <#71562#>;; <#67178#><#38941#>lr-vector-sum<#38941#> <#38942#>:<#38942#> <#38943#>(vectorof<#38943#> <#38944#>number)<#38944#> <#38945#><#38945#><#38946#>-;SPMgt;<#38946#><#38947#><#38947#> <#38948#>number<#38948#><#67178#><#71562#>
<#71563#>;; to sum up the numbers in <#67179#><#38949#>v<#38949#><#67179#><#71563#>
<#38950#>(d<#38950#><#38951#>efine<#38951#> <#38952#>(lr-vector-sum<#38952#> <#38953#>v)<#38953#>
<#38954#>(vector-sum-aux<#38954#> <#38955#>v<#38955#> <#38956#>0))<#38956#>
<#71564#>;; <#67180#><#38957#>vector-sum<#38957#> <#38958#>:<#38958#> <#38959#>(vectorof<#38959#> <#38960#>number)<#38960#> <#38961#><#38961#><#38962#>-;SPMgt;<#38962#><#38963#><#38963#> <#38964#>number<#38964#><#67180#><#71564#>
<#71565#>;; to sum up the numbers in <#67181#><#38965#>v<#38965#><#67181#> with index in [<#67182#><#38966#>i<#38966#><#67182#>, <#67183#><#38967#>(vector-length<#38967#> <#38968#>v)<#38968#><#67183#>)<#71565#>
<#38969#>(d<#38969#><#38970#>efine<#38970#> <#38971#>(vector-sum-aux<#38971#> <#38972#>v<#38972#> <#38973#>i)<#38973#>
<#38974#>(c<#38974#><#38975#>ond<#38975#>
<#38976#>[<#38976#><#38977#>(=<#38977#> <#38978#>i<#38978#> <#38979#>(vector-length<#38979#> <#38980#>v))<#38980#> <#38981#>0]<#38981#>
<#38982#>[<#38982#><#38983#>else<#38983#> <#38984#>(+<#38984#> <#38985#>(vector-ref<#38985#> <#38986#>v<#38986#> <#38987#>i)<#38987#> <#38988#>(vector-sum-aux<#38988#> <#38989#>v<#38989#> <#38990#>(add1<#38990#> <#38991#>i)))]<#38991#><#38992#>))<#38992#>
<#38996#>Figure: Summing up the numbers in a vector (version 2)<#38996#>
To transform the template into a complete function definition, we consider
each clause of the <#67184#><#38998#>cond<#38998#><#67184#>:
See figure~#figvectorsum#39038><#39025#>(+<#39025#> <#39026#>(vector-ref<#39026#> <#39027#>v<#39027#> <#39028#>(sub1<#39028#> <#39029#>i))<#39029#> <#39030#>(vector-sum-aux<#39030#> <#39031#>v<#39031#> <#39032#>(sub1<#39032#> <#39033#>i)))<#39033#>
<#39054#>(lr-vector-sum<#39054#> <#39055#>(vector<#39055#> <#39056#>0<#39056#> <#39057#>1<#39057#> <#39058#>2<#39058#> <#39059#>3))<#39059#>
shows that <#67204#><#39063#>vector-sum-aux<#39063#><#67204#> indeed extracts the items from
<#67205#><#39064#>v<#39064#><#67205#> from left to right.
The definition of <#67206#><#39065#>lr-vector-sum<#39065#><#67206#> shows why we need to study
alternative definitions of classes of natural numbers. Sometimes it is
necessary to count down to <#67207#><#39066#>0<#39066#><#67207#>. But at other times it is equally
useful, and natural, to count from <#67208#><#39067#>0<#39067#><#67208#> up to some other number.
The two functions also show how important it is to reason about
intervals. The auxiliary vector-processing functions process intervals of
the given vector. A good purpose statement specifies the exact interval
that the function works on. Indeed, once we understand the exact interval
specification, formulating the full function is relatively
straightforward. We will see the importance of this point when we return to
the study of vector-processing functions in the last section.
<#39070#>Exercise 29.3.4<#39070#>
<#71566#>;; <#67219#><#39107#>list-sum<#39107#> <#39108#>:<#39108#> <#39109#>(listof<#39109#> <#39110#>number)<#39110#> <#39111#><#39111#><#39112#>-;SPMgt;<#39112#><#39113#><#39113#> <#39114#>number<#39114#><#67219#> <#71566#>
<#71567#>;; to compute the sum of the numbers on <#67220#><#39115#>alon<#39115#><#67220#><#71567#>
<#39116#>(d<#39116#><#39117#>efine<#39117#> <#39118#>(list-sum<#39118#> <#39119#>alon)<#39119#>
<#39120#>(list-sum-aux<#39120#> <#39121#>alon<#39121#> <#39122#>(length<#39122#> <#39123#>alon)))<#39123#>
<#71568#>;; <#67221#><#39124#>list-sum-aux<#39124#> <#39125#>:<#39125#> <#39126#>N<#39126#> <#39127#>(listof<#39127#> <#39128#>number)<#39128#> <#39129#><#39129#><#39130#>-;SPMgt;<#39130#><#39131#><#39131#> <#39132#>number<#39132#><#67221#> <#71568#>
<#71569#>;; to compute the sum of the first <#67222#><#39133#>L<#39133#><#67222#> numbers on <#67223#><#39134#>alon<#39134#><#67223#><#71569#>
<#39135#>(d<#39135#><#39136#>efine<#39136#> <#39137#>(list-sum-aux<#39137#> <#39138#>L<#39138#> <#39139#>alon)<#39139#>
<#39140#>(c<#39140#><#39141#>ond<#39141#>
<#39142#>[<#39142#><#39143#>(zero?<#39143#> <#39144#>L)<#39144#> <#39145#>0]<#39145#>
<#39146#>[<#39146#><#39147#>else<#39147#> <#39148#>(+<#39148#> <#39149#>(list-ref<#39149#> <#39150#>alon<#39150#> <#39151#>(sub1<#39151#> <#39152#>L))<#39152#> <#39153#>(list-sum-aux<#39153#> <#39154#>(sub1<#39154#> <#39155#>L)<#39155#> <#39156#>alon))]<#39156#><#39157#>))<#39157#>
Instead of using the structural definition of the list, the developer of
this program used the size of the list---a natural number---as the guiding
element in the design process.
The resulting definition uses Scheme's <#67224#><#39161#>list-ref<#39161#><#67224#> function to access
each item on the list. Looking up an item in a list with <#67225#><#39162#>list-ref<#39162#><#67225#>
is an O(N) operation for lists of <#39163#>N<#39163#> items. Determine the abstract
running time of <#67226#><#39164#>sum<#39164#><#67226#> (from section~#seclistsmore#39165>
While accessing the items of a vector is one kind of programming problem,
constructing vectors is an entirely different problem. When we know the
number of items in a vector, we can construct it using
<#67256#><#39230#>vector<#39230#><#67256#>. When we we wish to write programs, however, that work on a
large class of vectors independent of their size, we need
<#67257#><#39231#>build-vector<#39231#><#67257#>.
Consider the following simple example. Suppose we represent the velocity of
an object with a vector. For example, <#67258#><#39232#>(vector<#39232#>\ <#39233#>1<#39233#>\ <#39234#>2)<#39234#><#67258#> represents the
veloicity of an object on a plane that moves <#67259#><#39235#>1<#39235#><#67259#> unit to the right
and <#67260#><#39236#>2<#39236#><#67260#> down in each time unit. For comparison, <#67261#><#39237#>(vector<#39237#>\ <#39238#>-1<#39238#>\ <#39239#>2<#39239#><#39240#> <#39240#><#39241#>1)<#39241#><#67261#> is the veloicity of an object in space; it moves
<#67262#><#39242#>-6<#39242#><#67262#> units in the x-direction in 6 time units,
<#67263#><#39243#>12<#39243#><#67263#> units in the y-direction in 6 time units, and
<#67264#><#39244#>6<#39244#><#67264#> units in the z-direction in 6 time units. We call <#67265#><#39245#>(vector<#39245#>\ <#39246#>-6<#39246#><#39247#> <#39247#><#39248#>12<#39248#>\ <#39249#>6)<#39249#><#67265#> the <#39250#>displacement<#39250#> of the object in 6 time units.
Let's develop a function that computes the displacement for an object with
some velocity <#67266#><#39251#>v<#39251#><#67266#> in <#67267#><#39252#>t<#39252#><#67267#> time units:
<#71570#>;; <#67268#><#39257#>displacement<#39257#> <#39258#>:<#39258#> <#39259#>(vectorof<#39259#> <#39260#>number)<#39260#> <#39261#>number<#39261#> <#39262#><#39262#><#39263#>-;SPMgt;<#39263#><#39264#><#39264#> <#39265#>(vectorof<#39265#> <#39266#>number)<#39266#><#67268#><#71570#>
<#71571#>;; to compute the displacement of <#67269#><#39267#>v<#39267#><#67269#> and <#67270#><#39268#>t<#39268#><#67270#><#71571#>
<#39269#>(define<#39269#> <#39270#>(displacement<#39270#> <#39271#>v<#39271#> <#39272#>t)<#39272#> <#39273#>...)<#39273#>
Computing the displacement is straightforward for some examples:
<#39281#>(displacement<#39281#> <#39282#>(vector<#39282#> <#39283#>1<#39283#> <#39284#>2)<#39284#> <#39285#>3)<#39285#>
<#39286#>=<#39286#> <#39287#>(vector<#39287#> <#39288#>3<#39288#> <#39289#>6)<#39289#>
<#39290#>(displacement<#39290#> <#39291#>(vector<#39291#> <#39292#>-1<#39292#> <#39293#>2<#39293#> <#39294#>1)<#39294#> <#39295#>6)<#39295#>
<#39296#>=<#39296#> <#39297#>(vector<#39297#> <#39298#>-6<#39298#> <#39299#>12<#39299#> <#39300#>6)<#39300#>
<#39301#>(displacement<#39301#> <#39302#>(vector<#39302#> <#39303#>-1<#39303#> <#39304#>-2)<#39304#> <#39305#>2)<#39305#>
<#39306#>=<#39306#> <#39307#>(vector<#39307#> <#39308#>-2<#39308#> <#39309#>-4)<#39309#>
We just multiply each component of the object with the number, which yields
a new vector.
The examples' meaning for our programming problem is that
<#67271#><#39313#>displacement<#39313#><#67271#> must construct a vector of the same how-many as
<#67272#><#39314#>v<#39314#><#67272#> and must use the items in <#67273#><#39315#>v<#39315#><#67273#> to compute those of the new
vectors. Here is how we build a vector of the same how-many as some given
vector <#67274#><#39316#>v<#39316#><#67274#>:
<#39321#>(build-vector<#39321#> <#39322#>(vector-length<#39322#> <#39323#>v)<#39323#> <#39324#>...)<#39324#>
Now we need to replace ...\ with a function that computes the
<#67275#><#39328#>0<#39328#><#67275#>-th, <#67276#><#39329#>1<#39329#><#67276#>-st, and so on items of the new vector:
<#71572#>;; <#67277#><#39334#>new-item<#39334#> <#39335#>:<#39335#> <#39336#>N<#39336#> <#39337#><#39337#><#39338#>-;SPMgt;<#39338#><#39339#><#39339#> <#39340#>number<#39340#><#67277#><#71572#>
<#71573#>;; to compute the contents of the new vector at the <#67278#><#39341#>i<#39341#><#67278#>-th position<#71573#>
<#39342#>(define<#39342#> <#39343#>(new-item<#39343#> <#39344#>index)<#39344#> <#39345#>...)<#39345#>
Following our discussion, we multiply <#67279#><#39349#>(vector-ref<#39349#>\ <#39350#>v<#39350#>\ <#39351#>i)<#39351#><#67279#> with
<#67280#><#39352#>t<#39352#><#67280#> and that's all.
Take a look at the complete definition:
<#71574#>;; <#67281#><#39357#>displacement<#39357#> <#39358#>:<#39358#> <#39359#>(vectorof<#39359#> <#39360#>number)<#39360#> <#39361#>number<#39361#> <#39362#><#39362#><#39363#>-;SPMgt;<#39363#><#39364#><#39364#> <#39365#>(vectorof<#39365#> <#39366#>number)<#39366#><#67281#><#71574#>
<#71575#>;; to compute the displacement of <#67282#><#39367#>v<#39367#><#67282#> and <#67283#><#39368#>t<#39368#><#67283#><#71575#>
<#39369#>(d<#39369#><#39370#>efine<#39370#> <#39371#>(displacement<#39371#> <#39372#>v<#39372#> <#39373#>t)<#39373#>
<#39374#>(l<#39374#><#39375#>ocal<#39375#> <#39376#>((define<#39376#> <#39377#>(new-item<#39377#> <#39378#>i)<#39378#> <#39379#>(*<#39379#> <#39380#>(vector-ref<#39380#> <#39381#>v<#39381#> <#39382#>i)<#39382#> <#39383#>t)))<#39383#>
<#39384#>(build-vector<#39384#> <#39385#>(vector-length<#39385#> <#39386#>v)<#39386#> <#39387#>new-item)))<#39387#>
The locally defined function is not recursive. We can thus replace it with
a plain <#67284#><#39391#>lambda<#39391#>-expression<#67284#>:
<#71576#>;; <#67285#><#39396#>displacement<#39396#> <#39397#>:<#39397#> <#39398#>(vectorof<#39398#> <#39399#>number)<#39399#> <#39400#>number<#39400#> <#39401#><#39401#><#39402#>-;SPMgt;<#39402#><#39403#><#39403#> <#39404#>(vectorof<#39404#> <#39405#>number)<#39405#><#67285#><#71576#>
<#71577#>;; to compute the displacement of <#67286#><#39406#>v<#39406#><#67286#> and <#67287#><#39407#>t<#39407#><#67287#><#71577#>
<#39408#>(d<#39408#><#39409#>efine<#39409#> <#39410#>(displacement<#39410#> <#39411#>v<#39411#> <#39412#>t)<#39412#>
<#39413#>(build-vector<#39413#> <#39414#>(vector-length<#39414#> <#39415#>v)<#39415#> <#39416#>(lambda<#39416#> <#39417#>(i)<#39417#> <#39418#>(*<#39418#> <#39419#>(vector-ref<#39419#> <#39420#>v<#39420#> <#39421#>i)<#39421#> <#39422#>t))))<#39422#>
Mathematicians call this function <#39426#>scalar product<#39426#>. They have also
studied many other operations on vectors, and in Scheme we can develop
those in a natural manner.
<#39429#>Exercise 29.3.11<#39429#>
<#71578#>;; <#67299#><#39464#>build-board<#39464#> <#39465#>:<#39465#> <#39466#>N<#39466#> <#39467#>(<#39467#><#39468#>N<#39468#> <#39469#>N<#39469#> <#39470#><#39470#><#39471#>-;SPMgt;<#39471#><#39472#><#39472#> <#39473#>boolean)<#39473#> <#39474#><#39474#><#39475#>-;SPMgt;<#39475#><#39476#><#39476#> <#39477#>board<#39477#><#67299#><#71578#>
<#71579#>;; to create a board of size <#67300#><#39478#>n<#39478#><#67300#> x <#67301#><#39479#>n<#39479#><#67301#>, <#71579#>
<#71580#>;; fill each position with indices <#67302#><#39480#>i<#39480#><#67302#> and <#67303#><#39481#>j<#39481#><#67303#> with <#67304#><#39482#>(f<#39482#> <#39483#>i<#39483#> <#39484#>j)<#39484#><#67304#><#71580#>
<#39485#>(define<#39485#> <#39486#>(build-board<#39486#> <#39487#>n<#39487#> <#39488#>f)<#39488#> <#39489#>...)<#39489#>
<#71581#>;; <#67305#><#39490#>board-ref<#39490#> <#39491#>:<#39491#> <#39492#>board<#39492#> <#39493#>N<#39493#> <#39494#>N<#39494#> <#39495#><#39495#><#39496#>-;SPMgt;<#39496#><#39497#><#39497#> <#39498#>boolean<#39498#><#67305#><#71581#>
<#71582#>;; to access a position with indices <#67306#><#39499#>i<#39499#><#67306#>, <#67307#><#39500#>j<#39500#><#67307#> on <#67308#><#39501#>a-board<#39501#><#67308#><#71582#>
<#39502#>(define<#39502#> <#39503#>(board-ref<#39503#> <#39504#>a-board<#39504#> <#39505#>i<#39505#> <#39506#>j)<#39506#> <#39507#>...)<#39507#>
Can we now run the program of section~#secqueens#39511>