307 lines
No EOL
126 KiB
HTML
307 lines
No EOL
126 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>Intermezzo 5: The Cost of Computation</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="tocviewlink" data-pltdoc="x">Generative Recursion</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html" class="tocviewselflink" 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></td><td><a href="i5-6.html" class="tocviewselflink" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right"></td><td><a href="i5-6.html#%28part._.Concrete_.Time__.Abstract_.Time%29" class="tocviewlink" data-pltdoc="x">Concrete Time, Abstract Time</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html#%28part._.The_.Definition_of__.On_the_.Order_.Of_%29" class="tocviewlink" data-pltdoc="x">The Definition of “On the Order Of”</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html#%28part._.Why_.Do_.Programs_.Use_.Predicates_and_.Selectors_%29" class="tocviewlink" data-pltdoc="x">Why Do Programs Use Predicates and Selectors?</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html#%28part._i5-6-fake%29" class="tocviewlink" data-pltdoc="x"></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="part_five.html" title="backward to "V Generative Recursion"" 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="part_six.html" title="forward to "VI Accumulators"" data-pltdoc="x">next →</a></span> </div><h3><a name="(part._i5-6)"></a>Intermezzo 5: The Cost of Computation</h3><table cellspacing="0" cellpadding="0"><tr><td><p><span class="hspace"> </span><a href="i5-6.html#%28part._.Concrete_.Time__.Abstract_.Time%29" class="toclink" data-pltdoc="x">Concrete Time, Abstract Time</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="i5-6.html#%28part._.The_.Definition_of__.On_the_.Order_.Of_%29" class="toclink" data-pltdoc="x">The Definition of “On the Order Of”</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="i5-6.html#%28part._.Why_.Do_.Programs_.Use_.Predicates_and_.Selectors_%29" class="toclink" data-pltdoc="x">Why Do Programs Use Predicates and Selectors?</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="i5-6.html#%28part._i5-6-fake%29" class="toclink" data-pltdoc="x"></a></p></td></tr></table><p><div class="SIntrapara">What do you know about program <span class="RktSym">f</span> once the following tests
|
|
succeed:
|
|
</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">f</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></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">f</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="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">f</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">8</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">If this question showed up on a standard test, you might respond with this:
|
|
</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">f</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._expt%29%29" class="RktValLink" data-pltdoc="x">expt</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">But nothing speaks against the following:
|
|
</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">f</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#%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">x</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">8</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="RktSym">x</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Tests tell you only that a program works as expected on some inputs.</div></p><p>In the same spirit, timing the evaluation of a program application for
|
|
specific inputs tells you how long it takes to compute the answers for
|
|
those inputs—<wbr></wbr>and nothing else.<span class="refelem"><span class="refcolumn"><span class="refcontent">You may also wish to reread
|
|
<a href="part_three.html#%28part._sec~3alocal-definitions%29" data-pltdoc="x">Local Definitions</a> and the discussion of integrity checks in
|
|
<a href="part_four.html#%28part._db._sec~3aproj-db%29" data-pltdoc="x">Project: Database</a>.</span></span></span> You may have two
|
|
programs—<wbr></wbr><span class="RktSym">prog-linear</span><span class="RktMeta"></span> and <span class="RktSym">prog-square</span><span class="RktMeta"></span>—<wbr></wbr>that compute the same answers when given
|
|
the same inputs, and you may find that for all chosen inputs, <span class="RktSym">prog-linear</span><span class="RktMeta"></span> always
|
|
computes the answer faster than <span class="RktSym">prog-square</span><span class="RktMeta"></span>. <a href="part_five.html#%28part._sec~3achoice%29" data-pltdoc="x">Making Choices</a> presents just
|
|
such a pair of programs: <span class="RktSym">gcd</span>, a <a name="(idx._(gentag._694))"></a>structurally recursive program,
|
|
and <span class="RktSym">gcd-generative</span>, an equivalent but generative-recursive
|
|
program. The timing comparison suggests that the latter is much faster
|
|
than the former.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img src="pict_237.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~3aperformance))" x-target-lift="Figure"></a>Figure 176: </span>A comparison of two running time expressions</span></p></blockquote><p>How confident are you that you wish to use <span class="RktSym">prog-linear</span><span class="RktMeta"></span> instead of
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>? Consider the graph in <a href="i5-6.html#%28counter._%28figure._fig~3aperformance%29%29" data-pltdoc="x">figure <span class="FigureRef">176</span></a>. In this
|
|
graph, the x-axis records the size of the input—<wbr></wbr>say, the length of
|
|
a list—<wbr></wbr>and the y-axis records the time it takes to compute the
|
|
answer for an input of a specific size. Assume that the straight line
|
|
represents the running time of <span class="RktSym">prog-linear</span><span class="RktMeta"></span> and the curved graph represents
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>. In the shaded region, <span class="RktSym">prog-linear</span><span class="RktMeta"></span> takes more time than
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>, but at the edge of this region the two graphs cross, and to
|
|
its right the performance of <span class="RktSym">prog-square</span><span class="RktMeta"></span> is worse than that of
|
|
<span class="RktSym">prog-linear</span><span class="RktMeta"></span>. If, for whatever reasons, you had evaluated the performance of
|
|
<span class="RktSym">prog-linear</span><span class="RktMeta"></span> and <span class="RktSym">prog-square</span><span class="RktMeta"></span> only for input sizes in the shaded region and if
|
|
your clients were to run your program mostly on inputs that fall in the
|
|
nonshaded region, you would be delivering the wrong program.</p><p>This intermezzo introduces the idea of <span style="font-style: italic">algorithmic analysis</span>,
|
|
which allows programmers to make general statements about a program’s
|
|
performance and everyone else about the growth of a function.
|
|
<span class="refelem"><span class="refcolumn"><span class="refcontent">We thank Prabhakar Ragde for sharing his notes on connecting
|
|
the first edition of this book with algorithmic analysis.</span></span></span>Any serious
|
|
programmer and scientist must eventually become thoroughly familiar with
|
|
this notion. It is the basis for analyzing performance attributes of
|
|
programs. To understand the idea properly, you will need to work through a
|
|
text book.</p><h3><a name="(part._.Concrete_.Time__.Abstract_.Time)"></a>Concrete Time, Abstract Time</h3><p><div class="SIntrapara"><a href="part_five.html#%28part._sec~3achoice%29" data-pltdoc="x">Making Choices</a> compares the running time of <span class="RktSym">gcd</span> and
|
|
<span class="RktSym">gcd-generative</span>. In addition, it argues that the latter is better
|
|
because it always uses fewer recursive steps than the former to compute
|
|
an answer. We use this idea as the starting point to analyze the
|
|
performance of <span class="RktSym">how-many</span>, a simple program from
|
|
<a href="part_two.html#%28part._ch~3adesign-lists%29" data-pltdoc="x">Designing with Self-Referential Data Definitions</a>: <a name="(idx._(gentag._695))"></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">how-many</span><span class="hspace"> </span><span class="RktSym">a-list</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">a-list</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="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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">a-list</span><span class="RktPn">)</span><span class="RktPn">)</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></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Suppose we want to know how long it takes to compute the length of some
|
|
unknown, non-empty list. Using the rules of computation from
|
|
<a href="i1-2.html" data-pltdoc="x">Intermezzo 1: Beginning Student Language</a>, we can look at this process as a series of algebraic
|
|
manipulations:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">how-many</span><span class="hspace"> </span><span class="RktSym">some-non-empty-list</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#%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">some-non-empty-list</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="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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">some-non-empty-list</span><span class="RktPn">)</span><span class="RktPn">)</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="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#%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="RktVal">#false</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#%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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">some-non-empty-list</span><span class="RktPn">)</span><span class="RktPn">)</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="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#%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="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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">some-non-empty-list</span><span class="RktPn">)</span><span class="RktPn">)</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="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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">some-non-empty-list</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The first step is to replace <span class="RktSym">a-list</span> in the definition of
|
|
<span class="RktSym">how-many</span> with the actual argument, <span class="RktSym">some-non-empty-list</span>, which
|
|
yields the 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> expression. Next we must 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#%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">some-non-empty-list</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">By assumption the result is <span class="RktVal">#false</span>. The question is how long it
|
|
takes to determine this result. While we don’t know the precise amount of
|
|
time, it is safe to say that checking on the constructor of a list takes a
|
|
small and fixed amount of time. Indeed, this assumption also holds for the
|
|
next step, when <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> checks what the value of the first condition
|
|
is. Since it is <span class="RktVal">#false</span>, the 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 is
|
|
dropped. Checking whether 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> line starts 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._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span>
|
|
is equally fast, which means we are left with
|
|
</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">how-many</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">some-non-empty-list</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Finally we may safely assume that <span class="RktSym"><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> extracts the remainder of
|
|
the list in a fixed amount of time, but otherwise it looks like we are
|
|
stuck. To compute how long <span class="RktSym">how-many</span> takes to determine the length
|
|
of some list, we need to know how long <span class="RktSym">how-many</span> takes to count
|
|
the number of items in the rest of that list.</div></p><p>Alternatively, if we assume that predicates and selectors take some fixed
|
|
amount of time, the time it takes <span class="RktSym">how-many</span> to determine the
|
|
length of a list depends on the number of recursive steps it
|
|
takes. Somewhat more precisely, evaluating <span class="RktPn">(</span><span class="RktSym">how-many</span><span class="stt"> </span><span class="RktSym">some-list</span><span class="RktPn">)</span>
|
|
takes roughly <span style="font-style: italic">n</span> times some fixed amount where <span style="font-style: italic">n</span> is the
|
|
length of the list or, equivalently, the number of times the program
|
|
recurs.</p><p>Generalizing from this example suggests that the running time depends on
|
|
the size of the input and that the number of recursive steps is a good
|
|
estimate for the length of an evaluation sequence. For this reason,
|
|
computer scientists discuss the <span style="font-style: italic">abstract running time</span> of a
|
|
program as a relationship between the size of the input and the number of
|
|
recursive steps in an evaluation.<span class="refelem"><span class="refcolumn"><span class="refcontent">“Abstract” because
|
|
the measure ignores the details of how much time primitive steps take.</span></span></span>
|
|
In our first example, the size of the input is the number of items on the
|
|
list. Thus, a list of one item requires one recursive step, a list of two
|
|
needs two steps, and for a list of <span style="font-style: italic">n</span> items, it’s <span style="font-style: italic">n</span> steps.</p><p>Computer scientists use the phrase a program <span class="RktSym">f</span> takes “on the
|
|
order of <span style="font-style: italic">n</span> steps” to formulate a claim about the abstract running time
|
|
of <span class="RktSym">f</span>. To use the phrase correctly, it must come with an
|
|
explanation of <span style="font-style: italic">n</span>, for example, “it counts the number of items on
|
|
the given list” or “it is the number of digits in the given number.”
|
|
Without such an explanation, the original phrase is actually meaningless.</p><p><div class="SIntrapara">Not all programs have the kind of simple abstract running time as
|
|
<span class="RktSym">how-many</span>. Take a look at the first recursive program in this
|
|
book: <a name="(idx._(gentag._696))"></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">contains-flatt?</span><span class="hspace"> </span><span class="RktSym">lo-names</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-names</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="RktPn">(</span><span class="RktSym"><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">lo-names</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"><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">lo-names</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">flatt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">contains-flatt?</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-names</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">For a list that starts with <span class="RktVal">'</span><span class="RktVal">flatt</span>, say,
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">contains-flatt?</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">"flatt"</span><span class="hspace"> </span><span class="RktVal">"robot"</span><span class="hspace"> </span><span class="RktVal">"ball"</span><span class="hspace"> </span><span class="RktVal">"game-boy"</span><span class="hspace"> </span><span class="RktVal">"pokemon"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">the program requires no recursive steps. In contrast, if
|
|
<span class="RktVal">'</span><span class="RktVal">flatt</span> occurs at the end of the list, as in,
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">contains-flatt?</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">"robot"</span><span class="hspace"> </span><span class="RktVal">"ball"</span><span class="hspace"> </span><span class="RktVal">"game-boy"</span><span class="hspace"> </span><span class="RktVal">"pokemon"</span><span class="hspace"> </span><span class="RktVal">"flatt"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">the evaluation needs as many recursive steps as there are items in the
|
|
list.</div></p><p><div class="SIntrapara">This second analysis brings us to the second important idea of program
|
|
analysis, namely, the kind of analysis that is performed:
|
|
</div><div class="SIntrapara"><ul><li><p>A <span style="font-style: italic">best-case analysis</span> focuses on the class of inputs for
|
|
which the program can easily find the answer. In our running example, a
|
|
list that starts with <span class="RktVal">'</span><span class="RktVal">flatt</span> is the best kind of input.</p></li><li><p>In turn, a <span style="font-style: italic">worst-case analysis</span> determines how badly a
|
|
program performs for those inputs that stress it most. The
|
|
<span class="RktSym">contains-flatt?</span> function exhibits its worst performance when
|
|
<span class="RktVal">'</span><span class="RktVal">flatt</span> is at the end of the input list.</p></li><li><p>Finally, an <span style="font-style: italic">average analysis</span> starts from the ideas that
|
|
programmers cannot assume that inputs are always of the best possible
|
|
shape and that they must hope that the inputs are not of the worst possible
|
|
shape. In many cases, they must estimate the <span style="font-weight: bold">average</span> time a
|
|
program takes. For example, <span class="RktSym">contains-flatt?</span> finds, on the
|
|
average, <span class="RktVal">'</span><span class="RktVal">flatt</span> somewhere in the middle of the input list. Thus,
|
|
if the latter consists of <span style="font-style: italic">n</span> items, the average
|
|
running time of <span class="RktSym">contains-flatt?</span> is <img src="pict_238.png" alt="image" width="20" height="12"/>, that is, it
|
|
recurs half as often as there are items on the input.</p></li></ul></div><div class="SIntrapara">Computer scientists therefore usually employ the “on the order of”
|
|
phrase in conjunction with “on the average” or “in the worst case.”</div></p><p><div class="SIntrapara">Returning to the idea that <span class="RktSym">contains-flatt?</span> uses, on the average,
|
|
an “order of <img src="pict_239.png" alt="image" width="20" height="12"/> steps” brings us to one more characteristic
|
|
of abstract running time. Because it ignores the exact time it takes to
|
|
evaluate primitive computation steps—<wbr></wbr>checking predicates, selecting
|
|
values, picking <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> clauses—<wbr></wbr>we can drop the division by
|
|
<span style="font-style: italic"></span>2<span style="font-style: italic"></span>. Here is why. By assumption, each basic step takes <span style="font-style: italic">k</span> units
|
|
of time, meaning <span class="RktSym">contains-flatt?</span> takes time
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_240.png" alt="image" width="45" height="15"/></p></blockquote></div><div class="SIntrapara">If you had a newer computer, these basic computations may run twice as
|
|
fast, in which case we would use <img src="pict_241.png" alt="image" width="19" height="12"/> as the constant for basic
|
|
work. Let’s call this constant <span style="font-style: italic">c</span> and calculate:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_242.png" alt="image" width="135" height="15"/></p></blockquote></div><div class="SIntrapara">that is, the abstract running time is always <span style="font-style: italic">n</span> multiplied by a
|
|
constant, and that’s all that matters to say “on the order of <span style="font-style: italic">n</span>.”</div></p><p><div class="SIntrapara">Now consider our sorting program from <a href="part_two.html#%28counter._%28figure._fig~3asort%29%29" data-pltdoc="x">figure <span class="FigureRef">72</span></a>. Here is a
|
|
hand-evaluation for a small input, listing all recursive steps:
|
|
</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._sort%29%29" class="RktValLink" data-pltdoc="x">sort</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">1</span><span class="hspace"> </span><span class="RktVal">2</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">insert</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._sort%29%29" class="RktValLink" data-pltdoc="x">sort</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><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">insert</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">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._sort%29%29" class="RktValLink" data-pltdoc="x">sort</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="RktPn">)</span><span class="RktPn">)</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">insert</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</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._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></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><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">2</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></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</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">insert</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</span><span class="hspace"> </span><span class="RktVal">1</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></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">insert</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._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">1</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._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">2</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The evaluation shows how <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span> traverses the given list and how it
|
|
sets up an application of <span class="RktSym">insert</span> for each number in the list. Put
|
|
differently, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span> is a two-phase program. During the first one,
|
|
the recursive steps for <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span> set up as many applications of
|
|
<span class="RktSym">insert</span> as there are items in the list. During the second phase,
|
|
each application of <span class="RktSym">insert</span> traverses a sorted list.</div></p><p>Inserting an item is similar to finding one, so it is not surprising
|
|
that the performance of <span class="RktSym">insert</span> and <span class="RktSym">contains-flatt?</span> are
|
|
alike. The applications of <span class="RktSym">insert</span> to a list of <span style="font-style: italic">l</span> items
|
|
triggers between <span style="font-style: italic"></span>0<span style="font-style: italic"></span> and <span style="font-style: italic">l</span> recursive steps. On the average, we
|
|
assume it requires <span style="font-style: italic">l/</span>2<span style="font-style: italic"></span>, which means
|
|
that <span class="RktSym">insert</span> takes “on the order of <span style="font-style: italic">l</span> steps” where
|
|
<span style="font-style: italic">l</span> is the length of the given list.</p><p><div class="SIntrapara">The question is how long these lists are to which <span class="RktSym">insert</span> adds
|
|
numbers. Generalizing from the above calculation, we can see that the
|
|
first one is <img src="pict_243.png" alt="image" width="29" height="9"/> items long, the second one <img src="pict_244.png" alt="image" width="29" height="9"/>, and so
|
|
on, all the way down to the empty list. Hence, we get that <span class="RktSym">insert</span>
|
|
performs
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_245.png" alt="image" width="365" height="17"/></p></blockquote></div><div class="SIntrapara">meaning
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_246.png" alt="image" width="68" height="15"/></p></blockquote></div><div class="SIntrapara">represents the best “guess” at the average number of insertion steps.
|
|
In this last term, <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> is the dominant factor, and so we say that a
|
|
sorting process takes “on the order 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> steps.”
|
|
<a href="i5-6.html#%28counter._%28exercise._ex~3abig-o1%29%29" data-pltdoc="x">Exercise 486</a> ask you to argue why it is correct to simplify this
|
|
claim in this way.</div></p><p>See <a href="i5-6.html#%28counter._%28exercise._ex~3abig-o1%29%29" data-pltdoc="x">exercise 486</a> for why this is the case.</p><p>We can also proceed with less formalism and rigor. Because <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span>
|
|
uses <span class="RktSym">insert</span> once per item on the list, we get an “order of
|
|
<span style="font-style: italic">n</span>” <span class="RktSym">insert</span> steps where <span style="font-style: italic">n</span> is the size of the
|
|
list. Since <span class="RktSym">insert</span> needs <img src="pict_247.png" alt="image" width="20" height="12"/> steps, we now see that a
|
|
sorting process needs <img src="pict_248.png" alt="image" width="36" height="12"/> steps or “on the order 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>.”</p><p><div class="SIntrapara">Totaling it all up, we get that <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span> takes on the “order of
|
|
<span style="font-style: italic">n</span> steps” plus <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> recursive steps in <span class="RktSym">insert</span> for a
|
|
list of <span style="font-style: italic">n</span> items, which yields
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_249.png" alt="image" width="35" height="11"/></p></blockquote></div><div class="SIntrapara">steps. See again <a href="i5-6.html#%28counter._%28exercise._ex~3abig-o1%29%29" data-pltdoc="x">exercise 486</a> for details.
|
|
<span style="font-weight: bold">Note</span> This analysis assumes that comparing two items on the list
|
|
takes a fixed amount of time. <span style="font-weight: bold">End</span></div></p><p><div class="SIntrapara">Our final example is the <span class="RktSym">inf</span> program from <a href="part_three.html#%28part._sec~3alocal-definitions%29" data-pltdoc="x">Local Definitions</a>:<a name="(idx._(gentag._697))"></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">inf</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._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="RktPn">(</span><span class="RktSym"><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="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._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></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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">inf</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="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._first%29%29" class="RktValLink" data-pltdoc="x">first</a></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">inf</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="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Let’s start with a small input: <span class="RktPn">(</span><span class="RktSym"><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">3</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span>. We know that the
|
|
result is <span class="RktVal">0</span>. Here is the first important step of a hand-evaluation:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inf</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">2</span><span class="hspace"> </span><span class="RktVal">1</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#%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="RktVal">3</span><span class="hspace"> </span><span class="highlighted"><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">3</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">From here, we must evaluate the first recursive call. Because the result is
|
|
<span class="RktVal">0</span> and the condition is thus <span class="RktVal">#false</span>, we must evaluate the
|
|
recursion in the else-branch as well.</div></p><p><div class="SIntrapara">Once we do so, we see two evaluations of <span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">inf</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">1</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#%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="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">inf</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">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">inf</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">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">At this point we can generalize the pattern and summarize it in a table:
|
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td style="border-bottom: 1px solid black;"><p>original expression</p></td><td style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p>requires two evaluations of</p></td></tr><tr><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td><td><p><span class="hspace"> </span></p></td><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td></tr><tr><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td><td><p><span class="hspace"> </span></p></td><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td></tr><tr><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td><td><p><span class="hspace"> </span></p></td><td><p><span class="RktPn">(</span><span class="RktSym">inf</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></p></td></tr></table></blockquote></div><div class="SIntrapara">In total, the hand-evaluation requires eight recursive steps for a list of
|
|
four items. If we added <span class="RktVal">4</span> to the front of the list, we would double the
|
|
number of recursive steps again. Speaking algebraically, <span class="RktSym">inf</span> needs
|
|
on the order of <span style="font-style: italic"></span>2<span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span> recursive steps for a list of <span style="font-style: italic">n</span> numbers
|
|
when the last number is the maximum, which is clearly the worst case for
|
|
<span class="RktSym">inf</span>.</div></p><p>Stop! If you paid close attention, you know that the above suggestion is
|
|
sloppy. The <span class="RktSym">inf</span> program really just needs <img src="pict_250.png" alt="image" width="25" height="10"/>
|
|
recursive steps for a list of <span style="font-style: italic">n</span> items. What is going on?</p><p><div class="SIntrapara">Remember that we don’t really measure the exact time when we say “on the
|
|
order of.” Instead we skip over all built-in predicates,
|
|
selectors, constructors, arithmetic, and so on and focus on recursive
|
|
steps only. Now consider this calculation:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_251.png" alt="image" width="77" height="15"/></p></blockquote></div><div class="SIntrapara">It shows that <img src="pict_252.png" alt="image" width="25" height="10"/> and <img src="pict_253.png" alt="image" width="12" height="8"/> differ by a small factor:
|
|
<span style="font-style: italic"></span>2<span style="font-style: italic"></span>, meaning “on the order of <img src="pict_254.png" alt="image" width="25" height="10"/> steps” describes
|
|
<span class="RktSym">inf</span> in a world where all basic operations provided by <span class="stt">*SL</span> run
|
|
at half the speed when compared to an <span class="RktSym">inf</span> program that runs at
|
|
“the order of <img src="pict_255.png" alt="image" width="12" height="8"/> steps.” In this sense, the two expressions
|
|
really mean the same thing. The question is what exactly they mean, and
|
|
that is the subject of the next section.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aorder-of-0))"></a><span style="font-weight: bold">Exercise</span> 484. While a list sorted in descending order is
|
|
clearly the worst possible input for <span class="RktSym">inf</span>, the analysis of
|
|
<span class="RktSym">inf</span>’s abstract running time explains why the rewrite of
|
|
<span class="RktSym">inf</span> 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._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> reduces the running time. For
|
|
convenience, we replicate this version here: <a name="(idx._(gentag._698))"></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">infL</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._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="RktPn">(</span><span class="RktSym"><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="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._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></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">s</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">infL</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="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._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">l</span><span class="RktPn">)</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._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">s</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">Hand-evaluate <span class="RktPn">(</span><span class="RktSym">infL</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span>. Then argue that
|
|
<span class="RktSym">infL</span> uses on the “order of <span style="font-style: italic">n</span> steps” in
|
|
the best and the worst case. You may now wish to revisit
|
|
<a href="part_three.html#%28counter._%28exercise._ex~3alocal-interm1%29%29" data-pltdoc="x">exercise 261</a>, which asks you to explore a similar problem. <a href="i5-6.html#%28counter._%28exercise._ex~3aorder-of-0%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3aorder-of-2))"></a><span style="font-weight: bold">Exercise</span> 485. A number tree is either a number or a pair of
|
|
number trees. Design <span class="RktSym">sum-tree</span>, which determines the
|
|
sum of the numbers in a tree. What is its abstract running time? What is
|
|
an acceptable measure of the size of such a tree? What is the worst
|
|
possible shape of the tree? What’s the best possible shape? <a href="i5-6.html#%28counter._%28exercise._ex~3aorder-of-2%29%29" class="ex-end" data-pltdoc="x"></a></p><h3><a name="(part._.The_.Definition_of__.On_the_.Order_.Of_)"></a>The Definition of “On the Order Of”</h3><p><div class="SIntrapara">The preceding section alluded to all the key ingredients of the phrase “on
|
|
the order of.” Now it is time to introduce a rigorous description of the
|
|
phrase. Let’s start with the two ideas that the preceding section
|
|
develops:
|
|
</div><div class="SIntrapara"><ol><li><p>The abstract measurement of performance is a relationship between
|
|
two quantities: the size of the input and the number of recursive steps
|
|
needed to determine the answer. The relationship is actually a
|
|
mathematical function that maps one natural number (the size of the
|
|
input) to another (the time needed).</p></li><li><p>Hence, a general statement about the performance of a program is a
|
|
statement about a function, and a comparison of the performance of two
|
|
programs calls for the comparison of two such functions.</p></li></ol></div><div class="SIntrapara">How do you decide whether one such function is “better” than another?</div></p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p><a href="part_three.html#%28counter._%28exercise._ex~3asem2-funcs%29%29" data-pltdoc="x">Exercise 245</a> tackles a different question, namely,
|
|
whether we can formulate a program that decides whether two other programs
|
|
are equal. In this intermezzo, we are not writing a program;
|
|
we are using plain mathematical arguments.</p></blockquote></blockquote></blockquote><p><div class="SIntrapara">Let’s return to the imaginary programs from the introduction: <span class="RktSym">prog-linear</span><span class="RktMeta"></span> and
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>. They compute the same results but their performance differs. The
|
|
<span class="RktSym">prog-linear</span><span class="RktMeta"></span> program requires “on the order of <span style="font-style: italic">n</span> steps” while <span class="RktSym">prog-square</span><span class="RktMeta"></span>
|
|
uses “on the order 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> steps.” Mathematically speaking, the
|
|
performance function for <span class="RktSym">prog-linear</span><span class="RktMeta"></span> is
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_256.png" alt="image" width="71" height="12"/></p></blockquote></div><div class="SIntrapara">and <span class="RktSym">prog-square</span><span class="RktMeta"></span>’s associated performance function is
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_257.png" alt="image" width="76" height="13"/></p></blockquote></div><div class="SIntrapara">In these definitions, <span style="font-style: italic">c</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">L</span></span><span style="font-style: italic"></span> is the cost for each recursive step in
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span> and <span style="font-style: italic">c</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">S</span></span><span style="font-style: italic"></span> is the cost per step in <span class="RktSym">prog-linear</span><span class="RktMeta"></span>.</div></p><p>Say we figure out that <span style="font-style: italic">c</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">L</span></span><span style="font-style: italic"> = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> and <span style="font-style: italic">c</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic">S</span></span><span style="font-style: italic"> = </span>1<span style="font-style: italic"></span>. Then we can
|
|
tabulate these abstract running times to make the comparison concrete:</p><p><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-style: italic">n</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>10</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>100</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>1000</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>2000</p></td></tr><tr><td align="right"><p><span class="RktSym">prog-square</span><span class="RktMeta"></span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>100</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>10000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1000000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4000000</p></td></tr><tr><td align="right"><p><span class="RktSym">prog-linear</span><span class="RktMeta"></span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>10000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>100000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1000000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>2000000</p></td></tr></table></blockquote></div><div class="SIntrapara">Like the graphs in <a href="i5-6.html#%28counter._%28figure._fig~3aperformance%29%29" data-pltdoc="x">figure <span class="FigureRef">176</span></a>, the table at first seems
|
|
to say that <span class="RktSym">prog-square</span><span class="RktMeta"></span> is better than <span class="RktSym">prog-linear</span><span class="RktMeta"></span>, because for inputs of the same
|
|
size <span style="font-style: italic">n</span>, <span class="RktSym">prog-square</span><span class="RktMeta"></span>’s result is smaller than <span class="RktSym">prog-linear</span><span class="RktMeta"></span>’s. But look at the
|
|
last column in the table. Once the inputs are sufficiently large,
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>’s advantage decreases until it disappears at an input size of
|
|
<span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>. <span style="font-weight: bold">Thereafter</span> <span class="RktSym">prog-square</span><span class="RktMeta"></span> is <span style="font-weight: bold">always</span> slower than
|
|
<span class="RktSym">prog-linear</span><span class="RktMeta"></span>.</div></p><p>This last insight is the key to the precise definition of the phrase
|
|
“order of.” If a function <span style="font-style: italic">f</span> on the natural numbers produces
|
|
larger numbers than some function <span style="font-style: italic">g</span> <span style="font-weight: bold">for all</span> natural numbers,
|
|
then <span style="font-style: italic">f</span> is clearly larger than <span style="font-style: italic">g</span>. But what if this comparison
|
|
fails for just a few inputs, say for <span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> or <span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, and
|
|
holds for all others? In that case, we would still like to say <span style="font-style: italic">f</span>
|
|
is better than <span style="font-style: italic">g</span>. And this brings us to the following definition.</p><blockquote><p><div class="SIntrapara"><span style="font-weight: bold">Definition</span> Given a function <span style="font-style: italic">g</span> on the natural numbers,
|
|
<span style="font-style: italic">O</span>(<span style="font-style: italic">g</span>)<span style="font-style: italic"></span> (pronounced: “big-O of g”) is a class of functions on
|
|
natural numbers. A function <span style="font-style: italic">f</span> is a member of <span style="font-style: italic">O</span>(<span style="font-style: italic">g</span>)<span style="font-style: italic"></span> if
|
|
<span style="font-weight: bold">there exist</span> numbers <span style="font-style: italic">c</span> and <span style="font-style: italic">bigEnough</span> such that
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span style="font-weight: bold">for all</span>
|
|
<img src="pict_258.png" alt="image" width="79" height="12"/>
|
|
it is true that
|
|
<img src="pict_259.png" alt="image" width="84" height="12"/></p></blockquote></div></p><p><span style="font-weight: bold">Terminology</span> If <img src="pict_260.png" alt="image" width="48" height="12"/>, we say <span style="font-style: italic">f</span> is no worse than
|
|
<span style="font-style: italic">g</span>.</p></blockquote><p><div class="SIntrapara">Naturally, we would love to illustrate this definition with the example of
|
|
<span class="RktSym">prog-linear</span><span class="RktMeta"></span> and <span class="RktSym">prog-square</span><span class="RktMeta"></span> from above. Recall the performance functions for <span class="RktSym">prog-linear</span><span class="RktMeta"></span>
|
|
and <span class="RktSym">prog-square</span><span class="RktMeta"></span>, with the constants plugged in:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_261.png" alt="image" width="70" height="13"/></p></blockquote></div><div class="SIntrapara">and
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_262.png" alt="image" width="89" height="12"/></p></blockquote></div><div class="SIntrapara">The key is to find the magic numbers <span style="font-style: italic">c</span> and
|
|
<span style="font-style: italic">bigEnough</span> such that <img src="pict_263.png" alt="image" width="51" height="12"/>, which would validate that
|
|
<span class="RktSym">prog-square</span><span class="RktMeta"></span>’s performance is no worse than <span class="RktSym">prog-linear</span><span class="RktMeta"></span>’s. For now, we just
|
|
tell you what these numbers are:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_264.png" alt="image" width="135" height="12"/></p></blockquote></div><div class="SIntrapara">Using these numbers, we need to show that
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_265.png" alt="image" width="82" height="12"/></p></blockquote></div><div class="SIntrapara">for every single <span style="font-style: italic">n</span> larger than <span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>. Here is how this kind
|
|
of argument is spelled out:
|
|
</div><div class="SIntrapara"><blockquote><p><div class="SIntrapara">Pick some specific <span style="font-style: italic">n</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> that satisfies the
|
|
condition:
|
|
</div><div class="SIntrapara"><blockquote><p><img src="pict_266.png" alt="image" width="59" height="10"/></p></blockquote></div><div class="SIntrapara">We use the symbolic name <span style="font-style: italic">n</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> so that we don’t make any specific
|
|
assumptions about it. Now recall from algebra that you can multiply both
|
|
sides of the inequality with the same positive factor, and the inequality
|
|
still holds. We use <span style="font-style: italic">n</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>:
|
|
</div><div class="SIntrapara"><blockquote><p><img src="pict_267.png" alt="image" width="103" height="10"/></p></blockquote></div><div class="SIntrapara">At this point, it is time to observe that the left side of the inequality
|
|
is just <span style="font-style: italic">L</span>(<span style="font-style: italic">n</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"></span> and the right side is <span style="font-style: italic">S</span>(<span style="font-style: italic">n</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"></span>:
|
|
</div><div class="SIntrapara"><blockquote><p><img src="pict_268.png" alt="image" width="84" height="12"/></p></blockquote></div><div class="SIntrapara">Since <span style="font-style: italic">n</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> is a generic number of the right kind, we have shown
|
|
exactly what we wanted to show.</div></p></blockquote></div><div class="SIntrapara">Usually you find <span style="font-style: italic">bigEnough</span> and <span style="font-style: italic">c</span> by working your way backward
|
|
through such an argument. While this kind of mathematical reasoning is
|
|
fascinating, we leave it to a course on algorithms.</div></p><p><div class="SIntrapara">The definition of <span style="font-style: italic">O</span> also explains with mathematical rigor why we don’t
|
|
have to pay attention to specific constants in our comparisons of abstract
|
|
running times. Say we can make each basic step of <span class="RktSym">prog-linear</span><span class="RktMeta"></span> go twice as
|
|
fast so that we have:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_269.png" alt="image" width="72" height="15"/></p></blockquote></div><div class="SIntrapara">and
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_270.png" alt="image" width="89" height="12"/></p></blockquote></div><div class="SIntrapara">The above argument goes through by doubling <span style="font-style: italic">bigEnough</span> to <span style="font-style: italic"></span>2<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>.</div></p><p>Finally, most people use <span style="font-style: italic">O</span> together with a short-hand for stating
|
|
functions. Thus they say <span class="RktSym">how-many</span>’s running time is
|
|
<span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span>—<wbr></wbr>because they tend to think of <span style="font-style: italic">n</span> as an abbreviation of
|
|
the (mathematical) function <span style="font-style: italic">id</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"> = n</span>. Similarly, this use yields
|
|
the claim that <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sort%29%29" class="RktValLink" data-pltdoc="x">sort</a></span>’s worst-case running time is <span style="font-style: italic">O</span>(<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>)<span style="font-style: italic"></span>
|
|
and <span class="RktSym">inc</span>’s is <span style="font-style: italic">O</span>(<span style="font-style: italic"></span>2<span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span>—<wbr></wbr>again because <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> is
|
|
short-hand for the function <span style="font-style: italic">sqr</span>(<span style="font-style: italic">n</span>)<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> and <span style="font-style: italic"></span>2<span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span> is short
|
|
for <span style="font-style: italic">expt</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"> = </span>2<span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span>.</p><p>Stop! What does it mean to say that a function’s performance is
|
|
<span style="font-style: italic">O</span>(<span style="font-style: italic"></span>1<span style="font-style: italic"></span>)<span style="font-style: italic"></span>?</p><p><a name="(counter._(exercise._ex~3abig-o1))"></a><span style="font-weight: bold">Exercise</span> 486. In the first subsection, we stated that the function
|
|
<span style="font-style: italic">f</span>(<span style="font-style: italic">n</span>)<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"> + n</span> belongs to the class <span style="font-style: italic">O</span>(<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>)<span style="font-style: italic"></span>. Determine the
|
|
pair of numbers <span style="font-style: italic">c</span> and <span style="font-style: italic">bigEnough</span> that verify this claim. <a href="i5-6.html#%28counter._%28exercise._ex~3abig-o1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3abig-o2))"></a><span style="font-weight: bold">Exercise</span> 487. Consider the functions <span style="font-style: italic">f</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"> = </span>2<span style="font-style: italic"></span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic">n</span></span><span style="font-style: italic"></span> and
|
|
<span style="font-style: italic">g</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"> = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"> n</span>. Show that <span style="font-style: italic">g</span> belongs to <span style="font-style: italic">O</span>(<span style="font-style: italic">f</span>)<span style="font-style: italic"></span>,
|
|
which means that <span style="font-style: italic">f</span> is, abstractly speaking, more (or at least
|
|
equally) expensive than <span style="font-style: italic">g</span>. If the input size is guaranteed to be
|
|
between 3 and 12, which function is better? <a href="i5-6.html#%28counter._%28exercise._ex~3abig-o2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3abig-o3))"></a><span style="font-weight: bold">Exercise</span> 488. Compare <img src="pict_271.png" alt="image" width="83" height="12"/> and <img src="pict_272.png" alt="image" width="53" height="13"/>. Does <span style="font-style: italic">f</span> belong to <span style="font-style: italic">O</span>(<span style="font-style: italic">g</span>)<span style="font-style: italic"></span> or <span style="font-style: italic">g</span> to <span style="font-style: italic">O</span>(<span style="font-style: italic">f</span>)<span style="font-style: italic">?</span> <a href="i5-6.html#%28counter._%28exercise._ex~3abig-o3%29%29" class="ex-end" data-pltdoc="x"></a></p><h3><a name="(part._.Why_.Do_.Programs_.Use_.Predicates_and_.Selectors_)"></a>Why Do Programs Use Predicates and Selectors?</h3><p><div class="SIntrapara">The notion of “on the order of” explains why the <a name="(idx._(gentag._699))"></a>design recipes produce
|
|
both well-organized and “performant” programs. We illustrate this
|
|
insight with a single example, the design of a program that searches for
|
|
a number in a list of numbers. Here are the signature, the purpose
|
|
statement, and examples formulated as tests:
|
|
</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_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._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 </span><span class="RktSym">x</span><span class="RktCmt"> in </span><span class="RktSym">l</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">search</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</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">search</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Here are two definitions that live up to these expectations: <a name="(idx._(gentag._700))"></a> <a name="(idx._(gentag._701))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><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="RktPn">(</span><span class="RktSym">searchL</span><span class="hspace"> </span><span class="RktSym">x</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._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">#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></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"><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._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">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">searchL</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">x</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="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></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="RktPn">(</span><span class="RktSym">searchS</span><span class="hspace"> </span><span class="RktSym">x</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._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="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</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></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"><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._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">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">searchS</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">x</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="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></div><div class="SIntrapara">The design of the program on the left follows the design recipe. In
|
|
particular, the development of the template calls for the use of
|
|
<a name="(idx._(gentag._702))"></a>structural predicates per clause in the data definition. Following this
|
|
advice yields a conditional program whose 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 deals
|
|
with empty lists and whose second one deals with all others. The question in the
|
|
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 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._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span> and the second 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~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span> or <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>.</div></p><p>The design of <span class="RktSym">searchS</span> fails to live up to the <a name="(idx._(gentag._703))"></a>structural
|
|
design<span class="refelem"><span class="refcolumn"><span class="refcontent">It really uses generative recursion.</span></span></span> recipe. It
|
|
instead takes inspiration from the idea that lists are containers that
|
|
have a size. Hence, a program can check this size for <span class="RktVal">0</span>, which is
|
|
equivalent to checking for emptiness.</p><p>Although this idea is functionally correct, it makes the assumption that
|
|
the cost of <span class="stt">*SL</span>-provided operations is a fixed constant. If
|
|
<span class="RktSym">length</span> is more like <span class="RktSym">how-many</span>, however, <span class="RktSym">searchS</span>
|
|
is going to be slower than <span class="RktSym">searchL</span>. Using our new terminology,
|
|
<span class="RktSym">searchL</span> is using <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span> recursive steps while
|
|
<span class="RktSym">searchS</span> needs <span style="font-style: italic">O</span>(<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>)<span style="font-style: italic"></span> steps for a list of <span style="font-style: italic">n</span>
|
|
items. In short, using arbitrary <span class="stt">*SL</span> operations to formulate conditions
|
|
may shift performance from one class of functions to one that is much
|
|
worse.</p><p><div class="SIntrapara">Let’s wrap up this intermezzo with an experiment that checks whether
|
|
<span class="RktSym">length</span> is a constant-time function or whether it consumes time
|
|
proportionally to the length of the given list. The easiest way is to
|
|
define a program that creates a long list and determines how much time
|
|
each version of the search program takes: <a name="(idx._(gentag._704))"></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._list%29" class="techoutside" data-pltdoc="x"><span class="techinside">List</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="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">how long do </span><span class="RktSym">searchS</span><span class="RktCmt"> and </span><span class="RktSym">searchL</span><span class="RktCmt"> take </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">to look for </span><span class="RktSym">n</span><span class="RktCmt"> in </span><span class="RktPn">(</span><span class="RktSym"><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">0</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 class="RktPn">(</span><span class="RktSym"><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">n</span><span class="stt"> </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="RktPn">(</span><span class="RktSym">timing</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._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">long-list</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._build-list%29%29" class="RktValLink" data-pltdoc="x">build-list</a></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#%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="RktSym">x</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/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#%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">searchS</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">long-list</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._time%29%29" class="RktStxLink" data-pltdoc="x">time</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">searchL</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">long-list</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">Now run this program on <span class="RktVal">10000</span> and <span class="RktVal">20000</span>.
|
|
If <span class="RktSym">length</span> is like <span class="RktSym"><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>, the times for the second run
|
|
will be roughly twice those of the first one; otherwise, the time for
|
|
<span class="RktSym">searchS</span> will increase dramatically.</div></p><p>Stop! Conduct the experiment.</p><p>Assuming you have completed the experiment, you now know that
|
|
<span class="RktSym">length</span> takes time proportionally to the size of the given list.
|
|
The “S” in <span class="RktSym">searchS</span> stands for “squared” because its running
|
|
time is <span style="font-style: italic">O</span>(<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>)<span style="font-style: italic"></span>. But don’t jump to the conclusion that
|
|
this<span class="refelem"><span class="refcolumn"><span class="refcontent">See <a href="part_six.html#%28part._sec~3amore-accu-mc%29" data-pltdoc="x">Data Representations with Accumulators</a> for how other languages
|
|
track the size of a container.</span></span></span> kind of reasoning holds for every
|
|
programming language you will encounter. Many deal with containers
|
|
differently than <span class="stt">*SL</span>. Understanding how this is done requires one more
|
|
design concept, accumulators, the concern of the final part of this book.</p><h3><a name="(part._i5-6-fake)"></a></h3><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="part_five.html" title="backward to "V Generative Recursion"" 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="part_six.html" title="forward to "VI Accumulators"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html> |