1523 lines
No EOL
694 KiB
HTML
1523 lines
No EOL
694 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>V Generative Recursion</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="shared.css" title="default"/><link rel="stylesheet" type="text/css" href="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="figure.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-racket.css" title="default"/><script type="text/javascript" src="scribble-common.js"></script><script type="text/javascript" src="figure.js"></script><script type="text/javascript" src="manual-racket.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">▼</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">How to Design Programs, Second Edition</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right"></td><td><a href="part_preface.html" class="tocviewlink" data-pltdoc="x">Preface</a></td></tr><tr><td align="right"></td><td><a href="part_prologue.html" class="tocviewlink" data-pltdoc="x">Prologue:<span class="mywbr"> </span> How to Program</a></td></tr><tr><td align="right">I </td><td><a href="part_one.html" class="tocviewlink" data-pltdoc="x">Fixed-<wbr></wbr>Size Data</a></td></tr><tr><td align="right"></td><td><a href="i1-2.html" class="tocviewlink" data-pltdoc="x">Intermezzo 1: Beginning Student Language</a></td></tr><tr><td align="right">II </td><td><a href="part_two.html" class="tocviewlink" data-pltdoc="x">Arbitrarily Large Data</a></td></tr><tr><td align="right"></td><td><a href="i2-3.html" class="tocviewlink" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a></td></tr><tr><td align="right">III </td><td><a href="part_three.html" class="tocviewlink" data-pltdoc="x">Abstraction</a></td></tr><tr><td align="right"></td><td><a href="i3-4.html" class="tocviewlink" data-pltdoc="x">Intermezzo 3: Scope and Abstraction</a></td></tr><tr><td align="right">IV </td><td><a href="part_four.html" class="tocviewlink" data-pltdoc="x">Intertwined Data</a></td></tr><tr><td align="right"></td><td><a href="i4-5.html" class="tocviewlink" data-pltdoc="x">Intermezzo 4: The Nature of Numbers</a></td></tr><tr><td align="right">V </td><td><a href="part_five.html" class="tocviewselflink" data-pltdoc="x">Generative Recursion</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html" class="tocviewlink" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a></td></tr><tr><td align="right">VI </td><td><a href="part_six.html" class="tocviewlink" data-pltdoc="x">Accumulators</a></td></tr><tr><td align="right"></td><td><a href="part_epilogue.html" class="tocviewlink" data-pltdoc="x">Epilogue:<span class="mywbr"> </span> Moving On</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_1");">►</a></td><td>V </td><td><a href="part_five.html" class="tocviewselflink" data-pltdoc="x">Generative Recursion</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">25 </td><td><a href="part_five.html#%28part._ch~3astrange-recursions%29" class="tocviewlink" data-pltdoc="x">Non-<wbr></wbr>standard Recursion</a></td></tr><tr><td align="right">26 </td><td><a href="part_five.html#%28part._ch~3adesign-algo%29" class="tocviewlink" data-pltdoc="x">Designing Algorithms</a></td></tr><tr><td align="right">27 </td><td><a href="part_five.html#%28part._ch~3agen-rec-samples%29" class="tocviewlink" data-pltdoc="x">Variations on the Theme</a></td></tr><tr><td align="right">28 </td><td><a href="part_five.html#%28part._ch~3agen-rec-math%29" class="tocviewlink" data-pltdoc="x">Mathematical Examples</a></td></tr><tr><td align="right">29 </td><td><a href="part_five.html#%28part._ch~3abacktrack%29" class="tocviewlink" data-pltdoc="x">Algorithms that Backtrack</a></td></tr><tr><td align="right">30 </td><td><a href="part_five.html#%28part._ch~3asummary5%29" class="tocviewlink" data-pltdoc="x">Summary</a></td></tr></table></div></div></div></div><div class="maincolumn"><div class="main"><div class="versionbox"><span class="version">8.6.0.2</span></div><div class="navsettop"><span class="navleft"><div class="nosearchform"></div> <span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="i4-5.html" title="backward to "Intermezzo 4: The Nature of Numbers"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "How to Design Programs, Second Edition"" data-pltdoc="x">up</a> <a href="i5-6.html" title="forward to "Intermezzo 5: The Cost of Computation"" data-pltdoc="x">next →</a></span> </div><h3>V<tt> </tt><a name="(part._part~3afive)"></a>Generative Recursion</h3><table cellspacing="0" cellpadding="0"><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3astrange-recursions%29" class="toclink" data-pltdoc="x">25<span class="hspace"> </span>Non-standard Recursion</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3abundle%29" class="toclink" data-pltdoc="x">25.1<span class="hspace"> </span>Recursion without Structure</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3aquick-sort%29" class="toclink" data-pltdoc="x">25.2<span class="hspace"> </span>Recursion that Ignores Structure</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3adesign-algo%29" class="toclink" data-pltdoc="x">26<span class="hspace"> </span>Designing Algorithms</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._.Adapting_the_.Design_.Recipe%29" class="toclink" data-pltdoc="x">26.1<span class="hspace"> </span>Adapting the Design Recipe</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._.Termination%29" class="toclink" data-pltdoc="x">26.2<span class="hspace"> </span>Termination</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3astruct-gen-rec%29" class="toclink" data-pltdoc="x">26.3<span class="hspace"> </span>Structural versus Generative Recursion</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3achoice%29" class="toclink" data-pltdoc="x">26.4<span class="hspace"> </span>Making Choices</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3agen-rec-samples%29" class="toclink" data-pltdoc="x">27<span class="hspace"> </span>Variations on the Theme</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3afractal%29" class="toclink" data-pltdoc="x">27.1<span class="hspace"> </span>Fractals, a First Taste</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3abinary-search%29" class="toclink" data-pltdoc="x">27.2<span class="hspace"> </span>Binary Search</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3afiles-lines%29" class="toclink" data-pltdoc="x">27.3<span class="hspace"> </span>A Glimpse at Parsing</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3agen-rec-math%29" class="toclink" data-pltdoc="x">28<span class="hspace"> </span>Mathematical Examples</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3anewton%29" class="toclink" data-pltdoc="x">28.1<span class="hspace"> </span>Newton’s Method</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3aintegrate%29" class="toclink" data-pltdoc="x">28.2<span class="hspace"> </span>Numeric Integration</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3aproj-gauss%29" class="toclink" data-pltdoc="x">28.3<span class="hspace"> </span>Project: Gaussian Elimination</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3abacktrack%29" class="toclink" data-pltdoc="x">29<span class="hspace"> </span>Algorithms that Backtrack</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._fsm._sec~3atraverse-graph1%29" class="toclink" data-pltdoc="x">29.1<span class="hspace"> </span>Traversing Graphs</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._sec~3aproj-backtrack%29" class="toclink" data-pltdoc="x">29.2<span class="hspace"> </span>Project: Backtracking</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_five.html#%28part._ch~3asummary5%29" class="toclink" data-pltdoc="x">30<span class="hspace"> </span>Summary</a></p></td></tr></table><p>If you follow the <a name="(idx._(gentag._590))"></a>design recipe of the first four parts, either you turn
|
|
domain knowledge into code or you exploit the structure of the data
|
|
definition to organize your code.<span class="refelem"><span class="refcolumn"><span class="refcontent">Some functions merely
|
|
compose such functions; we group those with the “structural” group.</span></span></span>
|
|
The latter functions typically decompose their arguments into their
|
|
immediate structural components and then process those components. If one
|
|
of these immediate components belongs to the same class of data as the
|
|
input, the function is <a name="(idx._(gentag._591))"></a><span style="font-style: italic">structurally recursive</span>. While
|
|
structurally designed functions make up the vast majority of code in the
|
|
world, some problems cannot be solved with a structural approach to
|
|
design.</p><p>To solve such complicated problems, programmers use <span style="font-style: italic">generative
|
|
recursion</span>, a form of recursion that is strictly more powerful than
|
|
structural recursion. The study of generative recursion is as old as
|
|
mathematics and is often called the study of <span style="font-style: italic">algorithms</span>. The
|
|
inputs of an algorithm represent a problem. An algorithm tends to
|
|
rearrange a problem into a set of several problems, solve those, and
|
|
combine their solutions into one overall solution. Often some of these
|
|
newly <span style="font-weight: bold">generated</span> problems are the same kind of problem as the given
|
|
one, in which case the algorithm can be reused to solve them. In these
|
|
cases, the algorithm is recursive, but its recursion uses newly generated
|
|
data not immediate parts of the input data.</p><p>From the very description of generative recursion, you can tell that
|
|
designing a generative recursive function is more of an ad hoc activity
|
|
than designing a structurally recursive function. Still, many elements of
|
|
the general <a name="(idx._(gentag._592))"></a>design recipe apply to the design of algorithms, too, and this
|
|
part of the book illustrates how and how much the design recipe helps. The
|
|
key to designing algorithms is the “generation” step, which often means
|
|
dividing up the problem. And figuring out a novel way of dividing a
|
|
problem requires insight.<span class="refelem"><span class="refcolumn"><span class="refcontent">In Greek, it’s “eureka!”</span></span></span>
|
|
Sometimes very little insight is required. For example, it might just
|
|
require a bit of commonsense knowledge about breaking up sequences of
|
|
letters. At other times, it may rely on deep mathematical theorems about
|
|
numbers. In practice, programmers design simple algorithms on their own
|
|
and rely on domain specialists for their complex brethren. For either
|
|
kind, programmers must thoroughly understand the underlying ideas so that
|
|
they can code up algorithms and have the program communicate with future
|
|
readers. The best way to get acquainted with the idea is to study a wide
|
|
range of examples and to develop a sense for the kinds of generative
|
|
recursions that may show up in the real world.</p><h3>25<tt> </tt><a name="(part._ch~3astrange-recursions)"></a>Non-standard Recursion</h3><p>At this point you have designed numerous functions that employ structural
|
|
recursion. When you design a function, you know you need to look at the
|
|
data definition for its major input. If this input is described by a
|
|
self-referential data definition, you end up with a function that refers to
|
|
itself basically where the data definition refers to itself.</p><p>This chapter presents two sample programs that use recursion
|
|
differently. They are illustrative of the problems that require some
|
|
“eureka,” ranging from the obvious idea to the sophisticated insight.</p><h4>25.1<tt> </tt><a name="(part._sec~3abundle)"></a>Recursion without Structure</h4><p>Imagine you have joined the DrRacket team. The team is working on a sharing
|
|
service to support collaborations among programmers. Concretely, the next
|
|
revision of DrRacket is going to enable ISL programmers to share the content
|
|
of their DrRacket’s definitions area across several computers. Each time one
|
|
programmer modifies the buffer, the revised DrRacket broadcasts the content of
|
|
the definitions area to the instances of DrRacket that participate in the
|
|
sharing session.</p><blockquote><p><span style="font-weight: bold">Sample Problem</span> Your task is to design the function <span class="RktSym">bundle</span>, which
|
|
prepares the content of the definitions area for broadcasting. DrRacket hands
|
|
over the content as a list of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s. The function’s task is to
|
|
bundle up chunks of individual “letters” into chunks and to thus
|
|
produce a list of strings—<wbr></wbr>called <span style="font-weight: bold">chunks</span>—<wbr></wbr>of a given length,
|
|
called <span style="font-weight: bold">chunk size</span>.</p></blockquote><p><div class="SIntrapara">As you can see, the problem basically spells out the signature and there is
|
|
no need for any problem-specific data definition: <a name="(idx._(gentag._593))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">bundles chunks of </span><span class="RktSym">s</span><span class="RktCmt"> into strings of length </span><span class="RktSym">n</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The purpose statement reformulates a sentence fragment from the problem
|
|
statement and uses the parameters from the dummy function header.</div></p><p><div class="SIntrapara">The third step calls for function examples. Here is a list of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">If we tell <span class="RktSym">bundle</span> to bundle this list into pairs—<wbr></wbr>that
|
|
is, <span class="RktSym">n</span> is <span class="RktVal">2</span>—<wbr></wbr>then the following list is the expected result:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"ab"</span><span class="hspace"> </span><span class="RktVal">"cd"</span><span class="hspace"> </span><span class="RktVal">"ef"</span><span class="hspace"> </span><span class="RktVal">"gh"</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Now if <span class="RktSym">n</span> is <span class="RktVal">3</span> instead, there is a left-over
|
|
“letter.” Since the problem statement does not tell us which of the
|
|
characters is left over, we can imagine at least two valid scenarios:
|
|
</div><div class="SIntrapara"><ul><li><p>The function produces <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"abc"</span><span class="stt"> </span><span class="RktVal">"def"</span><span class="stt"> </span><span class="RktVal">"g"</span><span class="RktPn">)</span>; that is, it
|
|
considers the last letter as the left-over one.</p></li><li><p>Or, it produces <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">"bcd"</span><span class="stt"> </span><span class="RktVal">"efg"</span><span class="RktPn">)</span>, which packs the lead
|
|
character into a string by itself.</p></li></ul></div><div class="SIntrapara">Stop! Come up with at least one other choice.</div></p><p><div class="SIntrapara">To make things simple, we pick the first choice as the desired result and
|
|
say so by writing down a corresponding test:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktVal">"abcdefg"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"abc"</span><span class="hspace"> </span><span class="RktVal">"def"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Note the use of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span>; it makes the test readable.</div></p><p><div class="SIntrapara">Examples and tests must also describe what happens at the boundary
|
|
of data definitions. In this context, boundary clearly means
|
|
<span class="RktSym">bundle</span> is given a list that is too short for the given chunk size:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"ab"</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">It also means we must consider what happens when <span class="RktSym">bundle</span> is
|
|
given <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>. For simplicity, we choose <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> as the
|
|
desired result:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">One natural alternative is to ask for <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">""</span><span class="RktVal">)</span>. Can you see others?</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._594))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> as compound, </span><span class="RktSym">s</span><span class="RktCmt"> considered atomic</span><br/>;<span class="RktCmt"> (</span><a href="part_four.html#%28part._sec~3atwo-inputs~3acase1%29" data-pltdoc="x">Processing Two Lists Simultaneously: Case 1</a><span class="RktCmt">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">] as compound, </span><span class="RktSym">n</span><span class="RktCmt"> atomic</span><br/>;<span class="RktCmt"> (</span><a href="part_four.html#%28part._sec~3atwo-inputs~3acase1%29" data-pltdoc="x">Processing Two Lists Simultaneously: Case 1</a><span class="RktCmt">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">] and </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> are on equal footing</span><br/>;<span class="RktCmt"> (</span><a href="part_four.html#%28part._sec~3atwo-inputs~3acase2%29" data-pltdoc="x">Processing Two Lists Simultaneously: Case 2</a><span class="RktCmt">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">consider all possibilities</span><br/>;<span class="RktCmt"> (</span><a href="part_four.html#%28part._sec~3atwo-inputs~3acase3%29" data-pltdoc="x">Processing Two Lists Simultaneously: Case 3</a><span class="RktCmt">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._positive~3f%29%29" class="RktValLink" data-pltdoc="x">positive?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3abundle-template-bad))" x-target-lift="Figure"></a>Figure 146: </span>Useless templates for breaking up strings into chunks</span></p></blockquote></div></p><p>The template step reveals that a <a name="(idx._(gentag._595))"></a>structural approach cannot
|
|
work. <a href="part_five.html#%28counter._%28figure._fig~3abundle-template-bad%29%29" data-pltdoc="x">Figure <span class="FigureRef">146</span></a> shows <span style="font-weight: bold">four</span> possible
|
|
templates. Since both arguments to <span class="RktSym">bundle</span> are complex, the first
|
|
two consider one of the arguments atomic. That clearly cannot be the case
|
|
because the function has to take apart each argument. The third template
|
|
is based on the assumption that the two arguments are processed in
|
|
lockstep, which is close—<wbr></wbr>except that <span class="RktSym">bundle</span> clearly has to
|
|
reset the chunk size to its original value at regular intervals. The final
|
|
template says that the two arguments are processed independently, meaning
|
|
there are four possibilities to proceed at each stage. This final design
|
|
decouples the arguments too much because the list and the counting number
|
|
must be processed together. In short, we must admit that the structural
|
|
templates appear to be useless for this design problem.</p><p><div class="SIntrapara"><a name="(idx._(gentag._596))"></a>
|
|
<a name="(idx._(gentag._597))"></a>
|
|
<a name="(idx._(gentag._598))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">bundles chunks of </span><span class="RktSym">s</span><span class="RktCmt"> into strings of length </span><span class="RktSym">n</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">idea</span><span class="RktCmt"> take </span><span class="RktSym">n</span><span class="RktCmt"> items and drop </span><span class="RktSym">n</span><span class="RktCmt"> at a time</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._implode%29%29" class="RktValLink" data-pltdoc="x">implode</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">take</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">keeps the first </span><span class="RktSym">n</span><span class="RktCmt"> items from </span><span class="RktSym">l</span><span class="RktCmt"> if possible or everything</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">take</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">take</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">removes the first </span><span class="RktSym">n</span><span class="RktCmt"> items from </span><span class="RktSym">l</span><span class="RktCmt"> if possible or everything</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3abundle))" x-target-lift="Figure"></a>Figure 147: </span>Generative recursion</span></p></blockquote></div></p><p><div class="SIntrapara"><a href="part_five.html#%28counter._%28figure._fig~3abundle%29%29" data-pltdoc="x">Figure <span class="FigureRef">147</span></a> shows a complete definition for <span class="RktSym">bundle</span>.
|
|
The definition uses the <span class="RktSym">drop</span> and <span class="RktSym">take</span> functions requested
|
|
in <a href="part_four.html#%28counter._%28exercise._ex~3adrop-take%29%29" data-pltdoc="x">exercise 395</a>; these functions are also available in standard
|
|
libraries. For completeness, the figure comes with their definitions:
|
|
<span class="RktSym">drop</span> eliminates up to <span class="RktSym">n</span> items from the front of the list,
|
|
<span class="RktSym">take</span> returns up to that many items. Using these functions, it is
|
|
quite straightforward to define <span class="RktSym">bundle</span>:
|
|
</div><div class="SIntrapara"><ol><li><p>if the given list is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, the result is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> as
|
|
decided upon;</p></li><li><p>otherwise <span class="RktSym">bundle</span> uses <span class="RktSym">take</span> to grab the first
|
|
<span class="RktSym">n</span> <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s from <span class="RktSym">s</span> and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._implode%29%29" class="RktValLink" data-pltdoc="x">implode</a></span>s them into
|
|
a plain <a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a>;</p></li><li><p>it then recurs with a list that is shortened by <span class="RktSym">n</span> items,
|
|
which is accomplished with <span class="RktSym">drop</span>; and</p></li><li><p>finally, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> combines the string from 2 with the list of
|
|
strings from 3 to create the result for the complete list.</p></li></ol></div><div class="SIntrapara">List item 3 highlights the key difference between <span class="RktSym">bundle</span> and any
|
|
function in the first four parts of this book. Because the definition of
|
|
<a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>es an item onto a list to create another one,
|
|
all functions in the first four parts use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span> and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span>
|
|
to deconstruct a non-empty list. In contrast, <span class="RktSym">bundle</span> uses
|
|
<span class="RktSym">drop</span>, which removes not just one but <span class="RktSym">n</span> items at once.</div></p><p>While the definition of <span class="RktSym">bundle</span> is unusual, the underlying ideas
|
|
are intuitive and not too different from the functions seen so far. Indeed,
|
|
if the chunk size <span class="RktSym">n</span> is <span class="RktVal">1</span>, <span class="RktSym">bundle</span> specializes to
|
|
a structurally recursive definition. Also, <span class="RktSym">drop</span> is guaranteed to
|
|
produce an integral part of the given list, not some arbitrarily rearranged
|
|
version. And this idea is precisely what the next section presents.</p><p><a name="(counter._(exercise._ex~3abundle-loops))"></a><span style="font-weight: bold">Exercise</span> 421. Is <span class="RktPn">(</span><span class="RktSym">bundle</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">"b"</span><span class="stt"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> a proper
|
|
use of the <span class="RktSym">bundle</span> function? What does it produce? Why? <a href="part_five.html#%28counter._%28exercise._ex~3abundle-loops%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3abundle-from-abstraction))"></a><span style="font-weight: bold">Exercise</span> 422. Define the function
|
|
<span class="RktSym">list->chunks</span>. It consumes a list <span class="RktSym">l</span> of arbitrary data and
|
|
a natural number <span class="RktSym">n</span>. The function’s result is a list of list chunks
|
|
of size <span class="RktSym">n</span>. Each chunk represents a sub-sequence of items in
|
|
<span class="RktSym">l</span>.</p><p>Use <span class="RktSym">list->chunks</span> to define <span class="RktSym">bundle</span> via function
|
|
composition. <a href="part_five.html#%28counter._%28exercise._ex~3abundle-from-abstraction%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3astring-bundle))"></a><span style="font-weight: bold">Exercise</span> 423. Define <span class="RktSym">partition</span>. It
|
|
consumes a <span class="RktSym">String</span> s and a natural number <span class="RktSym">n</span>. The function
|
|
produces a list of string chunks of size <span class="RktSym">n</span>.</p><p><div class="SIntrapara">For non-empty strings <span class="RktSym">s</span> and positive natural numbers <span class="RktSym">n</span>,
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._equal~3f%29%29" class="RktValLink" data-pltdoc="x">equal?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">partition</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">is <span class="RktVal">#true</span>. But don’t use this equality as the definition for
|
|
<span class="RktSym">partition</span>; use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._substring%29%29" class="RktValLink" data-pltdoc="x">substring</a></span> instead.</div></p><p><span style="font-weight: bold">Hint</span> Have <span class="RktSym">partition</span> produce its natural result for the empty
|
|
string. For the case where <span class="RktSym">n</span> is <span class="RktVal">0</span>, see
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3abundle-loops%29%29" data-pltdoc="x">exercise 421</a>.</p><p><span style="font-weight: bold">Note</span> The <span class="RktSym">partition</span> function is somewhat closer to what a
|
|
cooperative DrRacket environment would need than <span class="RktSym">bundle</span>. <a href="part_five.html#%28counter._%28exercise._ex~3astring-bundle%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>25.2<tt> </tt><a name="(part._sec~3aquick-sort)"></a>Recursion that Ignores Structure</h4><p>Recall that the <span class="RktSym">sort></span> function from <a href="part_two.html#%28part._ch~3alist-sort%29" data-pltdoc="x">Design by Composition</a> consumes
|
|
a list of numbers and rearranges it in some order, typically ascending or
|
|
descending. It proceeds by inserting the first number into the appropriate
|
|
position of the sorted rest of the list. Put differently, it is a
|
|
<a name="(idx._(gentag._599))"></a>structurally recursive function that reprocesses the result of the natural
|
|
recursions.</p><p><div class="SIntrapara">Hoare’s quick-sort algorithm goes about sorting lists in a radically
|
|
different manner and has become the classic example of generative recursion. The
|
|
underlying generative step uses the time-honored strategy of
|
|
divide-and-conquer. That is, it divides the nontrivial instances of the
|
|
problem into two smaller, related problems; solves those smaller problems;
|
|
and combines their solutions into a solution for the original problem. In
|
|
the case of the quick-sort algorithm, the intermediate goal is to divide
|
|
the list of numbers into two lists:
|
|
</div><div class="SIntrapara"><ul><li><p>one that contains all the numbers that are strictly smaller than the
|
|
first</p></li><li><p>and another one with all those items that are strictly larger.</p></li></ul></div><div class="SIntrapara">Then the two smaller lists are sorted via the quick-sort algorithm. Once
|
|
the two lists are sorted, the results are composed with the first item
|
|
placed in the middle. Owing to its special role, the first item on the
|
|
list is called the <span style="font-style: italic">pivot item</span>.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_180.png" alt="image" width="665.998046875" height="559.0625"/></p></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asort-ill))" x-target-lift="Figure"></a>Figure 148: </span>A graphical illustration of the quick-sort algorithm</span></p></blockquote><p>To develop an understanding of how the quick-sort algorithm works, let’s
|
|
walk through an example, quick-sorting <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">11</span><span class="stt"> </span><span class="RktVal">8</span><span class="stt"> </span><span class="RktVal">14</span><span class="stt"> </span><span class="RktVal">7</span><span class="RktPn">)</span>.
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asort-ill%29%29" data-pltdoc="x">Figure <span class="FigureRef">148</span></a> illustrates the process in a graphical way. The
|
|
figure consists of a top half, the divide phase, and the bottom half, the
|
|
conquer phase.</p><p>The partition phase is represented with boxes and solid arrows. Three
|
|
arrows emerge from each boxed list and go to a box with three pieces: the
|
|
circled pivot element in the middle, to its left the boxed list of numbers
|
|
smaller than the pivot, and to its right the boxed list of those numbers
|
|
that are larger than the pivot. Each of these steps isolates at least one
|
|
number as the pivot, meaning the two neighboring lists are shorter than the
|
|
given list. Consequently, the overall process terminates too.</p><p>Consider the first step where the input is <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">11</span><span class="stt"> </span><span class="RktVal">8</span><span class="stt"> </span><span class="RktVal">14</span><span class="stt"> </span><span class="RktVal">7</span><span class="RktPn">)</span>. The
|
|
pivot item is <span class="RktVal">11</span>. Partitioning the list into items larger and
|
|
smaller than <span class="RktVal">11</span> produces <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">8</span><span class="stt"> </span><span class="RktVal">7</span><span class="RktPn">)</span> and <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">14</span><span class="RktPn">)</span>.
|
|
The remaining steps of the partitioning phase work in an analogous
|
|
way. Partitioning ends when all numbers have been isolated as pivot
|
|
elements. At this point, you can already read off the final result by
|
|
reading the pivots from left to right.</p><p>The conquering phase is represented with dashed arrows and boxed lists.
|
|
Three arrows enter each result box: the middle one from a pivot, the left
|
|
one from the boxed result of sorting the smaller numbers, and the right one
|
|
from the boxed result of sorting the larger ones. Each step adds at least
|
|
one number to the result list, the pivot, meaning the lists grow toward the
|
|
bottom of the diagram. The box at the bottom is a sorted variant of the
|
|
given list at the top.</p><p>Take a look at the left-most, upper-most conquer step. It combines the
|
|
pivot <span class="RktVal">7</span> with two empty lists, resulting in <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">7</span><span class="RktVal">)</span>. The next
|
|
one down corresponds to the partitioning step that isolated <span class="RktVal">8</span> and
|
|
thus yields <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">7</span><span class="stt"> </span><span class="RktVal">8</span><span class="RktVal">)</span>. Each level in the conquering phase mirrors a
|
|
corresponding level from the partitioning phase. After all, the overall
|
|
process is recursive.</p><p><a name="(counter._(exercise._ex~3aquicksort-hand))"></a><span style="font-weight: bold">Exercise</span> 424. Draw a quick-sort diagram like the one in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asort-ill%29%29" data-pltdoc="x">figure <span class="FigureRef">148</span></a> for <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">11</span><span class="stt"> </span><span class="RktVal">9</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">18</span><span class="stt"> </span><span class="RktVal">12</span><span class="stt"> </span><span class="RktVal">14</span><span class="stt"> </span><span class="RktVal">4</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span>. <a href="part_five.html#%28counter._%28exercise._ex~3aquicksort-hand%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Now that we have a good understanding of the quick-sort idea, we can
|
|
translate it into ISL+. Clearly, <span class="RktSym">quick-sort<</span> distinguishes two
|
|
cases. If the input is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, it produces <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> because this
|
|
list is sorted already; otherwise, it performs a generative recursion.
|
|
This case split suggests the following <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> expression:
|
|
<a name="(idx._(gentag._600))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">produces a sorted version of </span><span class="RktSym">alon</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The answer for the first case is given. For the second case, when
|
|
<span class="RktSym">quick-sort<</span>’s input is a non-empty list, the algorithm uses the
|
|
first item to partition the rest of the list into two sublists: a list with
|
|
all items smaller than the pivot item and another one with those larger
|
|
than the pivot item.</div></p><p>Since the rest of the list is of unknown size, we leave the task of
|
|
partitioning the list to two auxiliary functions: <span class="RktSym">smallers</span>
|
|
and <span class="RktSym">largers</span>. They process the list and filter out those items
|
|
that are smaller and larger, respectively, than the pivot. Hence each
|
|
auxiliary function accepts two arguments, namely, a list of numbers and a
|
|
number. Designing these two functions is an exercise in structural
|
|
recursion. Try on your own or read the definitions shown in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3aquick-sort%29%29" data-pltdoc="x">figure <span class="FigureRef">149</span></a>.</p><p><div class="SIntrapara"><a name="(idx._(gentag._601))"></a>
|
|
<a name="(idx._(gentag._602))"></a>
|
|
<a name="(idx._(gentag._603))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">produces a sorted version of </span><span class="RktSym">alon</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> the numbers are all distinct </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c%29%29" class="RktValLink" data-pltdoc="x"><</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aquick-sort))" x-target-lift="Figure"></a>Figure 149: </span>The quick-sort algorithm</span></p></blockquote></div></p><p><div class="SIntrapara">Each of these lists is sorted separately, using <span class="RktSym">quick-sort<</span>, which
|
|
implies the use of recursion, specifically the following two expressions:
|
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="stt"> </span><span class="RktSym">alon</span><span class="stt"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span>,
|
|
which sorts the list of items smaller than the pivot; and</p></li><li><p><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="stt"> </span><span class="RktSym">alon</span><span class="stt"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span>,
|
|
which sorts the list of items larger than the pivot.</p></li></ol></div><div class="SIntrapara">Once <span class="RktSym">quick-sort<</span> has the sorted versions of the two lists, it must
|
|
combine the two lists and the pivot in the proper order: first all those
|
|
items smaller than <span class="RktSym">pivot</span>, then <span class="RktSym">pivot</span>, and finally all
|
|
those that are larger. Since the first and last list are already sorted,
|
|
<span class="RktSym">quick-sort<</span> can simply use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largers</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">pivot</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara"><a href="part_five.html#%28counter._%28figure._fig~3aquick-sort%29%29" data-pltdoc="x">Figure <span class="FigureRef">149</span></a> contains the full program; read it before
|
|
proceeding.</div></p><p><div class="SIntrapara">Now that we have an actual function definition, we can evaluate the example
|
|
from above by hand:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">14</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">11</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr></table></blockquote></div><div class="SIntrapara">The calculation shows the essential steps of the sorting process, that is,
|
|
the partitioning steps, the recursive sorting steps, and the concatenation
|
|
of the three parts. From this calculation, it is easy to see how
|
|
<span class="RktSym">quick-sort<</span> implements the process illustrated in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asort-ill%29%29" data-pltdoc="x">figure <span class="FigureRef">148</span></a>.</div></p><p>Both <a href="part_five.html#%28counter._%28figure._fig~3asort-ill%29%29" data-pltdoc="x">figure <span class="FigureRef">148</span></a> and the calculation also show how
|
|
<span class="RktSym">quick-sort<</span> completely ignores the structure of the given list. The
|
|
first recursion works on two distant numbers from the originally given list
|
|
and the second one on the list’s third item. These recursions aren’t random,
|
|
but they are certainly not relying on the structure of the data
|
|
definition.</p><p>Contrast <span class="RktSym">quick-sort<</span>’s organization with that of the <span class="RktSym">sort></span>
|
|
function from <a href="part_two.html#%28part._ch~3alist-sort%29" data-pltdoc="x">Design by Composition</a>. The design of the latter follows the
|
|
structural design recipe, yielding a program that processes a list item by
|
|
item. By splitting the list, <span class="RktSym">quick-sort<</span> can speed up the process
|
|
of sorting the list, though at the cost of not using plain <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span>
|
|
and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span>.</p><p><a name="(counter._(exercise._ex~3aquick-sort-purpose))"></a><span style="font-weight: bold">Exercise</span> 425. Articulate purpose statements for
|
|
<span class="RktSym">smallers</span> and <span class="RktSym">largers</span> in <a href="part_five.html#%28counter._%28figure._fig~3aquick-sort%29%29" data-pltdoc="x">figure <span class="FigureRef">149</span></a>. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-purpose%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aquick-sort-terminal))"></a><span style="font-weight: bold">Exercise</span> 426. Complete the hand-evaluation from
|
|
above. A close inspection of the evaluation suggests an additional trivial
|
|
case for <span class="RktSym">quick-sort<</span>. Every time <span class="RktSym">quick-sort<</span> consumes a
|
|
list of one item, it returns it as is. After all, the sorted version of a
|
|
list of one item is the list itself.</p><p>Modify <span class="RktSym">quick-sort<</span> to take advantage of this observation.
|
|
Evaluate the example again. How many steps does the revised algorithm
|
|
save? <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-terminal%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aquick-sort-switch))"></a><span style="font-weight: bold">Exercise</span> 427. While <span class="RktSym">quick-sort<</span> quickly reduces
|
|
the size of the problem in many cases, it is inappropriately slow for small
|
|
problems. Hence people use <span class="RktSym">quick-sort<</span> to reduce the size of the
|
|
problem and switch to a different sort function when the list is small
|
|
enough.</p><p>Develop a version of <span class="RktSym">quick-sort<</span> that uses <span class="RktSym">sort<</span> (an
|
|
appropriately adapted variant of <span class="RktSym">sort></span> from <a href="part_two.html#%28part._sec~3asort.I%29" data-pltdoc="x">Auxiliary Functions that Recur</a>) if
|
|
the length of the input is below some threshold. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-switch%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aquick-sort-drop))"></a><span style="font-weight: bold">Exercise</span> 428. If the input to <span class="RktSym">quick-sort<</span>
|
|
contains the same number several times, the algorithm returns a list that
|
|
is strictly shorter than the input. Why? Fix the problem so that the
|
|
output is as long as the input. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-drop%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aquick-sort-filter))"></a><span style="font-weight: bold">Exercise</span> 429. Use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._filter%29%29" class="RktValLink" data-pltdoc="x">filter</a></span> to define
|
|
<span class="RktSym">smallers</span> and <span class="RktSym">largers</span>. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-filter%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aquick-sort-abstract))"></a><span style="font-weight: bold">Exercise</span> 430. Develop a variant of
|
|
<span class="RktSym">quick-sort<</span> that uses only one comparison function, say,
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c%29%29" class="RktValLink" data-pltdoc="x"><</a></span>. Its partitioning step divides the given list <span class="RktSym">alon</span> into
|
|
a list that contains the items of <span class="RktSym">alon</span> smaller than the pivot and
|
|
another one with those that are not smaller.</p><p>Use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> to package up the program as a single function. Abstract
|
|
this function so that it consumes a list and a comparison function. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-abstract%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>26<tt> </tt><a name="(part._ch~3adesign-algo)"></a>Designing Algorithms</h3><p>The overview for this part already explains that the design of generative
|
|
recursion functions is more ad hoc than <a name="(idx._(gentag._604))"></a>structural design. As the first
|
|
chapter shows, two generative recursions can radically differ in how they
|
|
process functions. Both <span class="RktSym">bundle</span> and <span class="RktSym">quick-sort<</span> process
|
|
lists, but while the former at least respects the sequencing in the given
|
|
list, the latter rearranges its given list at will. The question is
|
|
whether a single <a name="(idx._(gentag._605))"></a>design recipe can help with the creation of such widely
|
|
differing functions.</p><p>The first section shows how to adapt the <a name="(idx._(gentag._606))"></a>process dimension of the <a name="(idx._(gentag._607))"></a>design
|
|
recipe to generative recursion. The second section homes in on another new
|
|
phenomenon: an algorithm may fail to produce an answer for some of its
|
|
inputs. Programmers must therefore analyze their programs and supplement
|
|
the design information with a <a name="(idx._(gentag._608))"></a>comment on termination. The remaining
|
|
sections contrast <a name="(idx._(gentag._609))"></a>structural and <a name="(idx._(gentag._610))"></a>generative recursion.</p><h4>26.1<tt> </tt><a name="(part._.Adapting_the_.Design_.Recipe)"></a>Adapting the Design Recipe</h4><p><div class="SIntrapara">Let’s examine the six general steps of our structural design recipe in
|
|
light of the examples in the preceding chapter:
|
|
</div><div class="SIntrapara"><ul><li><p>As before, we must represent the problem information as data in our
|
|
chosen programming language. The choice of a <span style="font-weight: bold">data representation</span>
|
|
for a problem affects our thinking about the computational process, so
|
|
some planning ahead is necessary. Alternatively, be prepared to backtrack
|
|
and to explore different <a name="(idx._(gentag._611))"></a>data representations. Regardless, we must analyze
|
|
the problem information and define data collections.</p></li><li><p>We also need a signature, a function header, and a <a name="(idx._(gentag._612))"></a>purpose
|
|
statement. Since the generative step has no connection to the structure of
|
|
the <a name="(idx._(gentag._613))"></a>data definition, the purpose statement must go beyond <span style="font-weight: bold">what</span> the
|
|
function is to compute and also explain <span style="font-weight: bold">how</span> the function computes
|
|
its result.</p></li><li><p>It is useful to explain the “how” with <a name="(idx._(gentag._614))"></a>function examples, the way
|
|
we explained <span class="RktSym">bundle</span> and <span class="RktSym">quick-sort<</span> in the previous
|
|
chapter. That is, while function examples in the structural world merely
|
|
specify which output the function is to produce for which input, the
|
|
purpose of examples in the world of generative recursion is to explain the
|
|
underlying idea behind the computational process.</p><p>For <span class="RktSym">bundle</span>, the examples specify how the function acts in general
|
|
and in certain boundary cases. For <span class="RktSym">quick-sort<</span>, the example in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asort-ill%29%29" data-pltdoc="x">figure <span class="FigureRef">148</span></a> illustrates how the function partitions the
|
|
given list with respect to the pivot item. By adding such worked examples
|
|
to the purpose statement, we—<wbr></wbr>the designers—<wbr></wbr>gain an improved
|
|
understanding of the desired process, and we communicate this understanding
|
|
to future readers of this code.</p></li><li><p>Our discussion suggests a <a name="(idx._(gentag._615))"></a>general template for
|
|
<a name="(idx._(gentag._616))"></a>algorithms. Roughly
|
|
speaking, the design of an algorithm distinguishes two kinds of problems:
|
|
those that are <span style="font-style: italic">trivially solvable</span> and those that are
|
|
not.<span class="refelem"><span class="refcolumn"><span class="refcontent">For this part of the book, “trivial” is a technical
|
|
term.</span></span></span> If a given problem is trivially solvable, an algorithm produces
|
|
the matching solution. For example, the problems of sorting an empty list
|
|
or a one-item list are trivially solvable. A list with many items is a
|
|
nontrivial problem. For these nontrivial problems, algorithms commonly
|
|
generate new problems of the same kind as the given one, solve those
|
|
recursively, and combine the solutions into an overall solution.</p><p><div class="SIntrapara">Based on this sketch, all algorithms have roughly this organization:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generative-recursive-fun</span><span class="hspace"> </span><span class="RktSym">problem</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">trivially-solvable?</span><span class="hspace"> </span><span class="RktSym">problem</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">determine-solution</span><span class="hspace"> </span><span class="RktSym">problem</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">combine-solutions</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">problem</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generative-recursive-fun</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generate-problem-1</span><span class="hspace"> </span><span class="RktSym">problem</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generative-recursive-fun</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generate-problem-n</span><span class="hspace"> </span><span class="RktSym">problem</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The original problem is occasionally needed to combine the solutions for
|
|
the newly generated problems, which is why it is handed over to
|
|
<span class="RktSym">combine-solutions</span>.</div></p></li><li><p><div class="SIntrapara">This <a name="(idx._(gentag._617))"></a>template is only a suggestive blueprint, not a definitive shape.
|
|
Each piece of the template is to remind us to think about the
|
|
following four questions:
|
|
</div><div class="SIntrapara"><ul><li><p>What is a trivially solvable problem?</p></li><li><p>How are trivial problems solved?</p></li><li><p>How does the algorithm generate new problems that are more easily
|
|
solvable than the original one? Is there one new problem that we generate
|
|
or are there several?</p></li><li><p>Is the solution of the given problem the same as the solution of
|
|
(one of) the new problems? Or, do we need to combine the solutions to
|
|
create a solution for the original problem? And, if so, do we need
|
|
anything from the original problem data?</p></li></ul></div><div class="SIntrapara">To define the algorithm as a function, we must express the answers to
|
|
these four questions as functions and expressions in terms of the chosen
|
|
<a name="(idx._(gentag._618))"></a>data representation.</div></p><p>For this step, the table-driven attempt from <a href="part_two.html#%28part._ch~3adesign-lists%29" data-pltdoc="x">Designing with Self-Referential Data Definitions</a> might
|
|
help again. Reconsider the <span class="RktSym">quick-sort<</span> example from
|
|
<a href="part_five.html#%28part._sec~3aquick-sort%29" data-pltdoc="x">Recursion that Ignores Structure</a>. The central idea behind <span class="RktSym">quick-sort<</span> is to
|
|
divide a given list into a list of smaller items and larger items and to
|
|
sort those separately. <a href="part_five.html#%28counter._%28figure._fig~3aquick-sort-table%29%29" data-pltdoc="x">Figure <span class="FigureRef">150</span></a> spells out how some
|
|
simple numeric examples work out for the nontrivial cases. From these
|
|
examples it is straightforward to guess that the answer to the fourth
|
|
question is to append the sorted list of smaller numbers, the pivot number,
|
|
and the sorted list of larger numbers, which can easily be translated into
|
|
code.</p></li><li><p>Once the function is complete, it is time to test it. As before, the
|
|
goal of testing is to discover and eliminate bugs.</p></li></ul></div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span class="RktSym">alon</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="RktSym">pivot</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>sorted, smaller</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>sorted, larger</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>expected</p></td></tr><tr><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">2</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td></tr><tr><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">2</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td></tr><tr><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">3</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">4</span><span class="RktVal">)</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span></p></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aquick-sort-table))" x-target-lift="Figure"></a>Figure 150: </span>The table-based guessing approach for combining solutions</span></p></blockquote><p><a name="(counter._(exercise._ex~3agen-fun-instance1))"></a><span style="font-weight: bold">Exercise</span> 431. Answer the four key
|
|
questions for the <span class="RktSym">bundle</span> problem and the first three questions
|
|
for the <span class="RktSym">quick-sort<</span> problem. How many instances of
|
|
<span class="RktSym">generate-problem</span> are needed? <a href="part_five.html#%28counter._%28exercise._ex~3agen-fun-instance1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aworm5-explained))"></a><span style="font-weight: bold">Exercise</span> 432. <a href="part_two.html#%28counter._%28exercise._ex~3aworm5%29%29" data-pltdoc="x">Exercise 219</a> introduces the function
|
|
<span class="RktSym">food-create</span>, which consumes a <a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a> and produces a randomly
|
|
chosen <a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a> that is guaranteed to be distinct from the given
|
|
one. First reformulate the two functions as a single definition, using
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span>; then justify the design of <span class="RktSym">food-create</span>. <a href="part_five.html#%28counter._%28exercise._ex~3aworm5-explained%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>26.2<tt> </tt><a name="(part._.Termination)"></a>Termination</h4><p><div class="SIntrapara">Generative recursion adds an entirely new aspect to computations:
|
|
non-termination. A function such as <span class="RktSym">bundle</span> may never produce a
|
|
value or signal an error for certain inputs. <a href="part_five.html#%28counter._%28exercise._ex~3abundle-loops%29%29" data-pltdoc="x">Exercise 421</a> asks
|
|
what the result of <span class="RktPn">(</span><span class="RktSym">bundle</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">"b"</span><span class="stt"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> is, and here is an
|
|
explanation of why it does not have a result:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._implode%29%29" class="RktValLink" data-pltdoc="x">implode</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">take</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._implode%29%29" class="RktValLink" data-pltdoc="x">implode</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">""</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">drop</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">""</span><span class="hspace"> </span><span class="highlighted"><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">"b"</span><span class="stt"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The calculation shows how evaluating <span class="RktPn">(</span><span class="RktSym">bundle</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"a"</span><span class="stt"> </span><span class="RktVal">"b"</span><span class="stt"> </span><span class="RktVal">"c"</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> requires having a result for the very same expression. In the
|
|
context of ISL+ this means the evaluation does not stop. Computer
|
|
scientists say that <span class="RktSym">bundle</span> does not <span style="font-style: italic">terminate</span> when the
|
|
second argument is <span class="RktVal">0</span>; they also say that the function
|
|
<span style="font-style: italic">loops</span> or that the computation is stuck in an <span style="font-style: italic">infinite
|
|
loop</span>.</div></p><p>Contrast this insight with the designs presented in the first four
|
|
parts. Every function designed according to the recipe either produces an
|
|
answer or raises an error signal for every input. After all, the recipe
|
|
dictates that each natural recursion consumes an immediate piece of the
|
|
input, not the input itself. Because data is constructed in a hierarchical
|
|
manner, input shrinks at every stage. Eventually the function is applied
|
|
to an atomic piece of data, and the recursion stops.</p><p>This reminder also explains why generative recursive functions may
|
|
diverge. According to the <a name="(idx._(gentag._619))"></a>design recipe for generative recursion, an
|
|
algorithm may generate new problems without any limitations. If the design
|
|
recipe required a guarantee that the new problems were
|
|
“smaller” than the given one, it would terminate.<span class="refelem"><span class="refcolumn"><span class="refcontent">The
|
|
theory of computation actually shows that we must lift these restrictions
|
|
eventually.</span></span></span> But, imposing such a restriction would needlessly complicate
|
|
the design of functions such as <span class="RktSym">bundle</span>.</p><p>In this book, we therefore keep the first six steps of the design recipe
|
|
mostly intact and supplement them with a seventh step: the
|
|
<a name="(idx._(gentag._620))"></a><span style="font-style: italic">termination argument</span>. <a href="part_five.html#%28counter._%28figure._fig~3adesign7%29%29" data-pltdoc="x">Figure <span class="FigureRef">151</span></a> presents the
|
|
first part of the <a name="(idx._(gentag._621))"></a>design recipe for generative recursion, and
|
|
<a href="part_five.html#%28counter._%28figure._fig~3adesign7b%29%29" data-pltdoc="x">figure <span class="FigureRef">152</span></a> the second one. They show the design recipe
|
|
in the conventional tabular form. The unmodified steps come with a dash
|
|
in the <span style="font-weight: bold">activity</span> column. Others come with comments on how the <a name="(idx._(gentag._622))"></a>design
|
|
recipe for generative recursion differs from the one for structural
|
|
recursion. The last row in <a href="part_five.html#%28counter._%28figure._fig~3adesign7b%29%29" data-pltdoc="x">figure <span class="FigureRef">152</span></a> is completely new.</p><p>A termination argument comes in one of two forms. The first one argues why
|
|
each recursive call works on a problem that is smaller than the given
|
|
one. Often this argument is straightforward; on rare occasions, you will
|
|
need to work with a mathematician to prove a theorem for such arguments.
|
|
The second kind illustrates with an example that the function may not
|
|
terminate.<span class="refelem"><span class="refcolumn"><span class="refcontent">You cannot define a predicate for this class;
|
|
otherwise you could modify the function and ensure that it always
|
|
terminates.</span></span></span> Ideally it should also describe the class of data for which
|
|
the function may loop. In rare cases, you may not be able to make either
|
|
argument because computer science does not know enough yet.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">steps</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">outcome</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">activity</span></p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>problem analysis</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a name="(idx._(gentag._623))"></a>data representation and <a name="(idx._(gentag._624))"></a>definition</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>—<wbr></wbr></p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>header</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>a purpose statement concerning the “how” of the function</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>supplement the explanation of <span style="font-weight: bold">what</span> the function computes with
|
|
a one-liner on <span style="font-weight: bold">how</span> it computes the result</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>examples</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>examples and tests</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>work through the “how” with several examples</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>template</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>fixed template</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>—<wbr></wbr></p></td></tr></table></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3adesign7))" x-target-lift="Figure"></a>Figure 151: </span>Designing algorithms (part 1)</span></p></blockquote><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">steps</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">outcome</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">activity</span></p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>definition</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>full-fledged function definition</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>formulate conditions for trivially solvable problems;
|
|
formulate answers for these trivial cases;
|
|
determine how to generate new problems for nontrivial problems,
|
|
possibly using auxiliary functions;
|
|
determine how to combine the solutions of the generated problems
|
|
into a solution for the given problem</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>tests</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>discover mistakes</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>—<wbr></wbr></p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p>termination</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>(1) a size argument for each recursive call
|
|
or
|
|
(2) examples of exceptions to termination</p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p>investigate whether the problem data for each recursive data is
|
|
smaller than the given data; find examples that cause the function to loop</p></td></tr></table></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3adesign7b))" x-target-lift="Figure"></a>Figure 152: </span>Designing algorithms (part 2)</span></p></blockquote><p><div class="SIntrapara">Let’s illustrate the two kinds of <a name="(idx._(gentag._625))"></a>termination arguments with examples.
|
|
For the <span class="RktSym">bundle</span> function, it suffices to warn readers about chunk
|
|
size <span class="RktVal">0</span>: <a name="(idx._(gentag._626))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">bundles sub-sequences of </span><span class="RktSym">s</span><span class="RktCmt"> into strings of length </span><span class="RktSym">n</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">termination</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="stt"> </span><span class="RktSym">s</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktCmt"> loops unless </span><span class="RktSym">s</span><span class="RktCmt"> is </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bundle</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">In this case, it is possible to define a predicate that precisely
|
|
describes when <span class="RktSym">bundle</span> terminates. For <span class="RktSym">quick-sort<</span>, the
|
|
key observation is that each recursive use of <span class="RktSym">quick-sort<</span>
|
|
receives a list that is shorter than <span class="RktSym">alon</span>: <a name="(idx._(gentag._627))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates a sorted variant of </span><span class="RktSym">alon</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">termination</span><span class="RktCmt"> both recursive calls to </span><span class="RktSym">quick-sort<</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">receive list that miss the pivot item</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">In one case, the list consists of the numbers that are strictly smaller
|
|
than the pivot; the other one is for numbers strictly larger.</div></p><p><a name="(counter._(exercise._ex~3aterminate-bundle))"></a><span style="font-weight: bold">Exercise</span> 433. Develop a checked version of
|
|
<span class="RktSym">bundle</span> that is guaranteed to terminate for all inputs. It may
|
|
signal an error for those cases where the original version loops. <a href="part_five.html#%28counter._%28exercise._ex~3aterminate-bundle%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aquick-sort-non-terminate))"></a><span style="font-weight: bold">Exercise</span> 434. Consider the following definition
|
|
of <span class="RktSym">smallers</span>, one of the two “problem generators” for
|
|
<span class="RktSym">quick-sort<</span>:<a name="(idx._(gentag._628))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">smallers</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">What can go wrong when this version is used with the <span class="RktSym">quick-sort<</span>
|
|
definition from <a href="part_five.html#%28part._sec~3aquick-sort%29" data-pltdoc="x">Recursion that Ignores Structure</a>? <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-non-terminate%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3aquick-sort-terminates))"></a><span style="font-weight: bold">Exercise</span> 435. When you worked on
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-abstract%29%29" data-pltdoc="x">exercise 430</a> or <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-drop%29%29" data-pltdoc="x">exercise 428</a>, you may have
|
|
produced looping solutions. Similarly, <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-non-terminate%29%29" data-pltdoc="x">exercise 434</a>
|
|
actually reveals how brittle the termination argument is for
|
|
<span class="RktSym">quick-sort<</span>. In all cases, the argument relies on the idea that
|
|
<span class="RktSym">smallers</span> and <span class="RktSym">largers</span> produce lists that are
|
|
maximally as long as the given list, and on our understanding that neither
|
|
includes the given pivot in the result.</p><p>Based on this explanation, modify the definition of <span class="RktSym">quick-sort<</span> so
|
|
that both functions receive lists that are shorter than the given one. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-terminates%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aworm5-terminated))"></a><span style="font-weight: bold">Exercise</span> 436. Formulate a termination argument for
|
|
<span class="RktSym">food-create</span> from <a href="part_five.html#%28counter._%28exercise._ex~3aworm5-explained%29%29" data-pltdoc="x">exercise 432</a>. <a href="part_five.html#%28counter._%28exercise._ex~3aworm5-terminated%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>26.3<tt> </tt><a name="(part._sec~3astruct-gen-rec)"></a>Structural versus Generative Recursion</h4><p>The template for algorithms is so general that it includes <a name="(idx._(gentag._629))"></a>structurally
|
|
recursive functions. Consider the left side of
|
|
<a href="part_five.html#%28counter._%28figure._fig~3agenerative-vs-structural%29%29" data-pltdoc="x">figure <span class="FigureRef">153</span></a>. This template is specialized to deal with
|
|
one trivial clause and one <a name="(idx._(gentag._630))"></a>generative step. If we replace
|
|
<span class="RktSym">trivial?</span> with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span> and <span class="RktSym">generate</span> with
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span>, we get a template for list-processing functions; see the
|
|
right side of <a href="part_five.html#%28counter._%28figure._fig~3agenerative-vs-structural%29%29" data-pltdoc="x">figure <span class="FigureRef">153</span></a>.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">general</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">trivial?</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">solve</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">combine-solutions</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">P</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">general</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">generate</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">special</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">solve</span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">combine-solutions</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">P</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">special</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">P</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3agenerative-vs-structural))" x-target-lift="Figure"></a>Figure 153: </span>From generative to structural recursion</span></p></blockquote><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agenerative-length))"></a><span style="font-weight: bold">Exercise</span> 437. Define <span class="RktSym">solve</span> and
|
|
<span class="RktSym">combine-solutions</span> so that
|
|
</div><div class="SIntrapara"><ul><li><p><span class="RktSym">special</span> computes the length of its input,</p></li><li><p><span class="RktSym">special</span> negates each number on the given list of numbers, and</p></li><li><p><span class="RktSym">special</span> uppercases the given list of strings.</p></li></ul></div><div class="SIntrapara">What do you conclude from these exercises? <a href="part_five.html#%28counter._%28exercise._ex~3agenerative-length%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>Now you may wonder whether there is a real difference between <a name="(idx._(gentag._631))"></a>structural
|
|
recursive design and the one for <a name="(idx._(gentag._632))"></a>generative recursion. Our answer is “it
|
|
depends.” Of course, we could say that all functions using structural
|
|
recursion are just special cases of generative recursion. This “everything
|
|
is equal” attitude, however, is of no help if we wish to understand the
|
|
process of designing functions. It confuses two kinds of design that
|
|
require different forms of knowledge and that have different
|
|
consequences. One relies on a systematic data analysis and not much more;
|
|
the other requires a deep, often mathematical, insight into the
|
|
<a name="(idx._(gentag._633))"></a>problem-solving process itself. One leads programmers to naturally
|
|
terminating functions; the other requires a termination
|
|
argument. Conflating these two approaches is unhelpful.</p><h4>26.4<tt> </tt><a name="(part._sec~3achoice)"></a>Making Choices</h4><p>When you interact with a function <span class="RktSym">f</span> that sorts lists of numbers,
|
|
it is impossible for you to know whether <span class="RktSym">f</span> is <span class="RktSym">sort<</span> or
|
|
<span class="RktSym">quick-sort<</span>. The two functions behave in an observably
|
|
equivalent way.<span class="refelem"><span class="refcolumn"><span class="refcontent"><span style="font-style: italic">Observable equivalence</span> is a central
|
|
concept from the study of programming languages.</span></span></span> This raises the
|
|
question of which of the two a programming language should provide. More
|
|
generally, when we can design a function using <a name="(idx._(gentag._634))"></a>structural recursion and
|
|
<a name="(idx._(gentag._635))"></a>generative recursion, we must figure out which one to pick.</p><p><div class="SIntrapara">To illustrate the consequences of this choice, we discuss a classical
|
|
example from mathematics: the problem of finding the greatest common
|
|
divisor (<span style="font-style: italic">gcd</span>) of two positive natural numbers.<span class="refelem"><span class="refcolumn"><span class="refcontent">John
|
|
Stone suggested the greatest common divisor as a suitable example.</span></span></span> All
|
|
such numbers have 1 as divisor in common. On occasion—<wbr></wbr>say, 2 and 3—<wbr></wbr>this
|
|
is also the only common divisor. Both 6 and 25 are numbers with several
|
|
divisors:
|
|
</div><div class="SIntrapara"><ul><li><p>6 is evenly divisible by 1, 2, 3, and 6;</p></li><li><p>25 is evenly divisible by 1, 5, and 25.</p></li></ul></div><div class="SIntrapara">And yet, their greatest common divisor is 1. In contrast, 18 and 24 have many
|
|
common divisors and their greatest common divisor is 6:
|
|
</div><div class="SIntrapara"><ul><li><p>18 is evenly divisible by 1, 2, 3, 6, 9, and 18;</p></li><li><p>24 is evenly divisible by 1, 2, 3, 4, 6, 8, 12, and 24.</p></li></ul></div></p><p><div class="SIntrapara">Completing the first three steps of the design recipe is straightforward: <a name="(idx._(gentag._636))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 1] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 1] -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds the greatest common divisor of </span><span class="RktSym">n</span><span class="RktCmt"> and </span><span class="RktSym">m</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="hspace"> </span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">25</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="hspace"> </span><span class="RktVal">18</span><span class="hspace"> </span><span class="RktVal">24</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">6</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">42</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The signature specifies the inputs as natural numbers greater than or equal to <span class="RktVal">1</span>.</div></p><p>From here we design both a structural and a generative recursive
|
|
solution. Since this part of the book is about generative recursion, we
|
|
merely present a structural solution in <a href="part_five.html#%28counter._%28figure._fig~3astructural-gcd%29%29" data-pltdoc="x">figure <span class="FigureRef">154</span></a> and
|
|
leave the design ideas to exercises. Just note that <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="stt"> </span><span class="RktSym">m</span><span class="stt"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> encodes the idea that both <span class="RktSym">n</span> and <span class="RktSym">m</span>
|
|
are “evenly divisible” by <span class="RktSym">i</span>.</p><p><div class="SIntrapara"><a name="(idx._(gentag._637))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines the gcd of </span><span class="RktSym">n</span><span class="RktCmt"> and </span><span class="RktSym">m</span><span class="RktCmt"> less than </span><span class="RktSym">i</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">greatest-divisor-<=</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">i</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">greatest-divisor-<=</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">greatest-divisor-<=</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._min%29%29" class="RktValLink" data-pltdoc="x">min</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3astructural-gcd))" x-target-lift="Figure"></a>Figure 154: </span>Finding the greatest common divisor via structural recursion</span></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3aexplain-structural-gcd))"></a><span style="font-weight: bold">Exercise</span> 438. In your words: how does
|
|
<span class="RktSym">greatest-divisor-<=</span> work? Use the design recipe to find the right
|
|
words. Why does the locally defined <span class="RktSym">greatest-divisor-<=</span> recur on
|
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._min%29%29" class="RktValLink" data-pltdoc="x">min</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktSym">m</span><span class="RktPn">)</span>? <a href="part_five.html#%28counter._%28exercise._ex~3aexplain-structural-gcd%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Although the design of <span class="RktSym">gcd-structural</span> is rather straightforward,
|
|
it is also naive. It simply tests for every number between the smaller of
|
|
<span class="RktSym">n</span> and <span class="RktSym">m</span> and <span class="RktVal">1</span> whether it divides both <span class="RktSym">n</span>
|
|
and <span class="RktSym">m</span> evenly and returns the first such number. For small
|
|
<span class="RktSym">n</span> and <span class="RktSym">m</span>, this works just fine. Consider the following
|
|
example, however:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktVal">101135853</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The result is <span class="RktVal">177</span>. To get there, <span class="RktSym">gcd-structural</span> checks
|
|
the “evenly divisible” condition for 45014640, that is, it checks
|
|
<span style="font-style: italic"></span>4<span style="font-style: italic"></span>5<span style="font-style: italic"></span>0<span style="font-style: italic"></span>1<span style="font-style: italic"></span>4<span style="font-style: italic"></span>6<span style="font-style: italic"></span>4<span style="font-style: italic"></span>0<span style="font-style: italic"> - </span>1<span style="font-style: italic"></span>7<span style="font-style: italic"></span>7<span style="font-style: italic"></span> remainders. Checking that many <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span>s—<wbr></wbr>twice!—<wbr></wbr>is a
|
|
large effort, and even reasonably fast computers need time to complete this
|
|
task.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agcd-struct-time))"></a><span style="font-weight: bold">Exercise</span> 439. Copy <span class="RktSym">gcd-structural</span> into DrRacket and evaluate
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._time%29%29" class="RktStxLink" data-pltdoc="x">time</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktVal">101135853</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">in the interactions area. <a href="part_five.html#%28counter._%28exercise._ex~3agcd-struct-time%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara">Since mathematicians recognized the inefficiency of this structural
|
|
function a long time ago, they studied the problem of finding divisors in
|
|
depth. The essential insight is that
|
|
</div><div class="SIntrapara"><blockquote><p>for two natural numbers, <span class="RktSym">L</span> for
|
|
<span style="font-weight: bold">large</span> and <span class="RktSym">S</span> for <span style="font-weight: bold">small</span>, the greatest common divisor
|
|
is equal to the greatest common divisor of <span class="RktSym">S</span> and the
|
|
remainder of <span class="RktSym">L</span> divided by <span class="RktSym">S</span>.</p></blockquote></div><div class="SIntrapara">Here is how we can articulate this insight as an equation:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Since <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="stt"> </span><span class="RktSym">L</span><span class="stt"> </span><span class="RktSym">S</span><span class="RktPn">)</span> is smaller than both
|
|
<span class="RktSym">L</span> and <span class="RktSym">S</span>, the right-hand side use of
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span> consumes <span class="RktSym">S</span> first.</div></p><p><div class="SIntrapara">Here is how this insight applies to our small example:
|
|
</div><div class="SIntrapara"><ul><li><p>The given numbers are <span class="RktVal">18</span> and <span class="RktVal">24</span>.</p></li><li><p>According to the insight, they have the same gcd as <span class="RktVal">18</span> and <span class="RktVal">6</span>.</p></li><li><p>And these two have the same greatest common divisor as <span class="RktVal">6</span> and
|
|
<span class="RktVal">0</span>.</p></li></ul></div><div class="SIntrapara">Now we seem stuck because <span class="RktVal">0</span> is unexpected. But, <span class="RktVal">0</span>
|
|
can be evenly divided by every number, meaning we have found our answer:
|
|
<span class="RktVal">6</span>.</div></p><p><div class="SIntrapara">Working through the example not only validates the basic insight but also
|
|
suggests how to turn the insight into an algorithm:
|
|
</div><div class="SIntrapara"><ul><li><p>when the smaller of the numbers is <span class="RktVal">0</span>, we face a trivial case;</p></li><li><p>the larger of the two numbers is the solution in the trivial case;</p></li><li><p>generating a new problem requires one <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span> operation; and</p></li><li><p>the above equation tells us that the answer to the newly generated
|
|
problem is also the answer to the originally given problem.</p></li></ul></div><div class="SIntrapara">In short, the answers for the four design-recipe questions fall out.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._638))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-generative</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 1] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>=1] -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative recursion</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="stt"> </span><span class="RktSym">L</span><span class="stt"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">==</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span><span class="stt"> </span><span class="RktSym">S</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="stt"> </span><span class="RktSym">L</span><span class="stt"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktSym">S</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._max%29%29" class="RktValLink" data-pltdoc="x">max</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._min%29%29" class="RktValLink" data-pltdoc="x">min</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3agenerative-gcd))" x-target-lift="Figure"></a>Figure 155: </span>Finding the greatest common divisor via generative recursion</span></p></blockquote></div></p><p><a href="part_five.html#%28counter._%28figure._fig~3agenerative-gcd%29%29" data-pltdoc="x">Figure <span class="FigureRef">155</span></a> presents the definition of the algorithm.
|
|
The <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition introduces the workhorse of the function:
|
|
<span class="RktSym">clever-gcd</span>. Its first <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> line discovers the trivial
|
|
case by comparing <span class="RktSym">smaller</span> to <span class="RktVal">0</span> and produces the matching
|
|
solution. The generative step uses <span class="RktSym">smaller</span> as the new first
|
|
argument and <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span><span class="stt"> </span><span class="RktSym">large</span><span class="stt"> </span><span class="RktSym">small</span><span class="RktPn">)</span> as the new second argument
|
|
to <span class="RktSym">clever-gcd</span>.</p><p><div class="SIntrapara">If we now use <span class="RktSym">gcd-generative</span> with our above example,
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">gcd-generative</span><span class="hspace"> </span><span class="RktVal">101135853</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">we see that the response is nearly instantaneous. A hand-evaluation shows
|
|
that <span class="RktSym">clever-gcd</span> recurs only nine times before it produces the
|
|
solution:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">101135853</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="hspace"> </span><span class="RktVal">11106573</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">11106573</span><span class="hspace"> </span><span class="RktVal">588348</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">588348</span><span class="hspace"> </span><span class="RktVal">516309</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">516309</span><span class="hspace"> </span><span class="RktVal">72039</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">72039</span><span class="hspace"> </span><span class="RktVal">12036</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">12036</span><span class="hspace"> </span><span class="RktVal">11859</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">11859</span><span class="hspace"> </span><span class="RktVal">177</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">clever-gcd</span><span class="hspace"> </span><span class="RktVal">177</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This also means that it checks only nine <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remainder%29%29" class="RktValLink" data-pltdoc="x">remainder</a></span> conditions,
|
|
clearly a much smaller effort than <span class="RktSym">gcd-structural</span> expends.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agcd-gen-time))"></a><span style="font-weight: bold">Exercise</span> 440. Copy <span class="RktSym">gcd-generative</span> into the
|
|
definitions area of DrRacket and evaluate
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._time%29%29" class="RktStxLink" data-pltdoc="x">time</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-generative</span><span class="hspace"> </span><span class="RktVal">101135853</span><span class="hspace"> </span><span class="RktVal">45014640</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">in the interactions area. <a href="part_five.html#%28counter._%28exercise._ex~3agcd-gen-time%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>You may now think that generative recursion design has discovered a much
|
|
faster solution to the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._gcd%29%29" class="RktValLink" data-pltdoc="x">gcd</a></span> problem, and you may conclude that
|
|
generative recursion is always the right way to go. This judgment is too
|
|
rash for three reasons. First, even a well-designed algorithm isn’t always
|
|
faster than an equivalent structurally recursive function. For example,
|
|
<span class="RktSym">quick-sort<</span> wins only for large lists; for small ones, the standard
|
|
<span class="RktSym">sort<</span> function is faster. Worse, a badly designed algorithm can
|
|
wreak havoc on the performance of a program. Second, it is typically easier
|
|
to design a function using the recipe for structural recursion. Conversely,
|
|
designing an algorithm requires an idea of how to generate new problems, a
|
|
step that often requires some deep insight. Finally, programmers who read
|
|
functions can easily understand structurally recursive functions, even
|
|
without much documentation. The generative step of an algorithm, though, is
|
|
based on a “eureka!” and, without a good explanation, is difficult to
|
|
understand for future readers—<wbr></wbr>and that includes older versions of
|
|
yourself.</p><p>Experience shows that most functions in a program employ structural design;
|
|
only a few exploit generative recursion. When we encounter a situation
|
|
where a design could use the recipe for either structural or generative
|
|
recursion, the best approach is to start with a structural version. If the
|
|
result turns out to be too slow for the task at hand—<wbr></wbr>and only then—<wbr></wbr>it
|
|
is time to explore the use of generative recursion.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aquick-sort-time1))"></a><span style="font-weight: bold">Exercise</span> 441. Evaluate
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">14</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal">14</span><span class="hspace"> </span><span class="RktVal">16</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">by hand. Show only those lines that introduce a new recursive call to
|
|
<span class="RktSym">quick-sort<</span>. How many recursive applications of <span class="RktSym">quick-sort<</span>
|
|
are required? How many recursive applications of the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span> function? Suggest a
|
|
general rule for a list of length <span class="RktSym">n</span>.</div></p><p><div class="SIntrapara">Evaluate
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">quick-sort<</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">11</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">13</span><span class="hspace"> </span><span class="RktVal">14</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">by hand. How many recursive applications of <span class="RktSym">quick-sort<</span> are
|
|
required? How many recursive applications of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span>? Does this
|
|
contradict the first part of the exercise? <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-time1%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3aquick-sort-time2))"></a><span style="font-weight: bold">Exercise</span> 442. Add <span class="RktSym">sort<</span> and
|
|
<span class="RktSym">quick-sort<</span> to the definitions area. Run tests on the functions to
|
|
ensure that they work on basic examples. Also develop
|
|
<span class="RktSym">create-tests</span>, a function that creates large test cases randomly.
|
|
Then explore how fast each works on various lists.</p><p>Does the experiment confirm the claim that the plain <span class="RktSym">sort<</span>
|
|
function often wins over <span class="RktSym">quick-sort<</span> for short lists
|
|
and vice versa?</p><p>Determine the cross-over point. Use it to build a <span class="RktSym">clever-sort</span>
|
|
function that behaves like <span class="RktSym">quick-sort<</span> for large lists and like
|
|
<span class="RktSym">sort<</span> for lists below this cross-over point. Compare with
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-switch%29%29" data-pltdoc="x">exercise 427</a>. <a href="part_five.html#%28counter._%28exercise._ex~3aquick-sort-time2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agcd-structural1))"></a><span style="font-weight: bold">Exercise</span> 443. Given the header material for
|
|
<span class="RktSym">gcd-structural</span>, a naive use of the design recipe might use the
|
|
following template or some variant: <a name="(idx._(gentag._639))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Why is it impossible to find a divisor with this strategy? <a href="part_five.html#%28counter._%28exercise._ex~3agcd-structural1%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3agcd-structural2))"></a><span style="font-weight: bold">Exercise</span> 444. <a href="part_five.html#%28counter._%28exercise._ex~3agcd-structural1%29%29" data-pltdoc="x">Exercise 443</a> means that the
|
|
design for <span class="RktSym">gcd-structural</span> calls for some planning and a
|
|
design-by-composition approach.</p><p><div class="SIntrapara">The very explanation of “greatest common denominator” suggests a
|
|
two-stage approach. First design a function that can compute the
|
|
list<span class="refelem"><span class="refcolumn"><span class="refcontent">Ideally, you should use sets not lists.</span></span></span> of divisors of a
|
|
natural number. Second, design a function that picks the largest common
|
|
number in the list of divisors of <span class="RktSym">n</span> and the list of divisors of
|
|
<span class="RktSym">m</span>. The overall function would look like this: <a name="(idx._(gentag._640))"></a>
|
|
<a name="(idx._(gentag._641))"></a>
|
|
<a name="(idx._(gentag._642))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gcd-structural</span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largest-common</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">divisors</span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktSym">S</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">divisors</span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 1] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 1] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes the divisors of </span><span class="RktSym">l</span><span class="RktCmt"> smaller or equal to </span><span class="RktSym">k</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">divisors</span><span class="hspace"> </span><span class="RktSym">k</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">] [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">] -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds the largest number common to both </span><span class="RktSym">k</span><span class="RktCmt"> and </span><span class="RktSym">l</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">largest-common</span><span class="hspace"> </span><span class="RktSym">k</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Why do you think <span class="RktSym">divisors</span> consumes two numbers? Why does it
|
|
consume <span class="RktSym">S</span> as the first argument in both uses? <a href="part_five.html#%28counter._%28exercise._ex~3agcd-structural2%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h3>27<tt> </tt><a name="(part._ch~3agen-rec-samples)"></a>Variations on the Theme</h3><p>The design of an algorithm starts with an informal description of a process
|
|
of how to create a problem that is more easily solvable than the given one
|
|
and whose solution contributes to the solution of the given problem. Coming
|
|
up with this kind of idea requires inspiration, immersion in an application
|
|
domain, and experience with many different kinds of examples.</p><p>This chapter presents several illustrative examples of algorithms. Some are
|
|
directly drawn from mathematics, which is the source of many ideas; others
|
|
come from computational settings. The first example is a graphical
|
|
illustration of our principle: the Sierpinski triangle. The second one
|
|
explains the divide-and-conquer principle with the simple mathematical
|
|
example of finding the root of a function. It then shows how to turn this
|
|
idea into a fast algorithm for searching sequences, a widely used
|
|
application. The third section concerns “parsing” of sequences of
|
|
<a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s, also a common problem in real-world programming.</p><h4>27.1<tt> </tt><a name="(part._sec~3afractal)"></a>Fractals, a First Taste</h4><p>Fractals play an important role in computational geometry. Flake writes in <span style="font-style: italic">The
|
|
Computational Beauty of Nature</span> (The MIT Press, 1998) that
|
|
“geometry can be extended to account for objects with a fractional
|
|
dimension. Such objects, known as <span style="font-style: italic">fractals</span>,
|
|
come very close to capturing the richness and variety of forms found in
|
|
nature. Fractals possess structural self-similarity on multiple ...
|
|
scales, meaning that a piece of a fractal will often look like the whole.”</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_181.png" alt="image" width="390" height="355.7025033688162"/><span class="hspace"> </span><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_182.png" alt="image" width="40" height="35.71281292110203"/><span class="hspace"> </span><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_183.png" alt="image" width="42" height="37.71281292110203"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asiepic))" x-target-lift="Figure"></a>Figure 156: </span>The Sierpinski triangle</span></p></blockquote><p><a href="part_five.html#%28counter._%28figure._fig~3asiepic%29%29" data-pltdoc="x">Figure <span class="FigureRef">156</span></a> displays an example of a fractal shape, known as
|
|
the Sierpinski triangle. The basic shape is an (equilateral) triangle, like
|
|
the one in the center. When this triangle is composed sufficiently many
|
|
times in a triangular fashion, we get the left-most shape.</p><p>The right-most image in <a href="part_five.html#%28counter._%28figure._fig~3asiepic%29%29" data-pltdoc="x">figure <span class="FigureRef">156</span></a> explains the generative
|
|
step. When taken by itself, it says that, given a triangle, find the
|
|
midpoint of each side and connect them to each other. This step yields four
|
|
triangles; repeat the process for each of the outer of these three
|
|
triangles unless these triangles are too small.</p><p><div class="SIntrapara">An alternative explanation, well suited for the shape composition
|
|
functions in <span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/image</span></span> teachpack</span>,<span class="refelem"><span class="refcolumn"><span class="refcontent">We owe this solution to Marc Smith.</span></span></span> is
|
|
based on the transition from the image in the center to the image on the
|
|
right. By juxtaposing two of the center triangles and then placing one copy
|
|
above these two, we also get the shape on the right:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_184.png" alt="image" width="47" height="42"/></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_185.png" alt="image" width="87" height="42"/></p></td></tr><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s-triangle</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_186.png" alt="image" width="87" height="76"/></p></td></tr></table></blockquote></div></p><p>This section uses the alternative description to design the Sierpinski
|
|
algorithm; <a href="part_six.html#%28part._sec~3afractal-acc%29" data-pltdoc="x">Accumulators as Results</a> deals with the first description. Given
|
|
that the goal is to generate the image of an equilateral triangle, we
|
|
encode the problem with a (positive) number, the length of the triangle’s
|
|
side. This decision yields a signature, a purpose statement, and a header:</p><p><div class="SIntrapara"><a name="(idx._(gentag._643))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates Sierpinski triangle of size </span><span class="RktSym">side</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sierpinski</span><span class="hspace"> </span><span class="RktSym">side</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._triangle%29%29" class="RktValLink" data-pltdoc="x">triangle</a></span><span class="hspace"> </span><span class="RktSym">side</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">outline</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Now it is time to address the four questions of generative recursion:
|
|
</div><div class="SIntrapara"><ul><li><p>When the given number is so small that drawing triangles inside of it
|
|
is pointless, the problem is trivial.</p></li><li><p>In that case, it suffices to generate a triangle.</p></li><li><p>Otherwise, the algorithm must generate a Sierpinski triangle of size
|
|
<span style="font-style: italic">side / </span>2<span style="font-style: italic"></span> because juxtaposing two such triangles in either direction
|
|
yields one of size <span style="font-style: italic">side</span>.</p></li><li><p><div class="SIntrapara">If <span class="RktSym">half-sized</span> is the Sierpinski triangle of size
|
|
<span style="font-style: italic">side / </span>2<span style="font-style: italic"></span>, then
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span><span class="hspace"> </span><span class="RktSym">half-sized</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">is a Sierpinski triangle of size <span style="font-style: italic">side</span>.</div></p></li></ul></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._644))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">SMALL</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">a size measure in terms of pixels </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">small-triangle</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._triangle%29%29" class="RktValLink" data-pltdoc="x">triangle</a></span><span class="hspace"> </span><span class="RktSym">SMALL</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">outline</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> creates Sierpinski Δ of size </span><span class="RktSym">side</span><span class="RktMeta"></span><span class="RktCmt"> by generating</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">one for </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2F%29%29" class="RktValLink" data-pltdoc="x">/</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">side</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="RktCmt"> and placing one copy above two copies</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sierpinski</span><span class="hspace"> </span><span class="RktSym">SMALL</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">small-triangle</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sierpinski</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">SMALL</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span><span class="hspace"> </span><span class="RktSym">small-triangle</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktSym">small-triangle</span><span class="hspace"> </span><span class="RktSym">small-triangle</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sierpinski</span><span class="hspace"> </span><span class="RktSym">side</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym">side</span><span class="hspace"> </span><span class="RktSym">SMALL</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._triangle%29%29" class="RktValLink" data-pltdoc="x">triangle</a></span><span class="hspace"> </span><span class="RktSym">side</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">outline</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sierpinski</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2F%29%29" class="RktValLink" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktSym">side</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="hspace"> </span><span class="RktSym">half-sized</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asierpinski-code))" x-target-lift="Figure"></a>Figure 157: </span>The Sierpinski algorithm</span></p></blockquote></div></p><p>With these answers, it is straightforward to define the function.
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asierpinski-code%29%29" data-pltdoc="x">Figure <span class="FigureRef">157</span></a> spells out the details. The “triviality
|
|
condition” translates to <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktSym">side</span><span class="stt"> </span><span class="RktSym">SMALL</span><span class="RktPn">)</span> for some constant
|
|
<span class="RktSym">SMALL</span>. For the trivial answer, the function returns a triangle of
|
|
the given size. In the recursive case, a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> expression
|
|
introduces the name <span class="RktSym">half-sized</span> for the Sierpinski triangle that is
|
|
half as big as the specified size. Once the recursive call has generated
|
|
the small Sierpinski triangle, it composes this image via <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span>
|
|
and <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span>.</p><p><div class="SIntrapara">The figure highlights two other points. First, the purpose statement is
|
|
articulated as an explanation of <span style="font-weight: bold">what</span> the function accomplishes
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates Sierpinski triangle of size </span><span class="RktSym">side</span><span class="RktMeta"></span><span class="RktCmt"> by </span>...</p></blockquote></div><div class="SIntrapara">and <span style="font-weight: bold">how</span> it accomplishes this goal:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span>...<span class="RktCmt"> generating one of size </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2F%29%29" class="RktValLink" data-pltdoc="x">/</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">side</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="RktCmt"> and </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">placing one copy above two composed copies</span></td></tr></table></blockquote></div><div class="SIntrapara">Second, the examples illustrate the two possible cases: one if the given
|
|
size is small enough, and one for a size that is too large still. In the
|
|
latter case, the expression that computes the expected value explains
|
|
exactly the meaning of the purpose statement.</div></p><p>Since <span class="RktSym">sierpinski</span> is based on generative recursion, defining the
|
|
function and testing it is not the last step. We must also consider why the
|
|
algorithm terminates for any given legal input. The input of
|
|
<span class="RktSym">sierpinski</span> is a single positive number. If the number is smaller
|
|
than <span class="RktSym">SMALL</span>, the algorithm terminates. Otherwise, the recursive
|
|
call uses a number that is half as large as the given one. Hence, the
|
|
algorithm must terminate for all positive <span class="RktSym">side</span>s, assuming
|
|
<span class="RktSym">SMALL</span> is positive, too.</p><p>One view of the Sierpinski process is that it divides its problem in half
|
|
until it is immediately solvable. With a little imagination, you can see
|
|
that the process can be used to search for numbers with certain
|
|
properties. The next section explains this idea in detail.</p><h4>27.2<tt> </tt><a name="(part._sec~3abinary-search)"></a>Binary Search</h4><p><div class="SIntrapara">Applied mathematicians model the real world with nonlinear equations
|
|
and then try to solve them. Specifically, they translate problems into a
|
|
function <span style="font-style: italic">f</span> from numbers to numbers and look for some number <span style="font-style: italic">r</span>
|
|
such that
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">f</span>(<span style="font-style: italic">r</span>)<span style="font-style: italic"> = </span>0<span style="font-style: italic"></span>.</p></blockquote></div><div class="SIntrapara">The value <span style="font-style: italic">r</span> is called the <span style="font-style: italic">root</span> of <span style="font-style: italic">f</span>.</div></p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img src="pict_187.png" alt="image" width="400" height="400"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aroot))" x-target-lift="Figure"></a>Figure 158: </span>A numeric function <span style="font-style: italic">f</span> with root in interval <span style="font-style: italic"></span>[<span style="font-style: italic">a,b</span>]<span style="font-style: italic"></span> (stage 1)</span></p></blockquote><p><div class="SIntrapara">Here is a problem from the physical domain:
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> A rocket is flying at the constant speed of <span style="font-style: italic">v</span> miles
|
|
per hour on a straight line toward some target, <span style="font-style: italic">d</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span> miles away. It
|
|
then accelerates at the rate of <span style="font-style: italic">a</span> miles per hour squared for
|
|
<span style="font-style: italic">t</span> hours. When will it hit its target?</p></blockquote></div><div class="SIntrapara">Physics tells us that the distance covered is the following function of
|
|
time:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">d</span>(<span style="font-style: italic">t</span>)<span style="font-style: italic"> = </span>(<span style="font-style: italic">v * t + </span>1<span style="font-style: italic">/</span>2<span style="font-style: italic"> * a * t</span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span></p></blockquote></div><div class="SIntrapara">The question of when it hits the target asks us to find the time <span style="font-style: italic">t</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span>
|
|
such that the object reaches the desired goal:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">d</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"> = </span>(<span style="font-style: italic">v * t</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"> + </span>1<span style="font-style: italic">/</span>2<span style="font-style: italic"> * a * t</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span></p></blockquote></div><div class="SIntrapara">From algebra we know that this is a quadratic equation and that it is
|
|
possible to solve such equations if <span style="font-style: italic">d</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span>, <span style="font-style: italic">a</span>, and <span style="font-style: italic">v</span>
|
|
satisfy certain conditions.</div></p><p>Generally such problems call for more complexity than quadratic
|
|
equations. In response, mathematicians have spent the last few centuries
|
|
developing root-finding methods for different types of functions. In this
|
|
section, we study a solution that is based on the <span style="font-style: italic">Intermediate Value
|
|
Theorem</span> (IVT), an early result of analysis. The resulting algorithm
|
|
is a primary example of generative recursion based on a mathematical
|
|
theorem. Computer scientists have generalized it to the <span style="font-style: italic">binary
|
|
search</span> algorithm.</p><p>The Intermediate Value Theorem says that a continuous function <span style="font-style: italic">f</span> has
|
|
a root in an interval <span style="font-style: italic"></span>[<span style="font-style: italic">a,b</span>]<span style="font-style: italic"></span> if <span style="font-style: italic">f</span>(<span style="font-style: italic">a</span>)<span style="font-style: italic"></span> and <span style="font-style: italic">f</span>(<span style="font-style: italic">b</span>)<span style="font-style: italic"></span> are on
|
|
opposite sides of the x-axis. By <span style="font-style: italic">continuous</span> we mean a
|
|
function that doesn’t “jump,” that doesn’t have gaps, and that proceeds
|
|
on a “smooth” path.</p><p><a href="part_five.html#%28counter._%28figure._fig~3aroot%29%29" data-pltdoc="x">Figure <span class="FigureRef">158</span></a> illustrates the Intermediate Value Theorem. The
|
|
function <span style="font-style: italic">f</span> is a continuous function, as suggested by the
|
|
uninterrupted, smooth graph. It is below the x-axis at <span style="font-style: italic">a</span> and above
|
|
at <span style="font-style: italic">b</span>, and
|
|
indeed, it intersects the x-axis somewhere in this interval, labeled
|
|
“range 1” in the figure.</p><p><div class="SIntrapara">Now take a look at the midpoint between <span style="font-style: italic">a</span> and <span style="font-style: italic">b</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">m = </span>(<span style="font-style: italic">a+b</span>)<span style="font-style: italic"> / </span>2<span style="font-style: italic"></span></p></blockquote></div><div class="SIntrapara">It partitions the interval <span style="font-style: italic"></span>[<span style="font-style: italic">a,b</span>]<span style="font-style: italic"></span> into two smaller, equally sized
|
|
intervals. We can now compute the value of <span style="font-style: italic">f</span> at <span style="font-style: italic">m</span> and see whether it is
|
|
below <span style="font-style: italic"></span>0<span style="font-style: italic"></span> or above. Here <span style="font-style: italic">f</span>(<span style="font-style: italic">m</span>)<span style="font-style: italic"> > </span>0<span style="font-style: italic"></span>, so, according to the Intermediate Value Theorem,
|
|
the root is in the left interval: <span style="font-style: italic"></span>[<span style="font-style: italic">a,m</span>]<span style="font-style: italic"></span>. Our picture confirms this
|
|
because the root is in the left half of the interval, labeled “range 2”
|
|
in <a href="part_five.html#%28counter._%28figure._fig~3aroot%29%29" data-pltdoc="x">figure <span class="FigureRef">158</span></a>.</div></p><p><div class="SIntrapara">We now have a description of the key step in the root-finding process.
|
|
Next, we translate this description into an ISL+ algorithm. Our
|
|
first task is to state its purpose. Clearly the
|
|
algorithm consumes a function and the boundaries of the interval in which
|
|
we expect to find a root: <a name="(idx._(gentag._645))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span>...</td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The three parameters can’t be just any function and numbers. For
|
|
<span class="RktSym">find-root</span> to work, we must assume that the following holds:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">that is, <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> and <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span> must be on opposite sides
|
|
of the x-axis.</div></p><p><div class="SIntrapara">Next we need to fix the function’s result and formulate a purpose
|
|
statement. Simply put, <span class="RktSym">find-root</span> finds an interval that contains a
|
|
root. The search divides the interval until its size, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">right</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span>, is tolerably small, say, smaller than some constant
|
|
<span class="RktSym">ε</span>.<span class="refelem"><span class="refcolumn"><span class="refcontent">DrRacket allows the use of Greek
|
|
symbols such as <span class="RktSym">ε</span>. But you can also write <span class="RktSym">EPSILON</span>
|
|
instead.</span></span></span> At that point, the function could produce one of three
|
|
results: the left boundary, the right one, or a representation of the
|
|
interval. Any one of them completely identifies the interval, and since it
|
|
is simpler to return numbers, we pick the left boundary. Here is the
|
|
complete header material:<a name="(idx._(gentag._646))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines </span><span class="RktSym">R</span><span class="RktCmt"> such that </span><span class="RktSym">f</span><span class="RktCmt"> has a root in [</span><span class="RktSym">R</span><span class="RktCmt">,</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktSym">R</span><span class="stt"> </span><span class="RktSym">ε</span><span class="RktPn">)</span><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> </span><span class="RktSym">f</span><span class="RktCmt"> is continuous </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">(2) </span><span class="Smaller"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> divides interval in half, the root is in </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">one of the two halves, picks according to (2)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3afind-root-example))"></a><span style="font-weight: bold">Exercise</span> 445. Consider the following function definition:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It defines a binomial for which we can determine its roots by hand:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">0</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">0</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Use <span class="RktSym">poly</span> to formulate a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-satisfied%29%29" class="RktStxLink" data-pltdoc="x">check-satisfied</a></span> test for <span class="RktSym">find-root</span>. <a name="(idx._(gentag._647))"></a></div></p><p><div class="SIntrapara">Also use <span class="RktSym">poly</span> to illustrate the root-finding process. Start with
|
|
the interval <span style="font-style: italic"></span>[<span style="font-style: italic"></span>3<span style="font-style: italic">,</span>6<span style="font-style: italic"></span>]<span style="font-style: italic"></span> and tabulate the information as follows for
|
|
<span style="font-style: italic">ε = </span>0<span style="font-style: italic"></span>:
|
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td style="border-bottom: 1px solid black;"><p><span style="font-style: italic">step</span></p></td><td style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">left</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">f left</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">right</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">f right</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">mid</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">f mid</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;" colspan="3"><p></p></td></tr><tr><td><p><span style="font-style: italic">n=</span>1<span style="font-style: italic"></span></p></td><td><p><span class="hspace"> </span></p></td><td align="right"><p>3</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>-1</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>6.00</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>8.00</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4.50</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1.25</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right" colspan="3"><p> </p></td></tr><tr><td><p><span style="font-style: italic">n=</span>2<span style="font-style: italic"></span></p></td><td><p><span class="hspace"> </span></p></td><td align="right"><p>3</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>-1</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4.50</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1.25</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>?</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>?</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right" colspan="3"><p></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Our next task is to address the four questions of algorithm design:
|
|
</div><div class="SIntrapara"><ol><li><p><div class="SIntrapara">We need a condition that describes when the problem is solved and a
|
|
matching answer. Given our discussion so far, this is straightforward:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">right</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></p></blockquote></div></p></li><li><p>The matching result in the trivial case is <span class="RktSym">left</span>.</p></li><li><p><div class="SIntrapara">For the generative case, we need an expression that generates new
|
|
problems for <span class="RktSym">find-root</span>. According to our informal description,
|
|
this step requires determining the midpoint and its function value:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">mid</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2F%29%29" class="RktValLink" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bed8fed3">[email protected]</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The midpoint is then used to pick the next interval. Following
|
|
IVT, the interval <span style="font-style: italic"></span>[<span style="font-style: italic">left,mid</span>]<span style="font-style: italic"></span> is the next candidate if
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="294f6944">[email protected]</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cbad8ba6">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">while <span style="font-style: italic"></span>[<span style="font-style: italic">mid,right</span>]<span style="font-style: italic"></span> is used for the recursive call if
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e284a28f">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1f795f72">[email protected]</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Translated into code, the body of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> must be a conditional:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b6d0f6db">[email protected]</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5b3d1b36">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d8be98b5">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9bfddbf6">[email protected]</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">In both clauses, we use <span class="RktSym">find-root</span> to continue the search.</div></p></li><li><p>The answer to the final question is obvious. Since the recursive call
|
|
to <span class="RktSym">find-root</span> finds the root of <span class="RktSym">f</span>, there is nothing else
|
|
to do.</p></li></ol></div><div class="SIntrapara">The completed function is displayed in <a href="part_five.html#%28counter._%28figure._fig~3aroot-of-f%29%29" data-pltdoc="x">figure <span class="FigureRef">159</span></a>; the
|
|
following exercises elaborate on its design.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._648))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines </span><span class="RktSym">R</span><span class="RktCmt"> such that </span><span class="RktSym">f</span><span class="RktCmt"> has a root in [</span><span class="RktSym">R</span><span class="RktCmt">,</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktSym">R</span><span class="stt"> </span><span class="RktSym">ε</span><span class="RktPn">)</span><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> </span><span class="RktSym">f</span><span class="RktCmt"> is continuous </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> divides interval in half, the root is in one of the two</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">halves, picks according to assumption </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">right</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">mid</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2F%29%29" class="RktValLink" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c5a385a8aca1">[email protected]</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="93f5d3fefaf7">[email protected]</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0a680ada9a4">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="94f2d4f9fdf0">[email protected]</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktSym"><a href="https://htdp.org/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b8def8d5d1dc">[email protected]</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-root</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">mid</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aroot-of-f))" x-target-lift="Figure"></a>Figure 159: </span>The <span style="font-style: italic">find-root</span> algorithm</span></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3afind-root-test))"></a><span style="font-weight: bold">Exercise</span> 446. Add the test from
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3afind-root-example%29%29" data-pltdoc="x">exercise 445</a> to the program in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3aroot-of-f%29%29" data-pltdoc="x">figure <span class="FigureRef">159</span></a>. Experiment with different values for
|
|
<span class="RktSym">ε</span>. <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-test%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afind-root-test2))"></a><span style="font-weight: bold">Exercise</span> 447. The <span class="RktSym">poly</span> function has two
|
|
roots. Use <span class="RktSym">find-root</span> with <span class="RktSym">poly</span> and an interval that
|
|
contains both roots. <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-test2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afind-root-termination))"></a><span style="font-weight: bold">Exercise</span> 448. The <span class="RktSym">find-root</span> algorithm
|
|
terminates for all (continuous) <span class="RktSym">f</span>, <span class="RktSym">left</span>, and
|
|
<span class="RktSym">right</span> for which the assumption holds. Why? Formulate a termination
|
|
argument.</p><p><span style="font-weight: bold">Hint</span> Suppose the arguments of <span class="RktSym">find-root</span> describe an interval of
|
|
size <span class="RktSym">S1</span>. How large is the distance between <span class="RktSym">left</span> and
|
|
<span class="RktSym">right</span> for the first and second recursive call to
|
|
<span class="RktSym">find-root</span>? After how many steps is <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">right</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> smaller
|
|
than or equal to <span class="RktSym">ε</span>? <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-termination%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afind-root-locals))"></a><span style="font-weight: bold">Exercise</span> 449. As presented in <a href="part_five.html#%28counter._%28figure._fig~3aroot-of-f%29%29" data-pltdoc="x">figure <span class="FigureRef">159</span></a>,
|
|
<span class="RktSym">find-root</span> computes the value of <span class="RktSym">f</span> for each boundary value
|
|
twice to generate the next interval. Use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> to avoid this recomputation.</p><p>In addition, <span class="RktSym">find-root</span> recomputes the value of a boundary across
|
|
recursive calls. For example, <span class="RktPn">(</span><span class="RktSym">find-root</span><span class="stt"> </span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span> computes
|
|
<span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> and, if <span style="font-style: italic"></span>[<span style="font-style: italic">left,mid</span>]<span style="font-style: italic"></span> is chosen as the next interval,
|
|
<span class="RktSym">find-root</span> computes <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> again. Introduce a helper function
|
|
that is like <span class="RktSym">find-root</span> but consumes not only <span class="RktSym">left</span> and
|
|
<span class="RktSym">right</span> but also <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> and <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">right</span><span class="RktPn">)</span> at each
|
|
recursive stage.</p><p>How many recomputations of <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">left</span><span class="RktPn">)</span> does this design maximally avoid?
|
|
<span style="font-weight: bold">Note</span> The two additional arguments to this helper function change at each
|
|
recursive stage, but the change is related to the change in the numeric
|
|
arguments. These arguments are so-called <span style="font-style: italic">accumulators</span>, which are the
|
|
topic of <a href="part_six.html" data-pltdoc="x">Accumulators</a>. <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-locals%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afind-root-monotonic))"></a><span style="font-weight: bold">Exercise</span> 450. A function <span class="RktSym">f</span> is
|
|
<span style="font-style: italic">monotonically increasing</span> if <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span> holds
|
|
whenever <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c%29%29" class="RktValLink" data-pltdoc="x"><</a></span><span class="stt"> </span><span class="RktSym">a</span><span class="stt"> </span><span class="RktSym">b</span><span class="RktPn">)</span> holds. Simplify <span class="RktSym">find-root</span> assuming the
|
|
given function is not only continuous but also monotonically increasing. <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-monotonic%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3afind-root-discrete))"></a><span style="font-weight: bold">Exercise</span> 451. A table is a structure of two fields:
|
|
the natural number <span class="RktSym">length</span> and a function
|
|
<span class="RktSym">array</span>,<span class="refelem"><span class="refcolumn"><span class="refcontent">Many programming languages, including Racket,
|
|
support arrays and vectors, which are similar to tables.</span></span></span> which consumes
|
|
natural numbers and, for those between <span class="RktVal">0</span> and <span class="RktSym">length</span>
|
|
(exclusive), produces answers:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">table</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">array</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._table)"></a><span style="font-style: italic">Table</span><span class="RktCmt"> is a structure:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-table</span><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><span class="RktPn">[</span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><span class="RktSym"><span class="nobreak">-></span></span><span class="stt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Since this data structure is somewhat unusual, it is critical to
|
|
illustrate it with examples:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">table1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-table</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a2</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._pi%29%29" class="RktValLink" data-pltdoc="x">pi</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">"table2 is not defined for i =!= 0"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">table2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-table</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktSym">a2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Here <span class="RktSym">table1</span>’s array function is defined for more inputs than its length
|
|
field allows; <span class="RktSym">table2</span> is defined for just one input, namely
|
|
<span class="RktVal">0</span>. Finally, we also define a useful function for looking up values
|
|
in tables: <a name="(idx._(gentag._649))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._table%29" class="techoutside" data-pltdoc="x"><span class="techinside">Table</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">looks up the </span><span class="RktSym">i</span><span class="RktCmt">th value in </span><span class="RktSym">array</span><span class="RktCmt"> of </span><span class="RktSym">t</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="hspace"> </span><span class="RktSym">t</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym">table-array</span><span class="hspace"> </span><span class="RktSym">t</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p>The root of a table <span class="RktSym">t</span> is a number in <span class="RktPn">(</span><span class="RktSym">table-array</span><span class="stt"> </span><span class="RktSym">t</span><span class="RktPn">)</span> that is
|
|
close to <span class="RktVal">0</span>. A <span style="font-style: italic">root index</span> is a natural number <span class="RktSym">i</span>
|
|
such that <span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="stt"> </span><span class="RktSym">t</span><span class="stt"> </span><span class="RktSym">i</span><span class="RktPn">)</span> is a root of table <span class="RktSym">t</span>.
|
|
A table <span class="RktSym">t</span> is monotonically increasing if <span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="stt"> </span><span class="RktSym">t</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span>
|
|
is less than <span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="stt"> </span><span class="RktSym">t</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span>, <span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="stt"> </span><span class="RktSym">t</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span> is less
|
|
than <span class="RktPn">(</span><span class="RktSym">table-ref</span><span class="stt"> </span><span class="RktSym">t</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span>, and so on.</p><p>Design <span class="RktSym">find-linear</span>. The function consumes a monotonically
|
|
increasing table and finds the smallest index for a root of the table. Use
|
|
the structural recipe for <a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a>, proceeding from <span class="RktVal">0</span> through
|
|
<span class="RktVal">1</span>, <span class="RktVal">2</span>, and so on to the <span class="RktSym">array-length</span> of the given
|
|
table. This kind of root-finding process is often called a <span style="font-style: italic">linear
|
|
search</span>.</p><p>Design <span class="RktSym">find-binary</span>, which also finds the smallest index for the root
|
|
of a monotonically increasing table but uses generative recursion to do so. Like ordinary
|
|
binary search, the algorithm narrows an interval down to the smallest possible
|
|
size and then chooses the index. Don’t forget to formulate a termination
|
|
argument.</p><p><span style="font-weight: bold">Hint</span> The key problem is that a table index is a <span style="font-weight: bold">natural</span> number,
|
|
not a plain number. Hence the interval boundary arguments for <span class="RktSym">find</span>
|
|
must be natural numbers. Consider how this observation changes
|
|
(1) the nature of trivially solvable problem instances,
|
|
(2) the midpoint computation,
|
|
(3) and the decision as to which interval to generate next.
|
|
To make this concrete, imagine a table with 1024 slots and the root at
|
|
1023. How many calls to <span class="RktSym">find</span> are needed in
|
|
<span class="RktSym">find-linear</span> and <span class="RktSym">find-binary</span>, respectively? <a href="part_five.html#%28counter._%28exercise._ex~3afind-root-discrete%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>27.3<tt> </tt><a name="(part._sec~3afiles-lines)"></a>A Glimpse at Parsing</h4><p><div class="SIntrapara">As mentioned in <a href="part_four.html#%28part._ch~3afiles%29" data-pltdoc="x">Iterative Refinement</a>, computers come with files, which provide
|
|
a form of permanent memory. From our perspective a <span style="font-style: italic">file</span> is just a
|
|
list of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s,<span class="refelem"><span class="refcolumn"><span class="refcontent">The exact convention differs from one
|
|
operating system to another, but for our purposes this is irrelevant.</span></span></span>
|
|
though interrupted by a special string:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._file)"></a><span style="font-style: italic">File</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">"\n"</span><span class="stt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="stt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> represents the content of a file </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktVal">"\n"</span><span class="RktCmt"> is the newline character </span></td></tr></table></blockquote></div><div class="SIntrapara">The idea is that <a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a>s are broken into lines, where <span class="RktVal">"\n"</span>
|
|
represents the so-called newline character, which indicates the end of a line.
|
|
Let’s also introduce lines before we move on:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._line)"></a><span style="font-style: italic">Line</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">].</span></p></blockquote></div></p><p><div class="SIntrapara">Many functions need to process files as list of lines. The
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-lines%29%29" class="RktValLink" data-pltdoc="x">read-lines</a></span> from <span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/batch-io</span></span> teachpack</span> is one of them. Concretely,
|
|
the function turns the file
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"w"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"y"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"u"</span><span class="hspace"> </span><span class="RktVal">"\n"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"i"</span><span class="hspace"> </span><span class="RktVal">"n"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"?"</span><span class="hspace"> </span><span class="RktVal">"\n"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"n"</span><span class="hspace"> </span><span class="RktVal">"y"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"p"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"s"</span><span class="hspace"> </span><span class="RktVal">"s"</span><span class="hspace"> </span><span class="RktVal">"?"</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">into a list of three lines:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"w"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"y"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"u"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"i"</span><span class="hspace"> </span><span class="RktVal">"n"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"?"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"n"</span><span class="hspace"> </span><span class="RktVal">"y"</span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktVal">"p"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"o"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"e"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"s"</span><span class="hspace"> </span><span class="RktVal">"s"</span><span class="hspace"> </span><span class="RktVal">"?"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Similarly, the file
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">also corresponds to a list of three lines:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! What are the list-of-lines representations for these three cases:
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span>, and <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"\n"</span><span class="stt"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span>? Why are
|
|
these examples important test cases?</div></p><p>The problem of turning a sequence of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s into a list of lines
|
|
is called the <span style="font-style: italic">parsing</span> problem. Many programming languages provide
|
|
functions that retrieve lines, words, numbers, and other kinds of so-called
|
|
tokens from files. But even if they do, it is common that programs need to
|
|
parse these tokens even further. This section provides a glimpse at a
|
|
parsing technique. Parsing is so complex and so central to the creation of
|
|
full-fledged software applications, however, that most undergraduate
|
|
curricula come with at least one course on parsing. So do not think you can
|
|
tackle real parsing problems properly even after mastering this section.</p><p><div class="SIntrapara">We start by stating the obvious—<wbr></wbr>a signature, a purpose statement, one of
|
|
the above examples, and a header—<wbr></wbr>for a function that turns a <a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a>
|
|
into a list of <a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a>s: <a name="(idx._(gentag._650))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">converts a file into a list of lines </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="hspace"> </span><span class="RktVal">"\n"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"\n"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">It is also easy to describe the parsing process, given our experience with
|
|
<a href="part_five.html#%28part._sec~3abundle%29" data-pltdoc="x">Recursion without Structure</a>:
|
|
</div><div class="SIntrapara"><ol><li><p>The problem is trivially solvable if the file is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>.</p></li><li><p>In that case, the file doesn’t contain a line.</p></li><li><p>Otherwise, the file contains at least one <span class="RktVal">"\n"</span> or some other
|
|
<a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>. These items—<wbr></wbr>up to and including the first <span class="RktVal">"\n"</span>,
|
|
if any—<wbr></wbr>must be separated from the rest of the <a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a>. The remainder
|
|
is a new problem of the same kind that <span class="RktSym">file->list-of-lines</span> can
|
|
solve.</p></li><li><p>It then suffices to <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> the initial segment as a single
|
|
line to the list of <a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a>s that result from the rest of the
|
|
<a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a>.</p></li></ol></div><div class="SIntrapara">The four questions suggest a straightforward instantiation of the template
|
|
for generative recursive functions. Because the separation of the initial
|
|
segment from the rest of the file requires a scan of an arbitrarily long
|
|
list of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s, we put two auxiliary functions on our wish list:
|
|
<span class="RktSym">first-line</span>, which collects all <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s up to, but
|
|
excluding, the first occurrence of <span class="RktVal">"\n"</span> or the end of the list; and
|
|
<span class="RktSym">remove-first-line</span>, which removes the very same items that
|
|
<span class="RktSym">first-line</span> collects.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._651))"></a>
|
|
<a name="(idx._(gentag._652))"></a>
|
|
<a name="(idx._(gentag._653))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">converts a file into a list of lines </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">first-line</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">remove-first-line</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktCmt"> -> </span><a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retrieves the prefix of </span><span class="RktSym">afile</span><span class="RktCmt"> up to the first occurrence of </span><span class="RktSym">NEWLINE</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">first-line</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">NEWLINE</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">first-line</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a><span class="RktCmt"> -> </span><a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">drops the suffix of </span><span class="RktSym">afile</span><span class="RktCmt"> behind the first occurrence of </span><span class="RktSym">NEWLINE</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">remove-first-line</span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">NEWLINE</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">remove-first-line</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">NEWLINE</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt"> </span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3afile2list))" x-target-lift="Figure"></a>Figure 160: </span>Translating a file into a list of lines</span></p></blockquote></div></p><p>From here, it is easy to create the rest of the program. In
|
|
<span class="RktSym">file->list-of-lines</span>, the answer in the first clause must be
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> because an empty file does not contain any lines. The answer
|
|
in the second clause must <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> the value of <span class="RktPn">(</span><span class="RktSym">first-line</span><span class="stt"> </span><span class="RktSym">afile</span><span class="RktPn">)</span> onto the value <span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">remove-first-line</span><span class="stt"> </span><span class="RktSym">afile</span><span class="RktPn">)</span><span class="RktPn">)</span>, because the first expression computes the first line and the
|
|
second one computes the rest of the lines. Finally, the auxiliary functions
|
|
traverse their inputs in a structurally recursive manner; their development
|
|
is a straightforward exercise. <a href="part_five.html#%28counter._%28figure._fig~3afile2list%29%29" data-pltdoc="x">Figure <span class="FigureRef">160</span></a> presents the
|
|
complete program code.</p><p><div class="SIntrapara">Here is how <span class="RktSym">file->list-of-lines</span> processes the second test:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="hspace"> </span><span class="RktVal">"\n"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">file->list-of-lines</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"e"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"f"</span><span class="hspace"> </span><span class="RktVal">"g"</span><span class="hspace"> </span><span class="RktVal">"h"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This evaluation is another reminder that the argument of the recursive
|
|
application of <span class="RktSym">file->list-of-lines</span> is almost never the rest of the
|
|
given file. It also shows why this generative recursion is guaranteed to
|
|
terminate for every given <a href="part_five.html#%28tech._file%29" class="techoutside" data-pltdoc="x"><span class="techinside">File</span></a>. Every recursive application consumes
|
|
a list that is shorter than the given one, meaning the recursive process
|
|
stops when the process reaches <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>.</div></p><p><a name="(counter._(exercise._ex~3afile-lines-purpose))"></a><span style="font-weight: bold">Exercise</span> 452. Both <span class="RktSym">first-line</span> and
|
|
<span class="RktSym">remove-first-line</span> are missing purpose statements. Articulate
|
|
proper statements. <a href="part_five.html#%28counter._%28exercise._ex~3afile-lines-purpose%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aparse-words))"></a><span style="font-weight: bold">Exercise</span> 453. Design the function <span class="RktSym">tokenize</span>. It turns
|
|
a <a href="part_five.html#%28tech._line%29" class="techoutside" data-pltdoc="x"><span class="techinside">Line</span></a> into a list of tokens. Here a token is either a
|
|
<a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a> or a <a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a> that consists of lower-case letters and
|
|
nothing else. That is, all white-space <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s are dropped; all
|
|
other non-letters remain as is; and all consecutive letters are bundled
|
|
into “words.” <span style="font-weight: bold">Hint</span> Read up on the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string-whitespace~3f%29%29" class="RktValLink" data-pltdoc="x">string-whitespace?</a></span>
|
|
function. <a href="part_five.html#%28counter._%28exercise._ex~3aparse-words%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3amatrix-gen))"></a><span style="font-weight: bold">Exercise</span> 454. Design <span class="RktSym">create-matrix</span>. The function
|
|
consumes a number <span style="font-style: italic">n</span> and a list of <span style="font-style: italic">n</span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span> numbers. It produces an
|
|
<img src="pict_188.png" alt="image" width="30" height="7"/> matrix, for example:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-matrix</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Make up a second example. <a href="part_five.html#%28counter._%28exercise._ex~3amatrix-gen%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h3>28<tt> </tt><a name="(part._ch~3agen-rec-math)"></a>Mathematical Examples</h3><p>Many solutions to mathematical problems employ generative recursion. A
|
|
future programmer must get to know such solutions for two reasons. On the one
|
|
hand, a fair number of programming tasks are essentially about turning
|
|
these kinds of mathematical ideas into programs. On the other hand,
|
|
practicing with such mathematical problems often proves inspirational for
|
|
the design of algorithms. This chapter deals with three such problems.</p><h4>28.1<tt> </tt><a name="(part._sec~3anewton)"></a>Newton’s Method</h4><p><a href="part_five.html#%28part._sec~3abinary-search%29" data-pltdoc="x">Binary Search</a> introduces one method for finding the root of a
|
|
mathematical function. As the exercises in the same section sketch, the method
|
|
naturally generalizes to computational problems, such as finding certain
|
|
values in tables, vectors, and arrays. In mathematical applications,
|
|
programmers tend to employ methods that originate from analytical
|
|
mathematics. A prominent one is due to Newton. Like binary search, the
|
|
so-called <span style="font-style: italic">Newton method</span> repeatedly improves an approximation to the
|
|
root until it is “close enough.” Starting from a guess, say, <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>, the
|
|
essence of the process is to construct the tangent of <span style="font-style: italic">f</span> at <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>
|
|
and to determine its root. While the tangent approximates the function, it is
|
|
also straightforward to determine its root. By repeating this process
|
|
sufficiently often,<span class="refelem"><span class="refcolumn"><span class="refcontent">Newton proved this fact.</span></span></span> an algorithm can
|
|
find a root <span style="font-style: italic">r</span> for which <span style="font-style: italic"></span>(<span style="font-style: italic">f r</span>)<span style="font-style: italic"></span> is close enough to <span style="font-style: italic"></span>0<span style="font-style: italic"></span>.</p><p><div class="SIntrapara">Clearly, this process relies on two pieces of domain knowledge about
|
|
tangents: their slopes and roots. Informally, a tangent of <span style="font-style: italic">f</span> at some
|
|
point <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span> is the line that goes through the point <span style="font-style: italic"></span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic">, f</span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span>
|
|
and has the same slope as <span style="font-style: italic">f</span>. One mathematical way to obtain the
|
|
tangent’s slope is to pick two close points on the x-axis that are
|
|
equidistant from <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span> and to use the slope of the line determined by
|
|
<span style="font-style: italic">f</span> at those two points. The convention is to choose a small number
|
|
<span style="font-style: italic">ε</span> and to work with <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> + ε</span> and <span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> - ε</span>. That is, the
|
|
points are <span style="font-style: italic"></span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> - ε, f</span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> - ε</span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span> and <span style="font-style: italic"></span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> + ε, f</span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"> + ε</span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span>, which
|
|
determine a line and a slope:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_189.png" alt="image" width="317" height="19"/></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3aslope))"></a><span style="font-weight: bold">Exercise</span> 455. Translate this mathematical formula into the ISL+
|
|
function <span class="RktSym">slope</span>, which maps function <span class="RktSym">f</span> and a number
|
|
<span class="RktSym">r1</span> to the slope of <span class="RktSym">f</span> at <span class="RktSym">r1</span>. Assume that
|
|
<span class="RktSym">ε</span> is a global constant. For your examples, use functions whose exact slope you can
|
|
figure out, say, horizontal lines, linear functions, and perhaps
|
|
polynomials if you know some calculus. <a href="part_five.html#%28counter._%28exercise._ex~3aslope%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">The second piece of domain knowledge concerns the root of a tangent, which is
|
|
just a line or a linear function. The tangent goes through <span style="font-style: italic"></span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic">, f</span>(<span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span>
|
|
and has the above <span style="font-style: italic">slope</span>. Mathematically, it is defined as
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_190.png" alt="image" width="225" height="13"/></p></blockquote></div><div class="SIntrapara">Finding the root of <span style="font-style: italic">tangent</span> means finding a value
|
|
<span style="font-style: italic">root-of-tangent</span> so that <span style="font-style: italic">tangent</span>(<span style="font-style: italic">root-of-tangent</span>)<span style="font-style: italic"></span> equals <span style="font-style: italic"></span>0<span style="font-style: italic"></span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_191.png" alt="image" width="252" height="13"/></p></blockquote></div><div class="SIntrapara">We can solve this equation in a straightforward manner:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_192.png" alt="image" width="178" height="23"/></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3aroot-of-tangent))"></a><span style="font-weight: bold">Exercise</span> 456. Design
|
|
<span class="RktSym">root-of-tangent</span>, a function that maps <span class="RktSym">f</span> and <span class="RktSym">r1</span><span class="RktMeta"></span> to
|
|
the root of the tangent through <span style="font-style: italic"></span>(<span style="font-style: italic"></span><span class="RktSym">r1</span><span style="font-style: italic">,</span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">r1</span><span class="RktPn">)</span><span style="font-style: italic"></span>)<span style="font-style: italic"></span>. <a href="part_five.html#%28counter._%28exercise._ex~3aroot-of-tangent%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Now we can use the design recipe to translate the description of Newton’s
|
|
process into an ISL+ program. The function—<wbr></wbr>let’s call it <span class="RktSym">newton</span>
|
|
in honor of its inventor—<wbr></wbr>consumes a function <span class="RktSym">f</span> and a number
|
|
<span class="RktSym">r1</span>:
|
|
<a name="(idx._(gentag._654))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a number </span><span class="RktSym">r</span><span class="RktCmt"> such that </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="RktCmt"> is small</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> repeatedly generates improved guesses</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1.0</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">For the template of <span class="RktSym">newton</span>, we turn to the central four questions of
|
|
the design recipe for generative recursion:
|
|
</div><div class="SIntrapara"><ol><li><p><div class="SIntrapara">If <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">r1</span><span class="RktPn">)</span> is close enough to <span class="RktVal">0</span>, the problem is
|
|
solved. Close to <span class="RktVal">0</span> could mean <span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">r1</span><span class="RktPn">)</span> is a small positive
|
|
number or a small negative number. Hence we check its absolute value:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._abs%29%29" class="RktValLink" data-pltdoc="x">abs</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></p></blockquote></div></p></li><li><p>The solution is <span class="RktSym">r1</span>.</p></li><li><p>The generative step of the algorithm consists of finding the root of the
|
|
tangent of <span class="RktSym">f</span> at <span class="RktSym">r1</span>, which generates the next guess. By applying
|
|
<span class="RktSym">newton</span> to <span class="RktSym">f</span> and this new guess, we resume the process.</p></li><li><p>The answer of the recursion is also the answer of the original problem.</p></li></ol></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._655))"></a>
|
|
<a name="(idx._(gentag._656))"></a>
|
|
<a name="(idx._(gentag._657))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a number </span><span class="RktSym">r</span><span class="RktCmt"> such that </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._abs%29%29" class="RktValLink" data-pltdoc="x">abs</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">3.5</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c~3d%29%29" class="RktValLink" data-pltdoc="x"><=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._abs%29%29" class="RktValLink" data-pltdoc="x">abs</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">root-of-tangent</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">see </span><a href="part_five.html#%28counter._%28exercise._ex~3aslope%29%29" data-pltdoc="x">exercise 455</a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">slope</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">see </span><a href="part_five.html#%28counter._%28exercise._ex~3aroot-of-tangent%29%29" data-pltdoc="x">exercise 456</a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">root-of-tangent</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3anewton))" x-target-lift="Figure"></a>Figure 161: </span>The Newton process</span></p></blockquote></div></p><p><a href="part_five.html#%28counter._%28figure._fig~3anewton%29%29" data-pltdoc="x">Figure <span class="FigureRef">161</span></a> displays <span class="RktSym">newton</span>. It includes two tests
|
|
that are derived from the tests in <a href="part_five.html#%28part._sec~3abinary-search%29" data-pltdoc="x">Binary Search</a> for
|
|
<span class="RktSym">find-root</span>. After all, both functions search for the root of a
|
|
function, and <span class="RktSym">poly</span> has two known roots.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img src="pict_193.png" alt="image" width="400" height="400"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3apoly-root))" x-target-lift="Figure"></a>Figure 162: </span>The graph of <span class="RktSym">poly</span> on the interval <span style="font-style: italic"></span>[<span style="font-style: italic"></span><span class="RktVal"><span class="nobreak">-1</span></span><span style="font-style: italic">,</span><span class="RktVal">5</span><span style="font-style: italic"></span>]<span style="font-style: italic"></span></span></p></blockquote><p><div class="SIntrapara">We are not finished with the design of <span class="RktSym">newton</span>. The new, seventh step
|
|
of the design recipe calls for an investigation into the termination behavior
|
|
of the function. For <span class="RktSym">newton</span>, the problem shows up with <span class="RktSym">poly</span>:
|
|
<a name="(idx._(gentag._658))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As mentioned, its roots are <span class="RktVal">2</span> and <span class="RktVal">4</span>. The graph of
|
|
<span class="RktSym">poly</span> in <a href="part_five.html#%28counter._%28figure._fig~3apoly-root%29%29" data-pltdoc="x">figure <span class="FigureRef">162</span></a> confirms these roots and also
|
|
shows that between the two roots the function flattens out. For a
|
|
mathematically inclined person, this shape raises the
|
|
question of what <span class="RktSym">newton</span> computes for an initial guess of <span class="RktVal">3</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">-1</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">/:division by zero</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The explanation is that <span class="RktSym">slope</span> produces a “bad” value and the
|
|
<span class="RktSym">root-of-tangent</span> function turns it into an error:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">slope</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">0</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">root-of-tangent</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">/:division by zero</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">In addition to this run-time error, <span class="RktSym">newton</span> exhibits two other
|
|
problems with respect to termination. Fortunately, we can demonstrate both
|
|
with <span class="RktSym">poly</span>. The first one concerns the nature of numbers, which we
|
|
briefly touched on in <a href="part_one.html#%28part._sec~3aarith-num%29" data-pltdoc="x">The Arithmetic of Numbers</a>. It is safe to ignore the
|
|
distinction between exact and inexact numbers for many beginner exercises in
|
|
programming, but when it comes to translating mathematics into programs, you
|
|
need to proceed with extreme caution. Consider the following:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">2.9999</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">An ISL+ program treats <span class="RktVal">2.9999</span> as an exact number, and the
|
|
computations in <span class="RktSym">newton</span> process it as such, though because the numbers
|
|
aren’t integers, the computation uses exact rational fractions. Since the
|
|
arithmetic for fractions can get much slower than the arithmetic for inexact
|
|
numbers, the above function call takes a significant amount of time in
|
|
DrRacket. Depending on your computer, it may take between a few seconds and a
|
|
minute or more. If you happen to choose other numbers that trigger this form
|
|
of computation, it may seem as if the call to <span class="RktSym">newton</span> does not
|
|
terminate at all.</div></p><p><div class="SIntrapara">The second problem concerns non-termination. Here is the example:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">newton</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">#i3.0</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It uses the inexact number <span class="RktVal">#i3.0</span><span class="RktMeta"></span> as the initial guess, which unlike
|
|
<span class="RktVal">3</span> causes a different kind of problem. Specifically, the
|
|
<span class="RktSym">slope</span> function now produces an inexact <span class="RktVal">0</span> for poly while
|
|
<span class="RktSym">root-of-tangent</span> jumps to infinity:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">slope</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">#i3.0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i0.0</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">root-of-tangent</span><span class="hspace"> </span><span class="RktSym">poly</span><span class="hspace"> </span><span class="RktVal">#i3.0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i+inf.0</span></p></td></tr></table></blockquote></div><div class="SIntrapara">As a result, the evaluation immediately falls into an infinite
|
|
loop.<span class="refelem"><span class="refcolumn"><span class="refcontent">The calculation in <span class="RktSym">newton</span> turns <span class="RktVal">#i+inf.0</span><span class="RktMeta"></span> into
|
|
<span class="RktVal">+nan.0</span>, a piece of data that says “not a number.” Most
|
|
arithmetic operations propagate this value, which explains the behavior of
|
|
<span class="RktSym">newton</span>.</span></span></span></div></p><p>In short, <span class="RktSym">newton</span> exhibits the full range of problems when it comes
|
|
to complex termination behavior. For some inputs, the function produces a
|
|
correct result. For some others, it signals errors. And for yet others, it
|
|
goes into infinite loop or appears to go into one. The header for
|
|
<span class="RktSym">newton</span>—<wbr></wbr>or some other piece of writing—<wbr></wbr>must warn others who
|
|
wish to use the function and future readers of these complexities, and good
|
|
math libraries in common programming languages do so.</p><p><a name="(counter._(exercise._ex~3adouble-amount))"></a><span style="font-weight: bold">Exercise</span> 457. Design the function
|
|
<span class="RktSym">double-amount</span>,<span class="refelem"><span class="refcolumn"><span class="refcontent">This exercise was suggested by Adrian
|
|
German.</span></span></span> which computes how many months it takes to double a given amount
|
|
of money when a savings account pays interest at a fixed rate on a monthly
|
|
basis.</p><p><span style="font-weight: bold">Domain Knowledge</span> With a minor algebraic manipulation, you can show
|
|
that the given amount is irrelevant. Only the interest rate matters. Also
|
|
domain experts know that doubling occurs after roughly <span style="font-style: italic"></span>7<span style="font-style: italic"></span>2<span style="font-style: italic">/r</span> month as
|
|
long as the interest rate <span style="font-style: italic">r</span> is “small.” <a href="part_five.html#%28counter._%28exercise._ex~3adouble-amount%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>28.2<tt> </tt><a name="(part._sec~3aintegrate)"></a>Numeric Integration</h4><p><div class="SIntrapara">Many physics problems boil down to determining the area under a curve:
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> A car drives at a constant speed of <span style="font-style: italic">v</span> meters per
|
|
second. How far does it travel in <span class="RktVal">5</span>, <span class="RktVal">10</span>, <span class="RktVal">15</span>
|
|
seconds?</p><p>A rocket lifts off at the constant rate of acceleration of
|
|
<img src="pict_194.png" alt="image" width="43" height="13"/>. What height does it reach after <span class="RktVal">5</span>, <span class="RktVal">10</span>,
|
|
<span class="RktVal">15</span> seconds?</p></blockquote></div><div class="SIntrapara">Physics tells us that a vehicle travels <img src="pict_195.png" alt="image" width="75" height="12"/> meters if it moves at a constant speed <span style="font-style: italic">v</span> for <span style="font-style: italic">t</span>
|
|
seconds. For vehicles that accelerate, the distance traveled depends on the
|
|
square of the time <span style="font-style: italic">t</span> passed:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_196.png" alt="image" width="96" height="15"/></p></blockquote></div><div class="SIntrapara">In general, the law tells us that the distance corresponds to the area
|
|
under the graph of speed <span style="font-style: italic">v</span>(<span style="font-style: italic">t</span>)<span style="font-style: italic"></span> over time <span style="font-style: italic">t</span>.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img src="pict_197.png" alt="image" width="250" height="200"/>
|
|
<span class="hspace"> </span>
|
|
<img src="pict_198.png" alt="image" width="250" height="200"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3adistance))" x-target-lift="Figure"></a>Figure 163: </span>Distance traveled with constant vs accelerating speed</span></p></blockquote><p><a href="part_five.html#%28counter._%28figure._fig~3adistance%29%29" data-pltdoc="x">Figure <span class="FigureRef">163</span></a> illustrates the idea in a graphical manner. On
|
|
the left, we see an overlay of two graphs: the solid flat line is the speed
|
|
of the vehicle and the rising dashed line is the distance traveled. A quick
|
|
check shows that the latter is indeed the area determined by the former and
|
|
the x-axis at <span style="font-weight: bold">every point in time</span>. Similarly, the graphs on
|
|
the right show the relationship between a rocket moving at constantly
|
|
increasing speed and the height it reaches. Determining this area under the
|
|
graph of a function for some specific interval is called (function)
|
|
<span style="font-style: italic">integration</span>.</p><p>While mathematicians know formulas for the two sample problems that give
|
|
precise answers, the general problem calls for computational
|
|
solutions. The problem is that curves often come with complex shapes, more
|
|
like those in <a href="part_five.html#%28counter._%28figure._fig~3afunc-int%29%29" data-pltdoc="x">figure <span class="FigureRef">164</span></a>, which suggests that someone needs
|
|
to know the area between the x-axis, the vertical lines labeled
|
|
<span style="font-style: italic">a</span> and <span style="font-style: italic">b</span>, and the graph of <span style="font-style: italic">f</span>. Applied mathematicians
|
|
determine such areas in an approximate manner, summing the areas of many
|
|
small geometric shapes. It is therefore natural to develop algorithms
|
|
that deal with these calculations.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><p><img src="pict_199.png" alt="image" width="400" height="400"/></p></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3afunc-int))" x-target-lift="Figure"></a>Figure 164: </span>Integrating a function <span style="font-style: italic">f</span> between <span style="font-style: italic">a</span> and <span style="font-style: italic">b</span></span></p></blockquote><p><div class="SIntrapara">An integration algorithm consumes three inputs: the function <span class="RktSym">f</span> and
|
|
two borders, <span class="RktSym">a</span> and <span class="RktSym">b</span>. The fourth part, the x-axis, is
|
|
implied. This suggests the following signature:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></p></blockquote></div><div class="SIntrapara">In order to understand the idea behind integration, it is best to study
|
|
simple examples such as a constant function or a linear one. Thus,
|
|
consider <a name="(idx._(gentag._659))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">constant</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">20</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Passing <span class="RktSym">constant</span> to <span class="RktSym">integrate</span>, together with <span class="RktVal">12</span>
|
|
and <span class="RktVal">22</span>, describes a rectangle of width <span class="RktVal">10</span> and height
|
|
<span class="RktVal">20</span>. The area of this rectangle is <span class="RktVal">200</span>, meaning we get
|
|
this test:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktSym">constant</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">22</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">200</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Similarly, let’s use <span class="RktSym">linear</span> to create a second test: <a name="(idx._(gentag._660))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">linear</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">If we use <span class="RktSym">linear</span>, <span class="RktVal">0</span>, and <span class="RktVal">10</span> with
|
|
<span class="RktSym">integrate</span>, the area is a triangle with a base width of
|
|
<span class="RktVal">10</span> and a height of <span class="RktVal">20</span>. Here is the example as a test:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktSym">linear</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">100</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">After all, a triangle’s area is half of the product of its base width and
|
|
height.</div></p><p><div class="SIntrapara">For a third example, we exploit some domain-specific knowledge. As
|
|
mentioned, mathematicians know how to determine the area under some
|
|
functions in a precise manner. For example, the area under the function
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_200.png" alt="image" width="93" height="14"/></p></blockquote></div><div class="SIntrapara">on the interval <span style="font-style: italic"></span>[<span style="font-style: italic">a,b</span>]<span style="font-style: italic"></span> can be calculated with the following formula
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_201.png" alt="image" width="44" height="11"/></p></blockquote></div><div class="SIntrapara">Here is how to turn this idea into a concrete test: <a name="(idx._(gentag._661))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._square%29%29" class="RktValLink" data-pltdoc="x">square</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sqr%29%29" class="RktValLink" data-pltdoc="x">sqr</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._square%29%29" class="RktValLink" data-pltdoc="x">square</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._662))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">ε</span><span class="hspace"> </span><span class="RktVal">0.1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes the area under the graph of </span><span class="RktSym">f</span><span class="RktCmt"> between </span><span class="RktSym">a</span><span class="RktCmt"> and </span><span class="RktSym">b</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3c%29%29" class="RktValLink" data-pltdoc="x"><</a></span><span class="stt"> </span><span class="RktSym">a</span><span class="stt"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktCmt"> holds </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">20</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">22</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">200</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">100</span><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sqr%29%29" class="RktValLink" data-pltdoc="x">sqr</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">1000</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">ε</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrate</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#i0.0</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aintegrate-test))" x-target-lift="Figure"></a>Figure 165: </span>A generic integration function</span></p></blockquote></div></p><p><a href="part_five.html#%28counter._%28figure._fig~3aintegrate-test%29%29" data-pltdoc="x">Figure <span class="FigureRef">165</span></a> collects the result of the first three
|
|
steps of the design recipe. The figure adds a purpose statement and an
|
|
obvious assumption concerning the two interval boundaries. Instead of
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span> it uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span>, which anticipates the
|
|
numerical inaccuracies that come with computational approximations in such
|
|
calculations. Analogously, the header of <span class="RktSym">integrate</span> specifies
|
|
<span class="RktVal">#i0.0</span><span class="RktMeta"></span> as the return result, signaling that the function is
|
|
expected to return an inexact number.</p><p>The following two exercises show how to turn domain knowledge into
|
|
integration functions. Both functions compute rather crude
|
|
approximations. While the design of the first uses only mathematical
|
|
formulas, the second also exploits a bit of structural design ideas.
|
|
Solving these exercises creates the necessary appreciation for the core of
|
|
this section, which presents a generative-recursive integration algorithm.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aintegral-kepler))"></a><span style="font-weight: bold">Exercise</span> 458. Kepler suggested a simple integration
|
|
method. To compute an estimate<span class="refelem"><span class="refcolumn"><span class="refcontent">The method is known as
|
|
<span style="font-style: italic">Kepler’s rule</span>.</span></span></span> of the area under <span style="font-style: italic">f</span> between <span style="font-style: italic">a</span>
|
|
and <span style="font-style: italic">b</span>, proceed as follows:
|
|
</div><div class="SIntrapara"><ol><li><p>divide the interval into half at <span style="font-style: italic">mid = </span>(<span style="font-style: italic">a + b</span>)<span style="font-style: italic"> / </span>2<span style="font-style: italic"></span>;</p></li><li><p><div class="SIntrapara">compute the areas of these two <span style="font-style: italic">trapezoids</span>:
|
|
</div><div class="SIntrapara"><ul><li><p><span style="font-style: italic"></span>[<span style="font-style: italic"></span>(<span style="font-style: italic">a,</span>0<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">a,f</span>(<span style="font-style: italic">a</span>)<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">mid,</span>0<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">mid,f</span>(<span style="font-style: italic">mid</span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span>]<span style="font-style: italic"></span></p></li><li><p><span style="font-style: italic"></span>[<span style="font-style: italic"></span>(<span style="font-style: italic">mid,</span>0<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">mid,f</span>(<span style="font-style: italic">mid</span>)<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">b,</span>0<span style="font-style: italic"></span>)<span style="font-style: italic">,</span>(<span style="font-style: italic">b,f</span>(<span style="font-style: italic">b</span>)<span style="font-style: italic"></span>)<span style="font-style: italic"></span>]<span style="font-style: italic"></span>;</p></li></ul></div></p></li><li><p>then add the two areas.</p></li></ol></div></p><p><div class="SIntrapara"><span style="font-weight: bold">Domain Knowledge</span> Let’s take a look at these trapezoids. Here are
|
|
the two possible shapes, with minimal annotations to reduce clutter:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_202.png" alt="image" width="257.0" height="256.0"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_203.png" alt="image" width="257.0" height="256.0"/></p></blockquote></div><div class="SIntrapara">The left shape assumes <span style="font-style: italic">f</span>(<span style="font-style: italic">L</span>)<span style="font-style: italic"> > f</span>(<span style="font-style: italic">R</span>)<span style="font-style: italic"></span> while the right one shows the
|
|
case where <span style="font-style: italic">f</span>(<span style="font-style: italic">L</span>)<span style="font-style: italic"> < f </span>(<span style="font-style: italic">R</span>)<span style="font-style: italic"></span>. Despite the asymmetry, it is still possible
|
|
to calculate the area of these trapezoids with a single formula:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_204.png" alt="image" width="251" height="15"/></p></blockquote></div><div class="SIntrapara">Stop! Convince yourself that this formula <span style="font-weight: bold">adds</span> the area of the
|
|
triangle to the area of the lower rectangle for the left trapezoid,
|
|
while it <span style="font-weight: bold">subtracts</span> the triangle from the area of the
|
|
large rectangle for the right one.</div></p><p><div class="SIntrapara">Also show that the above formula is equal to
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_205.png" alt="image" width="144" height="15"/></p></blockquote></div><div class="SIntrapara">This is a mathematical validation of the asymmetry of the formula.</div></p><p>Design the function <span class="RktSym">integrate-kepler</span>. That is, turn the
|
|
mathematical knowledge into an ISL+ function. Adapt the test
|
|
cases from <a href="part_five.html#%28counter._%28figure._fig~3aintegrate-test%29%29" data-pltdoc="x">figure <span class="FigureRef">165</span></a> to this use. Which of the three
|
|
tests fails and by how much? <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-kepler%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aintegral-rectangle))"></a><span style="font-weight: bold">Exercise</span> 459. Another simple integration method divides the
|
|
area into many small rectangles. Each rectangle has a fixed width and is as
|
|
tall as the function graph in the middle of the rectangle. Adding up the
|
|
areas of the rectangles produces an estimate of the area under the function’s
|
|
graph.</p><p><div class="SIntrapara">Let’s use
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">R = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span></p></blockquote></div><div class="SIntrapara">to stand for the number of rectangles to be considered. Hence the width of
|
|
each rectangle is
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_206.png" alt="image" width="89" height="12"/></p></blockquote></div><div class="SIntrapara">The height of one of these rectangles is the value of
|
|
<span style="font-style: italic">f</span> at its midpoint. The first midpoint is clearly at <span style="font-style: italic">a</span> plus
|
|
half of the width of the rectangle,
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_207.png" alt="image" width="56" height="12"/></p></blockquote></div><div class="SIntrapara">which means its area is
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_208.png" alt="image" width="76" height="12"/></p></blockquote></div><div class="SIntrapara">To compute the area of the second rectangle, we must add the width of one
|
|
rectangle to the first midpoint:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_209.png" alt="image" width="105" height="12"/></p></blockquote></div><div class="SIntrapara">For the third one, we get
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_210.png" alt="image" width="120" height="12"/></p></blockquote></div><div class="SIntrapara">In general, we can use the following formula for the <span style="font-style: italic">i</span>th rectangle:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_211.png" alt="image" width="118" height="12"/></p></blockquote></div><div class="SIntrapara">The first rectangle has index <span style="font-style: italic"></span>0<span style="font-style: italic"></span>, the last one <span style="font-style: italic">R - </span>1<span style="font-style: italic"></span>.</div></p><p><div class="SIntrapara">Using these rectangles, we can now determine the area under the
|
|
graph:
|
|
</div><div class="SIntrapara"><blockquote><p><img src="pict_212.png" alt="image" width="348" height="90"/></p></blockquote></div></p><p>Turn the description of the process into an ISL+ function and call it <span class="RktSym">integrate-rectangles</span>.
|
|
Adapt the test cases from <a href="part_five.html#%28counter._%28figure._fig~3aintegrate-test%29%29" data-pltdoc="x">figure <span class="FigureRef">165</span></a> to this case.</p><p>The more rectangles the algorithm uses, the closer its estimate is to the
|
|
actual area. Make <span class="RktSym">R</span> a top-level constant and increase it by
|
|
factors of <span class="RktVal">10</span> until the algorithm’s accuracy eliminates problems
|
|
with an <span class="RktSym">ε</span> value of <span class="RktVal">0.1</span>.</p><p>Decrease <span class="RktSym">ε</span> to <span class="RktVal">0.01</span> and increase <span class="RktSym">R</span> enough
|
|
to eliminate any failing test cases again. Compare the result to
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3aintegral-kepler%29%29" data-pltdoc="x">exercise 458</a>. <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-rectangle%29%29" class="ex-end" data-pltdoc="x"></a></p><p>The Kepler method of <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-kepler%29%29" data-pltdoc="x">exercise 458</a> immediately suggests a
|
|
divide-and-conquer strategy like binary search introduced in
|
|
<a href="part_five.html#%28part._sec~3abinary-search%29" data-pltdoc="x">Binary Search</a>. Roughly speaking, the algorithm would split
|
|
the interval into two pieces, recursively compute the area of each piece,
|
|
and add the two results.</p><p><a name="(counter._(exercise._ex~3aintegral-dc))"></a><span style="font-weight: bold">Exercise</span> 460. Develop the algorithm <span class="RktSym">integrate-dc</span>,
|
|
which integrates a function <span class="RktSym">f</span> between the boundaries <span class="RktSym">a</span>
|
|
and <span class="RktSym">b</span> using a divide-and-conquer strategy. Use Kepler’s method
|
|
when the interval is sufficiently small. <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-dc%29%29" class="ex-end" data-pltdoc="x"></a></p><p>The divide-and-conquer approach of <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-dc%29%29" data-pltdoc="x">exercise 460</a> is
|
|
wasteful. Consider a function whose graph is level in one part and rapidly
|
|
changes in another; see <a href="part_five.html#%28counter._%28figure._fig~3awave-y-function%29%29" data-pltdoc="x">figure <span class="FigureRef">166</span></a> for a concrete
|
|
example. For the level part on the graph, it is pointless to keep splitting
|
|
the interval. It is just as easy to compute the trapezoid for the complete
|
|
interval as for the two halves. For the “wavy” part, however, the algorithm
|
|
must continue dividing the interval until the irregularities of the graph
|
|
are reasonably small.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img src="pict_213.png" alt="image" width="400" height="400"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3awave-y-function))" x-target-lift="Figure"></a>Figure 166: </span>A candidate for adaptive integration</span></p></blockquote><p><div class="SIntrapara">To discover when <span style="font-style: italic">f</span> is level, we can change the algorithm as
|
|
follows. Instead of just testing how large the interval is, the new
|
|
algorithm computes the area of three trapezoids: the given one and the two
|
|
halves. If the difference between the two is less than the area of a small
|
|
rectangle of height <span style="font-style: italic">ε</span> and width <img src="pict_214.png" alt="image" width="27" height="10"/>,
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_215.png" alt="image" width="51" height="12"/></p></blockquote></div><div class="SIntrapara">it is safe to assume that the overall area is a good approximation. In
|
|
other words, the algorithm determines whether <span style="font-style: italic">f</span> changes so much that
|
|
it affects the error margin. If so, it continues with the
|
|
divide-and-conquer approach; otherwise it stops and uses the Kepler
|
|
approximation.</div></p><p><a name="(counter._(exercise._ex~3aadaptive-integral))"></a><span style="font-weight: bold">Exercise</span> 461. Design <span class="RktSym">integrate-adaptive</span>. That
|
|
is, turn the recursive process description into an ISL+ algorithm. Make
|
|
sure to adapt the test cases from <a href="part_five.html#%28counter._%28figure._fig~3aintegrate-test%29%29" data-pltdoc="x">figure <span class="FigureRef">165</span></a> to this
|
|
use.</p><p>Do not discuss the termination of <span class="RktSym">integrate-adaptive</span>.</p><p>Does <span class="RktSym">integrate-adaptive</span> always compute a better answer than
|
|
either <span class="RktSym">integrate-kepler</span> or <span class="RktSym">integrate-rectangles</span> from <a href="part_five.html#%28counter._%28exercise._ex~3aintegral-rectangle%29%29" data-pltdoc="x">exercise 459</a>? Which
|
|
aspect is <span class="RktSym">integrate-adaptive</span> guaranteed to improve? <a href="part_five.html#%28counter._%28exercise._ex~3aadaptive-integral%29%29" class="ex-end" data-pltdoc="x"></a></p><p><span style="font-weight: bold">Terminology</span> The algorithm is called <span style="font-style: italic">adaptive integration</span>
|
|
because it automatically allocates time to those parts of the graph that
|
|
need it and spends little time on the others. Specifically, for those
|
|
parts of <span style="font-style: italic">f</span> that are level, it performs just a few calculations; for
|
|
the other parts, it inspects small intervals to decrease the error
|
|
margin. Computer science knows many adaptive algorithms, and
|
|
<span class="RktSym">integrate-adaptive</span> is just one of them.</p><h4>28.3<tt> </tt><a name="(part._sec~3aproj-gauss)"></a>Project: Gaussian Elimination</h4><p><div class="SIntrapara">Mathematicians not only search for solutions of equations in one variable;
|
|
they also study whole systems of linear equations:
|
|
</div><div class="SIntrapara"><blockquote><p><div class="SIntrapara"><span style="font-weight: bold">Sample Problem</span> In a bartering world, the values of coal (<span style="font-style: italic">x</span>), oil
|
|
(<span style="font-style: italic">y</span>), and gas (<span style="font-style: italic">z</span>) are determined by these exchange equations:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_216.png" alt="image" width="240" height="42"/></p></blockquote></div></p></blockquote></div><div class="SIntrapara">A solution to such a system of equations consists of a collection of
|
|
numbers, one per variable, such that if we replace the variable with its
|
|
corresponding number, the two sides of each equation evaluate to the same
|
|
number. In our running example, the solution is
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>, <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, and <span style="font-style: italic">z = </span>2<span style="font-style: italic"></span>.</p></blockquote></div><div class="SIntrapara">We can easily check this claim:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_217.png" alt="image" width="187" height="40"/></p></blockquote></div><div class="SIntrapara">The three equations reduce to
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"> = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, <span style="font-style: italic"></span>3<span style="font-style: italic"></span>1<span style="font-style: italic"> = </span>3<span style="font-style: italic"></span>1<span style="font-style: italic"></span>, and <span style="font-style: italic"></span>1<span style="font-style: italic"> =</span>1<span style="font-style: italic"></span>.</p></blockquote></div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._soe)"></a><span style="font-style: italic">SOE</span><span class="RktCmt"> is a non-empty </span><a href="part_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a><span class="RktCmt">.</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">constraint</span><span class="RktCmt"> for </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="stt"> </span><span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span><span class="RktPn">)</span><span class="RktCmt">, </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="stt"> </span><span style="font-style: italic">r</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">i</span></span><span style="font-style: italic"></span><span class="RktPn">)</span><span class="RktCmt"> is </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> represents a system of linear equations</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._equation)"></a><span style="font-style: italic">Equation</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">].</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">constraint</span><span class="RktCmt"> an </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt"> contains at least two numbers. </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> if </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span style="font-style: italic">a</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="stt"> </span><span style="font-style: italic">a</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span><span class="stt"> </span><span style="font-style: italic">b</span><span class="RktPn">)</span><span class="RktCmt"> is an </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt">, </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-style: italic">a</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span><span class="RktCmt">, </span>...<span class="RktCmt">, </span><span style="font-style: italic">a</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span><span class="RktCmt"> are the left-hand-side variable coefficients </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">and </span><span style="font-style: italic">b</span><span class="RktCmt"> is the right-hand side</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._solution)"></a><span style="font-style: italic">Solution</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">M</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">an </span><a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">an </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">31</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">a </span><a href="part_five.html#%28tech._solution%29" class="techoutside" data-pltdoc="x"><span class="techinside">Solution</span></a></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3amatrix))" x-target-lift="Figure"></a>Figure 167: </span>A data representation for systems of equations</span></p></blockquote><p><a href="part_five.html#%28counter._%28figure._fig~3amatrix%29%29" data-pltdoc="x">Figure <span class="FigureRef">167</span></a> introduces a data representation for our problem
|
|
domain. It includes an example of a system of equations and its solution.
|
|
This representation captures the essence of a system of equations, namely,
|
|
the numeric coefficients of the variables on the left-hand side and the
|
|
right-hand-side values. The names of the variables don’t play any role
|
|
because they are like parameters of functions; meaning, as long as they
|
|
are consistently renamed the equations have the same solutions.</p><p><div class="SIntrapara">For the rest of this section, it is convenient to use these functions:<a name="(idx._(gentag._663))"></a><a name="(idx._(gentag._664))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts the left-hand side from a row in a matrix</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">lhs</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">M</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">lhs</span><span class="hspace"> </span><span class="RktSym">e</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktSym">e</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts the right-hand side from a row in a matrix</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">M</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">rhs</span><span class="hspace"> </span><span class="RktSym">e</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktSym">e</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><a name="(counter._(exercise._ex~3agauss-data))"></a><span style="font-weight: bold">Exercise</span> 462. Design the function <span class="RktSym">check-solution</span>. It
|
|
consumes an <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a> and a <a href="part_five.html#%28tech._solution%29" class="techoutside" data-pltdoc="x"><span class="techinside">Solution</span></a>. Its result is <span class="RktVal">#true</span>
|
|
if plugging in the numbers from the <a href="part_five.html#%28tech._solution%29" class="techoutside" data-pltdoc="x"><span class="techinside">Solution</span></a> for the variables in
|
|
the <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a>s of the <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a> produces equal left-hand-side values
|
|
and right-hand-side values; otherwise the function produces <span class="RktVal">#false</span>.
|
|
Use <span class="RktSym">check-solution</span> to formulate tests with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-satisfied%29%29" class="RktStxLink" data-pltdoc="x">check-satisfied</a></span>.
|
|
<a name="(idx._(gentag._665))"></a></p><p><span style="font-weight: bold">Hint</span> Design the function <span class="RktSym">plug-in</span> first. It consumes the
|
|
left-hand side of an <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a> and a <a href="part_five.html#%28tech._solution%29" class="techoutside" data-pltdoc="x"><span class="techinside">Solution</span></a> and calculates
|
|
out the value of the left-hand side when the numbers from the solution are
|
|
plugged in for the variables. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-data%29%29" class="ex-end" data-pltdoc="x"></a></p><p><span style="font-style: italic">Gaussian elimination</span> is a standard method for finding solutions
|
|
to systems of linear equations. It consists of two steps. The first step is
|
|
to transform the system of equations into a system of different shape but
|
|
with the same solution. The second step is to find solutions to one
|
|
equation at a time. Here we focus on the first step because it is another
|
|
interesting instance of generative recursion.</p><p><div class="SIntrapara">The first step of the Gaussian elimination algorithm is called
|
|
“triangulation” because the result is a system of equations in the shape
|
|
of a triangle. In contrast, the original system is a rectangle. To
|
|
understand this terminology, take a look at this list, which represents the
|
|
original system:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">31</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Triangulation transforms this matrix into the following:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As promised, the shape of this system of equations is (roughly) a
|
|
triangle.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agauss-equiv2))"></a><span style="font-weight: bold">Exercise</span> 463. Check that the following system of equations
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_218.png" alt="image" width="235" height="40"/></p></blockquote></div><div class="SIntrapara">has the same solution as the one labeled with (<img src="pict_219.png" alt="image" width="5" height="11"/>). Do so by hand
|
|
and with <span class="RktSym">check-solution</span> from <a href="part_five.html#%28counter._%28exercise._ex~3agauss-data%29%29" data-pltdoc="x">exercise 462</a>. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-equiv2%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara">The key idea of triangulation is to subtract the first <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a>
|
|
from the remaining ones. To subtract one <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a> from another means
|
|
to subtract the corresponding coefficients in the two
|
|
<a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a>s. With our running example, subtracting the first equation
|
|
from the second yields the following matrix:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The goal of these subtractions is to put a <span class="RktVal">0</span> into the first column
|
|
of all but the first equation. For the third equation, getting a <span class="RktVal">0</span>
|
|
into the first position means subtracting the first equation <span style="font-weight: bold">twice</span>
|
|
from the third one:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-3</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>9</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Following convention, we drop the leading <span class="RktVal">0</span>’s from the
|
|
last two equations:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-3</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>9</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">That is, we first multiply each item in the first row with
|
|
<span class="RktVal">2</span> and then subtract the result from the last
|
|
row.<span class="refelem"><span class="refcolumn"><span class="refcontent">Mathematics teaches how to prove such facts. We use
|
|
them.</span></span></span> As mentioned, these subtractions do not change the solution; that
|
|
is, the solution of the original system is also the solution of the
|
|
transformed one.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agauss-equiv))"></a><span style="font-weight: bold">Exercise</span> 464. Check that the following system of equations
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_220.png" alt="image" width="244" height="42"/></p></blockquote></div><div class="SIntrapara">has the same solution as the one labeled with (<img src="pict_221.png" alt="image" width="5" height="11"/>). Again do so by
|
|
hand and with <span class="RktSym">check-solution</span> from <a href="part_five.html#%28counter._%28exercise._ex~3agauss-data%29%29" data-pltdoc="x">exercise 462</a>. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-equiv%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3agauss-subtract))"></a><span style="font-weight: bold">Exercise</span> 465. Design <span class="RktSym">subtract</span>. The function
|
|
consumes two <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a>s of equal length. It “subtracts” a multiple
|
|
of the second equation from the first, item by item, so that the resulting
|
|
<a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a> has a <span class="RktVal">0</span> in the first position. Since the leading
|
|
coefficient is known to be <span class="RktVal">0</span>, <span class="RktSym">subtract</span> returns the rest
|
|
of the list that results from the subtractions. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-subtract%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Now consider the rest of the <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-3</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>9</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It is also an <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a>, so we can apply the same algorithm again.
|
|
For our running example, this next subtraction step calls for subtracting
|
|
the first <a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a> <span class="RktVal"><span class="nobreak">-1</span></span> times from the second one. Doing so yields
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">9</span><span class="hspace"> </span><span class="RktVal">21</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The rest of this SOE is a single equation and cannot be simplified.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3atriangulate1))"></a><span style="font-weight: bold">Exercise</span> 466. Here is a representation for triangular SOEs:
|
|
<a name="(idx._(gentag._666))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._tm)"></a><span style="font-style: italic">TM</span><span class="RktCmt"> is an [</span><a href="part_three.html#%28tech._sim-dd._nelist._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">NEList-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">such that the </span><a href="part_five.html#%28tech._equation%29" class="techoutside" data-pltdoc="x"><span class="techinside">Equation</span></a><span class="RktCmt">s are of decreasing length: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span style="font-style: italic">n + </span>1<span style="font-style: italic"></span><span class="RktCmt">, </span><span style="font-style: italic">n</span><span class="RktCmt">, </span><span style="font-style: italic">n - </span>1<span style="font-style: italic"></span><span class="RktCmt">, </span>...<span class="RktCmt">, </span><span style="font-style: italic"></span>2<span style="font-style: italic"></span><span class="RktCmt">. </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> represents a triangular matrix</span></td></tr></table></blockquote></div><div class="SIntrapara">Design the <span class="RktSym">triangulate</span> algorithm:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a><span class="RktCmt"> -> </span><a href="part_five.html#%28tech._tm%29" class="techoutside" data-pltdoc="x"><span class="techinside">TM</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">triangulates the given system of equations </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">triangulate</span><span class="hspace"> </span><span class="RktSym">M</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Turn the above example into a test and spell out explicit answers for the
|
|
four questions based on our loose description.</div></p><p>Do not yet deal with the termination step of the design recipe. <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Unfortunately, the solution to <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate1%29%29" data-pltdoc="x">exercise 466</a> occasionally fails
|
|
to produce the desired triangular system. Consider the following
|
|
representation of a system of equations:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Its solution is <span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>, <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, and <span style="font-style: italic">z = </span>1<span style="font-style: italic"></span>.</div></p><p><div class="SIntrapara">The first step is to subtract the first row from the second and to subtract
|
|
it twice from the last one, which yields the following matrix:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-4</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Next, triangulation would focus on the rest of the matrix:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-4</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">but the first item of this matrix is <span class="RktVal">0</span>. Since it is impossible to
|
|
divide by <span class="RktVal">0</span>, the algorithm signals an error via <span class="RktSym">subtract</span>.</div></p><p><div class="SIntrapara">To overcome this problem, we need to use another piece of knowledge from
|
|
our problem domain. Mathematics tells us that switching equations in a
|
|
system of equations does not affect the solution. Of course, as we switch
|
|
equations, we must eventually find an equation whose leading coefficient is
|
|
not <span class="RktVal">0</span>. Here we can simply swap the first two:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-4</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">From here we may continue as before, subtracting the first equation from the
|
|
remaining one <span class="RktVal">0</span> times. The final triangular matrix is:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-8</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-4</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-5</span></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Show that <span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>, <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, and <span style="font-style: italic">z = </span>1<span style="font-style: italic"></span> is still a
|
|
solution for these equations.</div></p><p><a name="(counter._(exercise._ex~3atriangulate2))"></a><span style="font-weight: bold">Exercise</span> 467. Revise the algorithm <span class="RktSym">triangulate</span> from
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3atriangulate1%29%29" data-pltdoc="x">exercise 466</a> so that it rotates the equations first to find one
|
|
with a leading coefficient that is not <span class="RktVal">0</span> before it subtracts the
|
|
first equation from the remaining ones.</p><p>Does this algorithm terminate for all possible systems of equations?</p><p><div class="SIntrapara"><span style="font-weight: bold">Hint</span> The following expression rotates a non-empty list <span class="RktSym">L</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Explain why. <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate2%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara">Some <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a>s don’t have a solution. Consider this one:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_222.png" alt="image" width="176" height="42"/></p></blockquote></div><div class="SIntrapara">If you try to triangulate this SOE—<wbr></wbr>by hand or with your solution from
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3atriangulate2%29%29" data-pltdoc="x">exercise 467</a>—<wbr></wbr>you arrive at an intermediate matrix all of whose
|
|
equations start with <span class="RktVal">0</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_223.png" alt="image" width="176" height="27"/></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3atriangulate3))"></a><span style="font-weight: bold">Exercise</span> 468. Modify <span class="RktSym">triangulate</span> from
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3atriangulate2%29%29" data-pltdoc="x">exercise 467</a> so that it signals an error if it encounters an
|
|
<a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a> whose leading coefficients are all <span class="RktVal">0</span>. <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate3%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">After we obtain a triangular system of equations such as <span style="font-style: italic"></span>(<span style="font-style: italic">*</span>)<span style="font-style: italic"></span> in
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3agauss-equiv2%29%29" data-pltdoc="x">exercise 463</a>, we can solve the equations, one at a time. In our
|
|
specific example, the last equation says that <span style="font-style: italic">z</span> is
|
|
<span style="font-style: italic"></span>2<span style="font-style: italic"></span>. Equipped with this knowledge, we can eliminate <span style="font-style: italic">z</span> from the
|
|
second equation through a substitution:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_224.png" alt="image" width="94" height="10"/></p></blockquote></div><div class="SIntrapara">Doing so, in turn, determines the value for <span style="font-style: italic">y</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_225.png" alt="image" width="101" height="12"/></p></blockquote></div><div class="SIntrapara">Now that we have <span style="font-style: italic">z = </span>2<span style="font-style: italic"></span> and <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, we can plug these values
|
|
into the first equation:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_226.png" alt="image" width="131" height="9"/></p></blockquote></div><div class="SIntrapara">This yields another equation in a single variable, which we solve like
|
|
this:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_227.png" alt="image" width="147" height="12"/></p></blockquote></div><div class="SIntrapara">This finally yields a value for <span style="font-style: italic">x</span> and thus the complete solution for
|
|
the entire <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a>.</div></p><p><a name="(counter._(exercise._ex~3agauss-solve))"></a><span style="font-weight: bold">Exercise</span> 469. Design the <span class="RktSym">solve</span> function. It
|
|
consumes triangular <a href="part_five.html#%28tech._soe%29" class="techoutside" data-pltdoc="x"><span class="techinside">SOE</span></a>s and produces a solution.</p><p><span style="font-weight: bold">Hint</span> Use structural recursion for the design. Start with the
|
|
design of a function that solves a single linear equation in <span style="font-style: italic">n+</span>1<span style="font-style: italic"></span>
|
|
variables, given a solution for the last <span style="font-style: italic">n</span> variables. In general,
|
|
this function plugs in the values for the rest of the left-hand side,
|
|
subtracts the result from the right-hand side, and divides by the first
|
|
coefficient. Experiment with this suggestion and the above examples.</p><p><span style="font-weight: bold">Challenge</span> Use an existing abstraction and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> to design
|
|
<span class="RktSym">solve</span>. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-solve%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3agauss-complete))"></a><span style="font-weight: bold">Exercise</span> 470. Define <span class="RktSym">gauss</span>, which
|
|
combines the <span class="RktSym">triangulate</span> function from <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate3%29%29" data-pltdoc="x">exercise 468</a> and
|
|
the <span class="RktSym">solve</span> function from <a href="part_five.html#%28counter._%28exercise._ex~3agauss-solve%29%29" data-pltdoc="x">exercise 469</a>. <a href="part_five.html#%28counter._%28exercise._ex~3agauss-complete%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>29<tt> </tt><a name="(part._ch~3abacktrack)"></a>Algorithms that Backtrack</h3><p>Problem solving doesn’t always progress along some straight line. Sometimes
|
|
we may follow one approach and discover that we are stuck because we took
|
|
a wrong turn. One obvious option is to backtrack to the place where we made
|
|
the fateful decision and to take a different turn. Some algorithms work
|
|
just like that. This chapter presents two instances. The first section
|
|
deals with an algorithm for traversing graphs. The second one is an
|
|
extended exercise that uses backtracking in the context of a chess puzzle.</p><h4>29.1<tt> </tt><a name="(part._fsm._sec~3atraverse-graph1)"></a>Traversing Graphs</h4><p>Graphs are ubiquitous in our world and the world of computing. Imagine a
|
|
group of people, say, the students in your school. Write down all the names,
|
|
and connect the names of those people who know each other. You have just
|
|
created your first undirected graph.</p><p>Now take a look at <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>, which displays a small directed
|
|
graph. It consists of seven nodes—<wbr></wbr>the circled letters—<wbr></wbr>and nine
|
|
edges—<wbr></wbr>the arrows. The graph may represent a small version of an email
|
|
network. Imagine a company and all the emails that go back and forth. Write
|
|
down the email addresses of all employees. Then, address by address, draw
|
|
an arrow from the address to all those addresses to whom the owner sends
|
|
emails during a week. This is how you would create the directed graph in
|
|
<a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>, though it might end up looking much more complex,
|
|
almost impenetrable.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_228.png" alt="image" width="606" height="206"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._fsm._(figure._fig~3agraph))" x-target-lift="Figure"></a>Figure 168: </span>A directed graph</span></p></blockquote><p><div class="SIntrapara">In general, a <span style="font-style: italic">graph</span> consists of a collection of <span style="font-style: italic">nodes</span>
|
|
and a collection of <span style="font-style: italic">edges</span>, which connect nodes. In a
|
|
<span style="font-style: italic">directed graph</span>, the edges represent one-way connections between
|
|
the nodes; in an <span style="font-style: italic">undirected graph</span>, the edges represent two-way
|
|
connections between the nodes. In this context, the following is a common
|
|
type of problem:<span class="refelem"><span class="refcolumn"><span class="refcontent">Social scientists use such algorithms to
|
|
figure out the power structure in a company. Similarly they use such graphs
|
|
to predict the probable activities of people, even without knowledge of the
|
|
content of their emails.</span></span></span>
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design an algorithm that proposes a way to introduce one
|
|
person to another in a directed email graph for a large company. The
|
|
program consumes a directed graph representing established email
|
|
connections and two email addresses. It returns a sequence of email
|
|
addresses that connect the first email with the second.</p></blockquote></div><div class="SIntrapara">Mathematical scientists call the desired sequence a <span style="font-style: italic">path</span>.</div></p><p><div class="SIntrapara"><a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">Figure <span class="FigureRef">168</span></a> makes the sample problem
|
|
concrete. For example, you may wish to test whether the program can find a
|
|
path from <span style="font-style: italic">C</span> to <span style="font-style: italic">D</span>. This particular path consists of the
|
|
origination node <span style="font-style: italic">C</span> and the destination node <span style="font-style: italic">D</span>. In contrast,
|
|
if you wish to connect <span style="font-style: italic">E</span> with <span style="font-style: italic">D</span>, there are two paths:
|
|
</div><div class="SIntrapara"><ul><li><p>send email from <span style="font-style: italic">E</span> to <span style="font-style: italic">F</span> and then to <span style="font-style: italic">D</span>.</p></li><li><p>send it from <span style="font-style: italic">E</span> to <span style="font-style: italic">C</span> and then to <span style="font-style: italic">D</span>.</p></li></ul></div><div class="SIntrapara">Sometimes it is impossible to connect two nodes with a path. In the graph
|
|
of <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>, you cannot move from <span style="font-style: italic">C</span> to <span style="font-style: italic">G</span> by
|
|
following the arrows.</div></p><p>Looking at <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a> you can easily figure out how to get from
|
|
one node to another without thinking much about how you did it. So imagine
|
|
for a moment that the graph in <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a> is a large park. Also
|
|
imagine someone says you are located at <span style="font-style: italic">E</span> and you need to get to
|
|
<span style="font-style: italic">G</span>. You can clearly see two paths, one leading to <span style="font-style: italic">C</span> and
|
|
another one leading to <span style="font-style: italic">F</span>. Follow the first one and make sure to
|
|
remember that it is also possible to get from <span style="font-style: italic">E</span> to <span style="font-style: italic">F</span>. Now you
|
|
have a new problem, namely, how to get from <span style="font-style: italic">C</span> to <span style="font-style: italic">G</span>. The key
|
|
insight is that this new problem is just like the original problem; it asks
|
|
you to find a path from one node to another. Furthermore, if you can solve
|
|
the problem, you know how to get from <span style="font-style: italic">E</span> to <span style="font-style: italic">G</span>—<wbr></wbr>just add the
|
|
step from <span style="font-style: italic">E</span> to <span style="font-style: italic">C</span>. But there is no path from <span style="font-style: italic">C</span> to
|
|
<span style="font-style: italic">G</span>. Fortunately, you remember that it is also possible to go from
|
|
<span style="font-style: italic">E</span> to <span style="font-style: italic">F</span>, meaning you can <span style="font-style: italic">backtrack</span> to some point
|
|
where you have a choice to make and restart the search from there.</p><p><div class="SIntrapara">Now let’s design this algorithm in a systematic manner. Following the
|
|
general design recipe, we start with a data analysis. Here are two compact
|
|
list-based representations of the graph in <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">sample-graph</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">A</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">E</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">D</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">G</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">G</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></td><td><p><span class="hspace"> </span></p></td><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">sample-graph</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">A</span><span class="hspace"> </span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">E</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">D</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">D</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">G</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">G</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">Both contain one list per node. Each of these lists starts with the name of
|
|
a node followed by its (immediate) <span style="font-style: italic">neighbors</span>, that is, nodes
|
|
reachable by following a single arrow. The two differ in how they connect
|
|
the (name of the) node and its neighbors: the left one uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span>
|
|
while the right one uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>. For example, the second list
|
|
represents node <span style="font-style: italic">B</span> with its two outgoing edges to <span style="font-style: italic">E</span> and <span style="font-style: italic">F</span> in
|
|
<a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>. On the left <span class="RktVal">'</span><span class="RktVal">B</span> is the first name on a
|
|
two-element list; on the right it is the first name on a three-element
|
|
list.</div></p><p><a name="(counter._fsm._(exercise._ex~3arepresent-graph))"></a><span style="font-weight: bold">Exercise</span> 471. Translate one of the above
|
|
definitions into proper list form using <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span> and proper
|
|
symbols.</p><p><div class="SIntrapara">The data representation for nodes is straightforward:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._fsm._node)"></a><span style="font-style: italic">Node</span><span class="RktCmt"> is a </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt">.</span></p></blockquote></div><div class="SIntrapara">Formulate a data definition to describe the class of all
|
|
<a name="(tech._fsm._graph)"></a><span style="font-style: italic">Graph</span> representations, allowing an arbitrary number of nodes and
|
|
edges. Only one of the above representations has to belong to <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a>.</div></p><p>Design the function <span class="RktSym">neighbors</span>. It consumes a <a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a>
|
|
<span class="RktSym">n</span> and a <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a> <span class="RktSym">g</span> and produces the list of immediate
|
|
neighbors of <span class="RktSym">n</span> in <span class="RktSym">g</span>. <a href="part_five.html#%28counter._fsm._%28exercise._ex~3arepresent-graph%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Using your data definitions for <a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a> and <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a>—<wbr></wbr>regardless
|
|
of which one you chose, as long as you also designed <span class="RktSym">neighbors</span>—<wbr></wbr>we can
|
|
now formulate a signature and a purpose statement for <span class="RktSym">find-path</span>,
|
|
the function that searches a path in a graph: <a name="(idx._fsm._(gentag._667._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a path from </span><span class="RktSym">origination</span><span class="RktCmt"> to </span><span class="RktSym">destination</span><span class="RktCmt"> in </span><span class="RktSym">G</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">What this header leaves open is the exact shape of the result. It implies
|
|
that the result is a list of nodes, but it does not say which nodes it contains.</div></p><p><div class="SIntrapara">To appreciate this ambiguity and why it matters, let’s study the examples
|
|
from above. In ISL+, we can now formulate them like this:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">G</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The first call to <span class="RktSym">find-path</span> must return a unique path, the second
|
|
one must choose one from two, and the third one must signal that there is
|
|
no path from <span class="RktVal">'</span><span class="RktVal">C</span> to <span class="RktVal">'</span><span class="RktVal">G</span> in <span class="RktSym">sample-graph</span>. Here are two
|
|
possibilities, then, on how to construct the return value:
|
|
</div><div class="SIntrapara"><ul><li><p>The result of the function consists of all nodes leading from the
|
|
<span class="RktSym">origination</span> node to the <span class="RktSym">destination</span> node, including those
|
|
two.<span class="refelem"><span class="refcolumn"><span class="refcontent">It is easy to imagine others, such as skipping either of
|
|
the two given nodes.</span></span></span> In this case, an empty path could be used to express
|
|
the lack of a path between two nodes.</p></li><li><p>Alternatively, since the call itself already lists two of the nodes,
|
|
the output could mention only the “interior” nodes of the path. Then the
|
|
answer for the first call would be <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> because <span class="RktVal">'</span><span class="RktVal">D</span> is an
|
|
immediate neighbor of <span class="RktVal">'</span><span class="RktVal">C</span>. Of course,
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> could then no longer signal failure.</p></li></ul></div><div class="SIntrapara">Concerning the lack-of-a-path issue, we must choose a distinct value for
|
|
signaling this notion. Because <span class="RktVal">#false</span> is distinct, is meaningful, and
|
|
works in either case, we opt for it. As for the multiple-paths issue, we
|
|
postpone making a choice for now and list both possibilities in the example
|
|
section: <a name="(idx._fsm._(gentag._668._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._fsm._path)"></a><span style="font-style: italic">Path</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt">].</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> The list of nodes specifies a sequence</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">of immediate neighbors that leads from the first </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> on the list to the last one. </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._path%29" class="techoutside" data-pltdoc="x"><span class="techinside">Path</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a path from </span><span class="RktSym">origination</span><span class="RktCmt"> to </span><span class="RktSym">destination</span><span class="RktCmt"> in </span><span class="RktSym">G</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">if there is no path, the function produces </span><span class="RktVal">#false</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">D</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-member-of%29%29" class="RktStxLink" data-pltdoc="x">check-member-of</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">D</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">D</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">G</span><span class="hspace"> </span><span class="RktSym">sample-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Our next design step is to understand the four essential pieces of the
|
|
function: the “trivial problem” condition, a matching solution, the
|
|
generation of a new problem, and the combination step. The above discussion
|
|
of the search process and the analysis of the three examples suggest
|
|
answers:
|
|
</div><div class="SIntrapara"><ol><li><p>If the two given nodes are directly connected with an arrow
|
|
in the given graph, the path consists of just these two nodes. But there is
|
|
an even simpler case, namely, when the <span class="RktSym">origination</span> argument of
|
|
<span class="RktSym">find-path</span> is equal to its <span class="RktSym">destination</span>.</p></li><li><p>In that second case, the problem is truly trivial and the matching
|
|
answer is <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktSym">destination</span><span class="RktPn">)</span>.</p></li><li><p>If the arguments are different, the algorithm must inspect all
|
|
immediate neighbors of <span class="RktSym">origination</span> and determine whether there is
|
|
a path from any one of those to <span class="RktSym">destination</span>. In other words,
|
|
picking one of those neighbors generates a new instance of the “find a
|
|
path” problem.</p></li><li><p>Finally, once the algorithm has a path from a neighbor of
|
|
<span class="RktSym">origination</span> to <span class="RktSym">destination</span>, it is easy to construct a
|
|
complete path from the former to the latter—<wbr></wbr>just add the
|
|
<span class="RktSym">origination</span> node to the list.</p></li></ol></div><div class="SIntrapara">From a programming perspective, the third point is critical. Since a node
|
|
can have an arbitrary number of neighbors, the “inspect all neighbors”
|
|
task is too complex for a single primitive. We need an auxiliary function
|
|
that consumes a list of nodes and generates a new path problem for each of
|
|
them. Put differently, the function is a list-oriented version of
|
|
<span class="RktSym">find-path</span>.</div></p><p><div class="SIntrapara">Let’s call this auxiliary function <span class="RktSym">find-path/list</span> and let’s
|
|
formulate a wish for it: <a name="(idx._fsm._(gentag._669._fsm))"></a> <a name="(idx._fsm._(gentag._670._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt">] </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._path%29" class="techoutside" data-pltdoc="x"><span class="techinside">Path</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a path from some node on </span><span class="RktSym">lo-originations</span><span class="RktCmt"> to</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktSym">destination</span><span class="RktCmt">; otherwise, it produces </span><span class="RktVal">#false</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktSym">lo-originations</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Using this wish, we can fill in the generic template for
|
|
generative-recursive functions to get a first draft of <span class="RktSym">find-path</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbors</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It uses the <span class="RktSym">neighbors</span> from <a href="part_five.html#%28counter._fsm._%28exercise._ex~3arepresent-graph%29%29" data-pltdoc="x">exercise 471</a> and the
|
|
wish-list function <span class="RktSym">find-path/list</span> and otherwise uses the answers
|
|
to the four questions about generative recursive functions.</div></p><p><div class="SIntrapara">The rest of the design process is about details of composing these
|
|
functions properly. Consider the signature of <span class="RktSym">find-path/list</span>. Like
|
|
<span class="RktSym">find-path</span>, it produces [<a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a> <a href="part_five.html#%28tech._fsm._path%29" class="techoutside" data-pltdoc="x"><span class="techinside">Path</span></a>]. That is, if it finds
|
|
a path from any of the neighbors, it produces this path; otherwise, if
|
|
none of the neighbors is connected to <span class="RktSym">destination</span>, the function
|
|
produces <span class="RktVal">#false</span>. Hence the answer of <span class="RktSym">find-path</span> depends on
|
|
the kind of result that <span class="RktSym">find-path/list</span> produces, meaning the code must
|
|
distinguish the two possible answers with a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> expression: <a name="(idx._fsm._(gentag._671._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">next</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbors</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">candidate</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktSym">next</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The two cases reflect the two kinds of answers we might receive: a <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>
|
|
or a list. In the first case, <span class="RktSym">find-path/list</span> cannot find a path
|
|
from any neighbor to <span class="RktSym">destination</span>, meaning <span class="RktSym">find-path</span> itself
|
|
cannot construct such a path either. In the second case, the auxiliary
|
|
function found a path, but <span class="RktSym">find-path</span> must still add
|
|
<span class="RktSym">origination</span> to the front of this path because <span class="RktSym">candidate</span>
|
|
starts with one of <span class="RktSym">origination</span>’s neighbors, not
|
|
<span class="RktSym">origination</span> itself as agreed upon above.</div></p><p><div class="SIntrapara"><a name="(idx._fsm._(gentag._672._fsm))"></a>
|
|
<a name="(idx._fsm._(gentag._673._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._path%29" class="techoutside" data-pltdoc="x"><span class="techinside">Path</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a path from </span><span class="RktSym">origination</span><span class="RktCmt"> to </span><span class="RktSym">destination</span><span class="RktCmt"> in </span><span class="RktSym">G</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">if there is no path, the function produces </span><span class="RktVal">#false</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">next</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbors</span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">candidate</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktSym">next</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktSym">origination</span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt">] </span><a href="part_five.html#%28tech._fsm._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._path%29" class="techoutside" data-pltdoc="x"><span class="techinside">Path</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a path from some node on </span><span class="RktSym">lo-Os</span><span class="RktCmt"> to </span><span class="RktSym">D</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">if there is no path, the function produces </span><span class="RktVal">#false</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktSym">lo-Os</span><span class="hspace"> </span><span class="RktSym">D</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">lo-Os</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">candidate</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">lo-Os</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">D</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">lo-Os</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">D</span><span class="hspace"> </span><span class="RktSym">G</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym">candidate</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._fsm._(figure._fig~3afind-path-code))" x-target-lift="Figure"></a>Figure 169: </span>Finding a path in a graph</span></p></blockquote></div></p><p><a href="part_five.html#%28counter._fsm._%28figure._fig~3afind-path-code%29%29" data-pltdoc="x">Figure <span class="FigureRef">169</span></a> contains the complete definition of
|
|
<span class="RktSym">find-path</span>. It also contains a definition of
|
|
<span class="RktSym">find-path/list</span>, which processes its first argument via <a name="(idx._fsm._(gentag._674._fsm))"></a>structural
|
|
recursion. For each node in the list, <span class="RktSym">find-path/list</span> uses
|
|
<span class="RktSym">find-path</span> to check for a path. If <span class="RktSym">find-path</span> indeed
|
|
produces a path, that path is its answer. Otherwise,
|
|
<span class="RktSym">find-path/list</span> backtracks.</p><p><span style="font-weight: bold">Note</span> <a href="part_four.html#%28part._sec~3abtrees%29" data-pltdoc="x">Trees</a> discusses backtracking in the structural
|
|
world. A particularly good example is the function that searches blue-eyed
|
|
ancestors in a family tree. When the function encounters a node, it first
|
|
searches one branch of the family tree, say the father’s, and if this
|
|
search produces <span class="RktVal">#false</span>, it searches the other half. Since graphs
|
|
generalize trees, comparing this function with <span class="RktSym">find-path</span> is an
|
|
instructive exercise. <span style="font-weight: bold">End</span></p><p>Lastly, we need to check whether <span class="RktSym">find-path</span> produces an answer for
|
|
all possible inputs. It is relatively easy to check that, when given the
|
|
graph in <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a> and any two nodes in this graph,
|
|
<span class="RktSym">find-path</span> always produces some answer. Stop! Solve the next
|
|
exercise before you read on.</p><p><a name="(counter._fsm._(exercise._ex~3afind-path2))"></a><span style="font-weight: bold">Exercise</span> 472. Develop a test for <span class="RktSym">find-path</span> on the inputs
|
|
<span class="RktVal">'</span><span class="RktVal">A</span>, <span class="RktVal">'</span><span class="RktVal">G</span>, and <span class="RktSym">sample-graph</span>.</p><p>Take a look at <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>. Which path will the function find? Why?</p><p>Design <span class="RktSym">test-on-all-nodes</span>, a function that consumes a graph
|
|
<span class="RktSym">g</span> and determines whether there is a path between every pair of nodes. <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afind-path2%29%29" class="ex-end" data-pltdoc="x"></a></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_229.png" alt="image" width="606" height="206"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._fsm._(figure._fig~3acyclic-graph))" x-target-lift="Figure"></a>Figure 170: </span>A directed graph with cycle</span></p></blockquote><p>For other graphs, however, <span class="RktSym">find-path</span> may not terminate for certain
|
|
pairs of nodes. Consider the graph in <a href="part_five.html#%28counter._fsm._%28figure._fig~3acyclic-graph%29%29" data-pltdoc="x">figure <span class="FigureRef">170</span></a>.</p><p>Stop! Define <span class="RktSym">cyclic-graph</span> to represent the graph in this figure.</p><p><div class="SIntrapara">Compared to <a href="part_five.html#%28counter._fsm._%28figure._fig~3agraph%29%29" data-pltdoc="x">figure <span class="FigureRef">168</span></a>, this new graph contains only one extra
|
|
edge, from <span style="font-style: italic">C</span> to <span style="font-style: italic">B</span>. This seemingly small addition, though,
|
|
allows us to start a search in a node and to return to the same
|
|
node. Specifically, it is possible to move from <span style="font-style: italic">B</span> to <span style="font-style: italic">E</span> to
|
|
<span style="font-style: italic">C</span> and back to <span style="font-style: italic">B</span>. Indeed, when <span class="RktSym">find-path</span> is applied
|
|
to <span class="RktVal">'</span><span class="RktVal">B</span>, <span class="RktVal">'</span><span class="RktVal">D</span>, and this graph, it fails to stop, as
|
|
a hand-evaluation confirms:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">F</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">F</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path/list</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-path</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktSym">cyclic-graph</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._....%29%29" class="RktStxLink" data-pltdoc="x">..</a></span></td></tr></table></blockquote></div><div class="SIntrapara">The hand-evaluation shows that after seven applications of
|
|
<span class="RktSym">find-path</span> and <span class="RktSym">find-path/list</span>, ISL+ must evaluate the
|
|
exact same expression that it started with.<span class="refelem"><span class="refcolumn"><span class="refcontent">You know only
|
|
one exception to this rule: <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._random%29%29" class="RktValLink" data-pltdoc="x">random</a></span>.</span></span></span> Since the same input triggers
|
|
the same evaluation for any function, <span class="RktSym">find-path</span> does not
|
|
terminate for these inputs.</div></p><p>In summary, the <a name="(idx._fsm._(gentag._675._fsm))"></a><span style="font-weight: bold">termination</span> argument goes like this. If some given
|
|
graph is free of cycles, <span class="RktSym">find-path</span> produces some output for any
|
|
given inputs. After all, every path can only contain a finite number of
|
|
nodes, and the number of paths is finite, too. The function therefore either
|
|
exhaustively inspects all solutions starting from some given node or finds
|
|
a path from the origination to the destination node. If, however, a graph
|
|
contains a cycle, that is, a path from some node back to itself,
|
|
<span class="RktSym">find-path</span> may not produce a result for some inputs.</p><p>The next part presents a program design technique that addresses just this
|
|
kind of problem. In particular, it presents a variant of <span class="RktSym">find-path</span>
|
|
that can deal with cycles in a graph.</p><p><a name="(counter._fsm._(exercise._ex~3afind-path4))"></a><span style="font-weight: bold">Exercise</span> 473. Test <span class="RktSym">find-path</span> on <span class="RktVal">'</span><span class="RktVal">B</span>,
|
|
<span class="RktVal">'</span><span class="RktVal">C</span>, and the graph in <a href="part_five.html#%28counter._fsm._%28figure._fig~3acyclic-graph%29%29" data-pltdoc="x">figure <span class="FigureRef">170</span></a>. Also use
|
|
<span class="RktSym">test-on-all-nodes</span> from <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afind-path2%29%29" data-pltdoc="x">exercise 472</a> on this graph. <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afind-path4%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._fsm._(exercise._ex~3afind-path5))"></a><span style="font-weight: bold">Exercise</span> 474. Redesign the <span class="RktSym">find-path</span> program as a
|
|
single function. <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afind-path5%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._fsm._(exercise._ex~3afind-path6))"></a><span style="font-weight: bold">Exercise</span> 475. Redesign <span class="RktSym">find-path/list</span> so that it
|
|
uses an existing list abstraction from <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list%29%29" data-pltdoc="x">figures <span class="FigureRef">95</span></a> and <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list2%29%29" data-pltdoc="x"><span class="FigureRef">96</span></a> instead of explicit <a name="(idx._fsm._(gentag._676._fsm))"></a>structural
|
|
recursion. <span style="font-weight: bold">Hint</span> Read the documentation for Racket’s
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Fmap..rkt%29._ormap%29%29" class="RktValLink" data-pltdoc="x">ormap</a></span>. How does it differ from ISL+’s <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate.html#%28def._htdp-intermediate._%28%28lib._lang%2Fhtdp-intermediate..rkt%29._ormap%29%29" class="RktValLink" data-pltdoc="x">ormap</a></span> function?
|
|
Would the former be helpful here? <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afind-path6%29%29" class="ex-end" data-pltdoc="x"></a></p><p><span style="font-weight: bold">Note on Data Abstraction</span> You may have noticed that the <span class="RktSym">find-path</span>
|
|
function does not need to know how <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a> is defined. As long as you
|
|
provide a correct <span class="RktSym">neighbors</span> function for <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a>,
|
|
<span class="RktSym">find-path</span> works perfectly fine. In short, the <span class="RktSym">find-path</span>
|
|
program uses <span style="font-weight: bold">data abstraction</span>.</p><p>As <a href="part_three.html" data-pltdoc="x">Abstraction</a> says, data abstraction works just like function
|
|
abstraction. Here you could create a function <span class="RktSym">abstract-find-path</span>,
|
|
which would consume one more parameter than <span class="RktSym">find-path</span>:
|
|
<span class="RktSym">neighbors</span>. As long as you always handed
|
|
<span class="RktSym">abstract-find-path</span> a graph <span class="RktSym">G</span> from <a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a> and the
|
|
matching <span class="RktSym">neighbors</span> function, it would process the graph
|
|
properly. While the extra parameter suggests abstraction in the
|
|
conventional sense, the required relationship between two of the
|
|
parameters—<wbr></wbr><span class="RktSym">G</span> and <span class="RktSym">neighbors</span>—<wbr></wbr>really means that
|
|
<span class="RktSym">abstract-find-path</span> is also abstracted over the definition of
|
|
<a href="part_five.html#%28tech._fsm._graph%29" class="techoutside" data-pltdoc="x"><span class="techinside">Graph</span></a>. Since the latter is a data definition, the idea is dubbed
|
|
data abstraction.</p><p>When programs grow large, data abstraction becomes a critical tool for the
|
|
construction of a program’s components. The next volume in the <span class="emph">How to
|
|
Design</span> series addresses this idea in depth; the next section illustrates
|
|
the idea with another example. <span style="font-weight: bold">End</span></p><p><a name="(counter._fsm._(exercise._ex~3afsm-match))"></a><span style="font-weight: bold">Exercise</span> 476. <a href="part_two.html#%28part._sec~3asec-fsm-list%29" data-pltdoc="x">Finite State Machines</a> poses a problem
|
|
concerning finite state machines and strings but immediately defers to this
|
|
chapter because the solution calls for generative recursion. You have now
|
|
acquired the design knowledge needed to tackle the problem.</p><p>Design the function <span class="RktSym">fsm-match</span>. It consumes the data representation
|
|
of a finite state machine and a string. It produces <span class="RktVal">#true</span> if the
|
|
sequence of characters in the string causes the finite state machine to
|
|
transition from an initial state to a final state.</p><p><div class="SIntrapara">Since this problem is about the design of generative recursive functions,
|
|
we provide the essential data definition and a data example:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">transition</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">current</span><span class="hspace"> </span><span class="RktSym">key</span><span class="hspace"> </span><span class="RktSym">next</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">fsm</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">initial</span><span class="hspace"> </span><span class="RktSym">transitions</span><span class="hspace"> </span><span class="RktSym">final</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._fsm._fsm)"></a><span style="font-style: italic">FSM</span><span class="RktCmt"> is a structure:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-fsm</span><span class="stt"> </span><a href="part_five.html#%28tech._fsm._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="stt"> </span><span class="RktPn">[</span><span class="RktSym">List-of</span><span class="stt"> </span><a href="part_five.html#%28tech._fsm._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a><span class="RktPn">]</span><span class="stt"> </span><a href="part_five.html#%28tech._fsm._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._fsm._1transition)"></a><span style="font-style: italic">1Transition</span><span class="RktCmt"> is a structure:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-transition</span><span class="stt"> </span><a href="part_five.html#%28tech._fsm._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="stt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="stt"> </span><a href="part_five.html#%28tech._fsm._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._fsm._fsm._state)"></a><span style="font-style: italic">FSM-State</span><span class="RktCmt"> is </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">.</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">data example: see </span><a href="part_one.html#%28counter._%28exercise._ex~3afsm%29%29" data-pltdoc="x">exercise 109</a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fsm-a-bc*-d</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-fsm</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"AA"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-transition</span><span class="hspace"> </span><span class="RktVal">"AA"</span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-transition</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="hspace"> </span><span class="RktVal">"b"</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-transition</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="hspace"> </span><span class="RktVal">"c"</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-transition</span><span class="hspace"> </span><span class="RktVal">"BC"</span><span class="hspace"> </span><span class="RktVal">"d"</span><span class="hspace"> </span><span class="RktVal">"DD"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"DD"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The data example corresponds to the regular expression <span class="stt">a (b|c)* d</span>. As
|
|
mentioned in <a href="part_one.html#%28counter._%28exercise._ex~3afsm%29%29" data-pltdoc="x">exercise 109</a>, <span class="RktVal">"acbd"</span>, <span class="RktVal">"ad"</span>, and
|
|
<span class="RktVal">"abcd"</span> are examples of acceptable strings; <span class="RktVal">"da"</span>,
|
|
<span class="RktVal">"aa"</span>, or <span class="RktVal">"d"</span> do not match.</div></p><p><div class="SIntrapara">In this context, you are designing the following function: <a name="(idx._fsm._(gentag._677._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._fsm._fsm%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">an-fsm</span><span class="RktCmt"> recognize the given string</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fsm-match?</span><span class="hspace"> </span><span class="RktSym">an-fsm</span><span class="hspace"> </span><span class="RktSym">a-string</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara"><span style="font-weight: bold">Hint</span> Design the necessary auxiliary function locally to
|
|
the <span class="RktSym">fsm-match?</span> function. In this context, represent the problem as a pair of
|
|
parameters: the current state of the finite state machine and the remaining
|
|
list of <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s. <a href="part_five.html#%28counter._fsm._%28exercise._ex~3afsm-match%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(idx._fsm._(gentag._678._fsm))"></a>
|
|
<a name="(idx._fsm._(gentag._679._fsm))"></a>
|
|
<a name="(idx._fsm._(gentag._680._fsm))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> X]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates a list of all rearrangements of the items in w</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">arrangements</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktSym">others</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">without-item</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">arrangements</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._remove%29%29" class="RktValLink" data-pltdoc="x">remove</a></span><span class="hspace"> </span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">add-item-to-front</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">without-item</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktSym">add-item-to-front</span><span class="hspace"> </span><span class="RktSym">others</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">]] -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside"><span class="techoutside"><span class="techinside">Boolean</span></span></span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">are the words "rat", "art", and "tar" members of the given list?</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">all-words-from-rat?</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member%29%29" class="RktValLink" data-pltdoc="x">member</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktVal">"rat"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member%29%29" class="RktValLink" data-pltdoc="x">member</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktVal">"art"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member%29%29" class="RktValLink" data-pltdoc="x">member</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktVal">"tar"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">w</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-satisfied%29%29" class="RktStxLink" data-pltdoc="x">check-satisfied</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">arrangements</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"r"</span><span class="hspace"> </span><span class="RktVal">"a"</span><span class="hspace"> </span><span class="RktVal">"t"</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">all-words-from-rat?</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._fsm._(figure._fig~3apermutation-gen))" x-target-lift="Figure"></a>Figure 171: </span>A definition of <span class="RktSym">arrangements</span> using generative recursion</span></p></blockquote></div></p><p><div class="SIntrapara"><a name="(counter._fsm._(exercise._ex~3apermutation-gen))"></a><span style="font-weight: bold">Exercise</span> 477. Inspect the function definition of
|
|
<span class="RktSym">arrangements</span> in <a href="part_five.html#%28counter._fsm._%28figure._fig~3apermutation-gen%29%29" data-pltdoc="x">figure <span class="FigureRef">171</span></a>. The figure displays
|
|
a generative-recursive solution of the extended design problem covered by
|
|
<a href="part_two.html#%28part._sec~3apermute%29" data-pltdoc="x">Word Games, the Heart of the Problem</a>, namely<span class="refelem"><span class="refcolumn"><span class="refcontent">We thank Mark Engelberg for
|
|
suggesting this exercise.</span></span></span>
|
|
</div><div class="SIntrapara"><blockquote><p>given a word, create all possible rearrangements
|
|
of the letters.</p></blockquote></div><div class="SIntrapara">The extended exercise is a direct guide to the <a name="(idx._fsm._(gentag._681._fsm))"></a>structurally recursive
|
|
design of the main function and two auxiliaries, where the design of the
|
|
latter requires the creation of two more helper functions. In contrast,
|
|
<a href="part_five.html#%28counter._fsm._%28figure._fig~3apermutation-gen%29%29" data-pltdoc="x">figure <span class="FigureRef">171</span></a> uses the power of generative
|
|
recursion—<wbr></wbr>plus <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span>—<wbr></wbr>to
|
|
define the same program as a single function definition.</div></p><p>Explain the design of the generative-recursive version of
|
|
<span class="RktSym">arrangements</span>. Answer all questions that the design recipe for
|
|
generative recursion poses, including the question of termination.</p><p>Does <span class="RktSym">arrangements</span> in <a href="part_five.html#%28counter._fsm._%28figure._fig~3apermutation-gen%29%29" data-pltdoc="x">figure <span class="FigureRef">171</span></a> create the
|
|
same lists as the solution of <a href="part_two.html#%28part._sec~3apermute%29" data-pltdoc="x">Word Games, the Heart of the Problem</a>? <a href="part_five.html#%28counter._fsm._%28exercise._ex~3apermutation-gen%29%29" class="ex-end" data-pltdoc="x"></a></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_230.png" alt="image" width="252.0" height="252.0"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._fsm._(figure._fig~3aqueens))" x-target-lift="Figure"></a>Figure 172: </span>A chess board with a single queen and the positions it threatens</span></p></blockquote><h4>29.2<tt> </tt><a name="(part._sec~3aproj-backtrack)"></a>Project: Backtracking</h4><p>The <span style="font-style: italic">n</span> queens puzzle is a famous problem from the world of chess that
|
|
also illustrates the applicability of backtracking in a natural way. For
|
|
our purposes, a chess board is a grid of <span style="font-style: italic">n</span> by <span style="font-style: italic">n</span> squares. The
|
|
queen is a game piece that can move in a horizontal,
|
|
vertical,<span class="refelem"><span class="refcolumn"><span class="refcontent">We thank Mark Engelberg for his reformulation of
|
|
this section.</span></span></span> or diagonal direction arbitrarily far without “jumping”
|
|
over another piece. We say that a queen <span style="font-style: italic">threatens</span> a square if it
|
|
is on the square or can move to it. <a href="part_five.html#%28counter._fsm._%28figure._fig~3aqueens%29%29" data-pltdoc="x">Figure <span class="FigureRef">172</span></a> illustrates the
|
|
notion in a graphical manner. The queen is in the second column and sixth
|
|
row. The solid lines radiating out from the queen go through all those
|
|
squares that are threatened by the queen.</p><p>The classical queens problem is to place <span style="font-style: italic"></span>8<span style="font-style: italic"></span> queens on an
|
|
<span style="font-style: italic"></span>8<span style="font-style: italic"></span> by <span style="font-style: italic"></span>8<span style="font-style: italic"></span> chess board such that the queens on the board don’t
|
|
threaten each other. Computer scientists generalize the problem and ask
|
|
whether it is possible to place <span style="font-style: italic">n</span> queens on a <span style="font-style: italic">n</span> by <span style="font-style: italic">n</span>,
|
|
chess board such that the queens don’t pose a threat to
|
|
each other.</p><p>For <span style="font-style: italic">n = </span>2<span style="font-style: italic"></span>, the complete puzzle obviously has no solution. A queen
|
|
placed on any of the four squares threatens all remaining squares.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_231.png" alt="image" width="99.5" height="99.5"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_232.png" alt="image" width="99.5" height="99.5"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_233.png" alt="image" width="99.5" height="99.5"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aqueens-non-solutions))" x-target-lift="Figure"></a>Figure 173: </span>Three queen configurations for a 3 by 3 chess board</span></p></blockquote><p>There is also no solution for <span style="font-style: italic">n = </span>3<span style="font-style: italic"></span>.
|
|
<a href="part_five.html#%28counter._%28figure._fig~3aqueens-non-solutions%29%29" data-pltdoc="x">Figure <span class="FigureRef">173</span></a> presents all different placements of
|
|
two queens, that is, solutions for <span style="font-style: italic">k = </span>3<span style="font-style: italic"></span> and <span style="font-style: italic">n = </span>2<span style="font-style: italic"></span>. In each
|
|
case, the left queen occupies a square in the left column while a second
|
|
queen is placed in one of two squares that the first one does not
|
|
threaten. The placement of a second queen threatens all remaining,
|
|
unoccupied squares, meaning it is impossible to place a third queen.</p><p><a name="(counter._(exercise._ex~3a3queens))"></a><span style="font-weight: bold">Exercise</span> 478. You can also place the first queen in all
|
|
squares of the top-most row, the right-most column, and the bottom-most
|
|
row. Explain why all of these solutions are just like the three scenarios
|
|
depicted in <a href="part_five.html#%28counter._%28figure._fig~3aqueens-non-solutions%29%29" data-pltdoc="x">figure <span class="FigureRef">173</span></a>.</p><p>This leaves the central square. Is it possible to place even a second queen
|
|
after you place one on the central square of a <span style="font-style: italic"></span>3<span style="font-style: italic"></span> by <span style="font-style: italic"></span>3<span style="font-style: italic"></span> board? <a href="part_five.html#%28counter._%28exercise._ex~3a3queens%29%29" class="ex-end" data-pltdoc="x"></a></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td valign="top"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_234.png" alt="image" width="128.0" height="128.0"/></p></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_235.png" alt="image" width="160.5" height="160.5"/></p></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aqueens-solutions))" x-target-lift="Figure"></a>Figure 174: </span>Solutions for the <span style="font-style: italic">n</span> queens puzzle for 4 by 4 and 5 by 5 boards</span></p></blockquote><p><a href="part_five.html#%28counter._%28figure._fig~3aqueens-solutions%29%29" data-pltdoc="x">Figure <span class="FigureRef">174</span></a> displays two solutions for the <span style="font-style: italic">n</span> queens
|
|
puzzle: the left one is for <span style="font-style: italic">n = </span>4<span style="font-style: italic"></span>, the right one for <span style="font-style: italic">n</span><span style="font-style: italic">
|
|
</span><span style="font-style: italic">= </span>5<span style="font-style: italic"></span>. The figure shows how in each case a solution has one queen in
|
|
each row and column, which makes sense because a queen threatens
|
|
the entire row and column that radiate out from its square.</p><p>Now that we have conducted a sufficiently detailed analysis, we can proceed
|
|
to the solution phase. The analysis suggests several ideas:</p><p><div class="SIntrapara"><ol><li><p>The problem is about placing one queen at a time. When we place a queen on
|
|
a board, we can mark the corresponding rows, columns, and diagonals as unusable
|
|
for other queens.</p></li><li><p>For another queen, we consider only nonthreatened spots.</p></li><li><p>Just in case this first choice of a spot leads to problems later, we
|
|
remember what other squares are feasible for placing this queen.</p></li><li><p>If we are supposed to place a queen on a board but no safe squares
|
|
are left, we backtrack to a previous point in the process where we chose
|
|
one square over another and try one of the remaining squares.</p></li></ol></div><div class="SIntrapara">In short, this solution process is like the “find a path” algorithm.</div></p><p><div class="SIntrapara">Moving from the process description to a designed algorithm clearly calls
|
|
for two data representations: one for the chess boards and one for
|
|
positions on the board. Let’s start with the latter:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">QUEENS</span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._qp)"></a><span style="font-style: italic">QP</span><span class="RktCmt"> is a structure:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="stt"> </span><a href="part_five.html#%28tech._ci%29" class="techoutside" data-pltdoc="x"><span class="techinside">CI</span></a><span class="stt"> </span><a href="part_five.html#%28tech._ci%29" class="techoutside" data-pltdoc="x"><span class="techinside">CI</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._ci)"></a><span style="font-style: italic">CI</span><span class="RktCmt"> is an </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> in [</span><span class="RktVal">0</span><span class="RktCmt">,</span><span class="RktSym">QUEENS</span><span class="RktCmt">).</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="stt"> </span><span class="RktSym">r</span><span class="stt"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="RktCmt"> denotes the square at </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the </span><span class="RktSym">r</span><span class="RktCmt">-th row and </span><span class="RktSym">c</span><span class="RktCmt">-th column</span></td></tr></table></blockquote></div><div class="SIntrapara">After all, the chess board basically dictates the choice.</div></p><p>The definition for <a href="part_five.html#%28tech._ci%29" class="techoutside" data-pltdoc="x"><span class="techinside">CI</span></a> could use [<span class="RktVal">1</span>,<span class="RktSym">QUEENS</span>] instead of
|
|
[<span class="RktVal">0</span>, <span class="RktSym">QUEENS</span>), but the two definitions are basically
|
|
equivalent and counting up from <span class="RktVal">0</span> is what programmers
|
|
do. Similarly, the so-called algebraic notation for chess positions
|
|
uses the letters <span class="RktVal">'</span><span class="RktVal">a</span> through <span class="RktVal">'</span><span class="RktVal">h</span> for one of the board’s
|
|
dimensions, meaning <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a> could have used <a href="part_five.html#%28tech._ci%29" class="techoutside" data-pltdoc="x"><span class="techinside">CI</span></a>s and such
|
|
letters. Again, the two are roughly equivalent and with natural numbers it is
|
|
easier in ISL+ to create many positions than with letters.</p><p><a name="(counter._(exercise._ex~3aqueens-threatened))"></a><span style="font-weight: bold">Exercise</span> 479. Design the <span class="RktSym">threatening?</span>
|
|
function. It consumes two <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s and determines whether queens placed
|
|
on the two respective squares would threaten each other.</p><p><span style="font-weight: bold">Domain Knowledge</span> (1) Study <a href="part_five.html#%28counter._fsm._%28figure._fig~3aqueens%29%29" data-pltdoc="x">figure <span class="FigureRef">172</span></a>. The queen in
|
|
this figure threatens all squares on the horizontal, the vertical, and the
|
|
diagonal lines. Conversely, a queen on any square on these lines threatens
|
|
the queen.</p><p>(2) Translate your insights into mathematical conditions that relate the
|
|
squares’ coordinates to each other. For example, all squares on a
|
|
horizontal have the same y-coordinate. Similarly, all squares on one
|
|
diagonal have coordinates whose sums are the same. Which diagonal is that?
|
|
For the other diagonal, the differences between the two coordinates remain
|
|
the same. Which diagonal does this idea describe?</p><p><span style="font-weight: bold">Hint</span> Once you have figured out the domain knowledge, formulate a
|
|
<a name="(idx._(gentag._682))"></a>test suite that covers horizontals, verticals, and diagonals. Don’t
|
|
forget to include arguments for which <span class="RktSym">threatening?</span> must
|
|
produce <span class="RktVal">#false</span>. <a href="part_five.html#%28counter._%28exercise._ex~3aqueens-threatened%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aqueen-render))"></a><span style="font-weight: bold">Exercise</span> 480. Design <span class="RktSym">render-queens</span>. The function
|
|
consumes a natural number <span class="RktSym">n</span>, a list of <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s, and an
|
|
<a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a>. It produces an image of an <span class="RktSym">n</span> by <span class="RktSym">n</span> chess
|
|
board with the given image placed according to the given <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s.</p><p>You may wish to look for an image for a chess queen on-line or create a
|
|
simplistic one with the available image functions. <a href="part_five.html#%28counter._%28exercise._ex~3aqueen-render%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">As for a data representation for <a name="(tech._board)"></a><span style="font-style: italic">Board</span>s, we postpone this step
|
|
until we know how the algorithm implements the process. Doing so is another
|
|
exercise in data abstraction. Indeed, a data definition for <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a>
|
|
isn’t even necessary to state the signature for the algorithm proper:
|
|
<a name="(idx._(gentag._683))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a solution to the </span><span class="RktSym">n</span><span class="RktCmt"> queens problem </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">data example: [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">4QUEEN-SOLUTION-2</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">n-queens</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The complete puzzle is about finding a placement for <span style="font-style: italic">n</span> queens on an
|
|
<span style="font-style: italic">n</span> by <span style="font-style: italic">n</span> chess board. So clearly, the algorithm consumes
|
|
nothing else but a natural number, and it produces a representation for the
|
|
<span style="font-style: italic">n</span> queen placements—<wbr></wbr>if a solution exists. The latter can be
|
|
represented with a list of <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s, which is why we choose
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">] or </span><span class="RktVal">#false</span></p></blockquote></div><div class="SIntrapara">as the result. Naturally, <span class="RktVal">#false</span> represents the failure to find a solution.</div></p><p><div class="SIntrapara">The next step is to develop examples and to formulate them as tests. We
|
|
know that <span class="RktSym">n-queens</span> must fail when given <span class="RktVal">2</span> or
|
|
<span class="RktVal">3</span>. For <span class="RktVal">4</span>, there are two solutions with real boards and
|
|
four identical queens. <a href="part_five.html#%28counter._%28figure._fig~3aqueens-solutions%29%29" data-pltdoc="x">Figure <span class="FigureRef">174</span></a> shows one of
|
|
them, on the left, and the other one is this:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_236.png" alt="image" width="130.0" height="130.0"/></p></blockquote></div><div class="SIntrapara">In terms of data representations, however, there are many different ways to
|
|
represent these two images. <a href="part_five.html#%28counter._%28figure._fig~3asolutions-for-4%29%29" data-pltdoc="x">Figure <span class="FigureRef">175</span></a> sketches
|
|
some. Fill in the rest.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._684))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a solution to the </span><span class="RktSym">n</span><span class="RktCmt"> queens problem </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-member-of%29%29" class="RktStxLink" data-pltdoc="x">check-member-of</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">n-queens</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">3-2</span><span class="hspace"> </span><span class="RktSym">2-0</span><span class="hspace"> </span><span class="RktSym">1-3</span><span class="hspace"> </span><span class="RktSym">0-1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">n-queens</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">place-queens</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">board0</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asolutions-for-4))" x-target-lift="Figure"></a>Figure 175: </span>Solutions for the 4 queens puzzle</span></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3aqueen-property-testing))"></a><span style="font-weight: bold">Exercise</span> 481. The tests in
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asolutions-for-4%29%29" data-pltdoc="x">figure <span class="FigureRef">175</span></a> are awful. No real-world programmer
|
|
ever spells out all these possible outcomes.</p><p><div class="SIntrapara">One solution is to use property testing again. Design the
|
|
<span class="RktSym">n-queens-solution?</span> function, which consumes a natural number
|
|
<span class="RktSym">n</span> and produces a predicate on queen placements that determines
|
|
whether a given placement is a solution to an <span class="RktSym">n</span> queens puzzle:
|
|
</div><div class="SIntrapara"><ul><li><p>A solution for an <span class="RktSym">n</span> queens puzzle must have length <span class="RktSym">n</span><span class="RktMeta"></span>.</p></li><li><p>A <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a> on such a list may not threaten any other, distinct <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>.</p></li></ul></div><div class="SIntrapara">Once you have tested this predicate, use it and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-satisfied%29%29" class="RktStxLink" data-pltdoc="x">check-satisfied</a></span> to
|
|
formulate the tests for <span class="RktSym">n-queens</span>. <a name="(idx._(gentag._685))"></a></div></p><p><div class="SIntrapara">An alternative solution is to understand the lists of <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s as sets.
|
|
If two lists contain the same <a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a>s in different order, they are
|
|
equivalent as the figure suggests. Hence you could formulate the test for
|
|
<span class="RktSym">n-queens</span> as <a name="(idx._(gentag._686))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">] -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">is the result equal [as a set] to one of two lists</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">is-queens-result?</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">set=?</span><span class="hspace"> </span><span class="RktSym">4QUEEN-SOLUTION-1</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">set=?</span><span class="hspace"> </span><span class="RktSym">4QUEEN-SOLUTION-2</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Design the function <span class="RktSym">set=?</span>. It consumes two lists and determines
|
|
whether they contain the same items—<wbr></wbr>regardless of order. <a href="part_five.html#%28counter._%28exercise._ex~3aqueen-property-testing%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aqueens-solve))"></a><span style="font-weight: bold">Exercise</span> 482. The key idea to is to design a function that
|
|
places <span style="font-style: italic">n</span> queens on a chess board that may already contain some
|
|
queens: <a name="(idx._(gentag._687))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">places </span><span class="RktSym">n</span><span class="RktCmt"> queens on board; otherwise, returns </span><span class="RktVal">#false</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">place-queens</span><span class="hspace"> </span><span class="RktSym">a-board</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara"><a href="part_five.html#%28counter._%28figure._fig~3asolutions-for-4%29%29" data-pltdoc="x">Figure <span class="FigureRef">175</span></a> already refers to this function in the
|
|
definition of <span class="RktSym">n-queens</span>.</div></p><p><div class="SIntrapara">Design the <span class="RktSym">place-queens</span> algorithm. Assume you have the following
|
|
functions to deal with <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a>s: <a name="(idx._(gentag._688))"></a> <a name="(idx._(gentag._689))"></a><a name="(idx._(gentag._690))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates the initial </span><span class="RktSym">n</span><span class="RktCmt"> by </span><span class="RktSym">n</span><span class="RktCmt"> board</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">board0</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt"> -> </span><a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">places a queen at </span><span class="RktSym">qp</span><span class="RktCmt"> on </span><span class="RktSym">a-board</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-queen</span><span class="hspace"> </span><span class="RktSym">a-board</span><span class="hspace"> </span><span class="RktSym">qp</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">a-board</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_five.html#%28tech._qp%29" class="techoutside" data-pltdoc="x"><span class="techinside">QP</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds spots where it is still safe to place a queen</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-open-spots</span><span class="hspace"> </span><span class="RktSym">a-board</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The first function is used in <a href="part_five.html#%28counter._%28figure._fig~3asolutions-for-4%29%29" data-pltdoc="x">figure <span class="FigureRef">175</span></a> to create
|
|
the initial board representation for <span class="RktSym">place-queens</span>. You will need
|
|
the other two to describe the generative steps for the algorithm. <a href="part_five.html#%28counter._%28exercise._ex~3aqueens-solve%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>You cannot confirm yet that your solution to the preceding exercise works
|
|
because it relies on an extensive wish list. It calls for a data
|
|
representation of <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a>s that supports the three functions on the
|
|
wish list. This, then, is your remaining problem.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aqueens-board))"></a><span style="font-weight: bold">Exercise</span> 483. Develop a data definition for <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a> and
|
|
design the three functions specified in <a href="part_five.html#%28counter._%28exercise._ex~3aqueens-solve%29%29" data-pltdoc="x">exercise 482</a>. Consider
|
|
the following ideas:
|
|
</div><div class="SIntrapara"><ul><li><p>a <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a> collects those positions where a queen can still be
|
|
placed;</p></li><li><p>a <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a> contains the list of positions where a queen has been
|
|
placed;</p></li><li><p>a <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a> is a grid of <span class="RktSym">n</span> by <span class="RktSym">n</span> squares, each
|
|
possibly occupied by a queen. Use a structure with three fields
|
|
to represent a square: one for <span class="RktSym">x</span>,
|
|
one for <span class="RktSym">y</span>, and a third one saying whether the square is threatened.</p></li></ul></div><div class="SIntrapara">Use one of the above ideas to solve this exercise.</div></p><p><span style="font-weight: bold">Challenge</span> Use all three ideas to come up with three different data
|
|
representations of <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a>. Abstract your solution to
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3aqueens-solve%29%29" data-pltdoc="x">exercise 482</a> and confirm that it works with any of your data
|
|
representations of <a href="part_five.html#%28tech._board%29" class="techoutside" data-pltdoc="x"><span class="techinside">Board</span></a>. <a href="part_five.html#%28counter._%28exercise._ex~3aqueens-board%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>30<tt> </tt><a name="(part._ch~3asummary5)"></a>Summary</h3><p>This fifth part of the book introduces the idea of <span style="font-style: italic">eureka!</span> into
|
|
program design. Unlike the <a name="(idx._(gentag._691))"></a>structural design of the first four parts,
|
|
<span style="font-style: italic">eureka!</span> design starts from an idea of how the program should solve
|
|
a problem or process data that represents a problem. Designing here means
|
|
coming up with a clever way to call a recursive function on a new kind of
|
|
problem that is like the given one but simpler.</p><p>Keep in mind that while we have dubbed it <a name="(idx._(gentag._692))"></a><span style="font-weight: bold">generative recursion</span>, most
|
|
computer scientists refer to these functions as <span style="font-weight: bold">algorithms</span>.</p><p><div class="SIntrapara">Once you have completed this part of the book, you will understand the following
|
|
about the design of generative recursion:
|
|
</div><div class="SIntrapara"><ol><li><p>The standard outline of the design recipe remains valid.</p></li><li><p>The major change concerns the coding step. It introduces four new
|
|
questions on going from the completely generic template for generative
|
|
recursion to a complete function. With two of these questions, you work out
|
|
the “trivial” parts of the solution process; and with the other two you
|
|
work out the generative solution step.</p></li><li><p>The minor change is about the <a name="(idx._(gentag._693))"></a>termination behavior of generative
|
|
recursive functions. Unlike structurally designed functions, algorithms may
|
|
not terminate for some inputs. This problem might be due to inherent
|
|
limitations in the idea or the translation of the idea into
|
|
code. Regardless, the future reader of your program deserves a warning
|
|
about potentially “bad” inputs.</p></li></ol></div></p><p>You will encounter some simple or well-known algorithms in your real-world
|
|
programming tasks, and you will be expected to cope. For truly clever
|
|
algorithms, software companies employ highly paid specialists,
|
|
domain experts, and mathematicians to work out the conceptual details
|
|
before they ask programmers to turn the concepts into programs. You must
|
|
also be prepared for this kind of task, and the best preparation is
|
|
practice.</p><div class="navsetbottom"><span class="navleft"><div class="nosearchform"></div> <span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="i4-5.html" title="backward to "Intermezzo 4: The Nature of Numbers"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "How to Design Programs, Second Edition"" data-pltdoc="x">up</a> <a href="i5-6.html" title="forward to "Intermezzo 5: The Cost of Computation"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div><script data-cfasync="false" src="../../cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script></body></html> |