about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/ssch14
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/ssch14
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/ssch14')
-rw-r--r--js/games/nluqo.github.io/~bh/ssch14/number-name91
-rw-r--r--js/games/nluqo.github.io/~bh/ssch14/number-name.html91
-rw-r--r--js/games/nluqo.github.io/~bh/ssch14/recur-patterns789
-rw-r--r--js/games/nluqo.github.io/~bh/ssch14/recur-patterns.html789
4 files changed, 1760 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/ssch14/number-name b/js/games/nluqo.github.io/~bh/ssch14/number-name
new file mode 100644
index 0000000..bac8cd1
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch14/number-name
@@ -0,0 +1,91 @@
+<P>
+
+<P>
+<HTML>
+<HEAD>
+<TITLE>Simply Scheme:Project: Spelling Names of Huge Numbers</TITLE>
+</HEAD>
+<BODY>
+<CITE>Simply Scheme</CITE>:
+<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
+<H1>Project: Spelling Names of Huge Numbers</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../simply.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
+Wright</A><BR>University of California, Santa Barbara</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/ssch14.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="recur-patterns.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../ssch15/adv-recur.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
+Press web page for <CITE>Simply Scheme</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+<P>
+
+
+<P>Write a procedure <CODE><A NAME="g1"></A>number-name</CODE> that takes a positive integer
+argument and returns a sentence containing that number spelled out in words:
+
+<P><PRE>&gt; (number-name 5513345)
+(FIVE MILLION FIVE HUNDRED THIRTEEN THOUSAND THREE HUNDRED FORTY FIVE)
+
+&gt; (number-name (factorial 20))
+(TWO QUINTILLION FOUR HUNDRED THIRTY TWO QUADRILLION NINE HUNDRED TWO
+ TRILLION EIGHT BILLION ONE HUNDRED SEVENTY SIX MILLION SIX HUNDRED
+ FORTY THOUSAND)
+</PRE>
+
+<P>There are some special cases you will need to consider:
+
+<P><P><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers in which some particular digit is zero
+</TABLE><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers like 1,000,529 in which an entire group of three digits is zero.
+</TABLE><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers in the teens.
+
+</TABLE><P>
+
+<P>Here are two hints.  First, split the number into groups of three digits,
+going from right to left.  Also, use the sentence
+
+<P><PRE>'(thousand million billion trillion quadrillion quintillion
+  sextillion septillion octillion nonillion decillion)
+</PRE>
+
+<P>You can write this bottom-up or top-down.  To work bottom-up, pick a subtask
+and get that working before you tackle the overall structure of the
+problem.  For example, write a procedure that returns the word <CODE>FIFTEEN</CODE>
+given the argument <CODE>15</CODE>.
+
+<P>To work top-down, start by writing <CODE>number-name</CODE>, freely assuming the
+existence of whatever helper procedures you like.  You can begin debugging
+by writing <EM>stub</EM> procedures that fit into the overall program but
+don't really do their job correctly.  For example, as an intermediate stage
+you might end up with a program that works like this:
+
+<P><PRE>&gt; (number-name 1428425)                      ;; intermediate version
+(1 MILLION 428 THOUSAND 425)
+</PRE>
+
+
+<P>
+
+
+<HR>
+<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
+<A HREF="recur-patterns.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../ssch15/adv-recur.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>
diff --git a/js/games/nluqo.github.io/~bh/ssch14/number-name.html b/js/games/nluqo.github.io/~bh/ssch14/number-name.html
new file mode 100644
index 0000000..bac8cd1
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch14/number-name.html
@@ -0,0 +1,91 @@
+<P>
+
+<P>
+<HTML>
+<HEAD>
+<TITLE>Simply Scheme:Project: Spelling Names of Huge Numbers</TITLE>
+</HEAD>
+<BODY>
+<CITE>Simply Scheme</CITE>:
+<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
+<H1>Project: Spelling Names of Huge Numbers</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../simply.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
+Wright</A><BR>University of California, Santa Barbara</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/ssch14.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="recur-patterns.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../ssch15/adv-recur.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
+Press web page for <CITE>Simply Scheme</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+<P>
+
+
+<P>Write a procedure <CODE><A NAME="g1"></A>number-name</CODE> that takes a positive integer
+argument and returns a sentence containing that number spelled out in words:
+
+<P><PRE>&gt; (number-name 5513345)
+(FIVE MILLION FIVE HUNDRED THIRTEEN THOUSAND THREE HUNDRED FORTY FIVE)
+
+&gt; (number-name (factorial 20))
+(TWO QUINTILLION FOUR HUNDRED THIRTY TWO QUADRILLION NINE HUNDRED TWO
+ TRILLION EIGHT BILLION ONE HUNDRED SEVENTY SIX MILLION SIX HUNDRED
+ FORTY THOUSAND)
+</PRE>
+
+<P>There are some special cases you will need to consider:
+
+<P><P><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers in which some particular digit is zero
+</TABLE><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers like 1,000,529 in which an entire group of three digits is zero.
+</TABLE><TABLE><TR><TH align="right" valign="top">&bull;<TD>&nbsp;&nbsp;&nbsp;&nbsp;<TD valign="top">Numbers in the teens.
+
+</TABLE><P>
+
+<P>Here are two hints.  First, split the number into groups of three digits,
+going from right to left.  Also, use the sentence
+
+<P><PRE>'(thousand million billion trillion quadrillion quintillion
+  sextillion septillion octillion nonillion decillion)
+</PRE>
+
+<P>You can write this bottom-up or top-down.  To work bottom-up, pick a subtask
+and get that working before you tackle the overall structure of the
+problem.  For example, write a procedure that returns the word <CODE>FIFTEEN</CODE>
+given the argument <CODE>15</CODE>.
+
+<P>To work top-down, start by writing <CODE>number-name</CODE>, freely assuming the
+existence of whatever helper procedures you like.  You can begin debugging
+by writing <EM>stub</EM> procedures that fit into the overall program but
+don't really do their job correctly.  For example, as an intermediate stage
+you might end up with a program that works like this:
+
+<P><PRE>&gt; (number-name 1428425)                      ;; intermediate version
+(1 MILLION 428 THOUSAND 425)
+</PRE>
+
+
+<P>
+
+
+<HR>
+<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
+<A HREF="recur-patterns.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../ssch15/adv-recur.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>
diff --git a/js/games/nluqo.github.io/~bh/ssch14/recur-patterns b/js/games/nluqo.github.io/~bh/ssch14/recur-patterns
new file mode 100644
index 0000000..cfdd3aa
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch14/recur-patterns
@@ -0,0 +1,789 @@
+<P>
+
+<A NAME="fish"></A>
+<P><CENTER><IMG SRC="../ss-pics/fish.jpg" ALT="figure: fish"></CENTER>
+<HTML>
+<HEAD>
+<TITLE>Simply Scheme: Introducing Computer Science ch 14: Common Patterns in Recursive Procedures</TITLE>
+</HEAD>
+<BODY>
+<HR>
+<CITE>Simply Scheme:</CITE>
+<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
+<H2>Chapter 14</H2>
+<H1>Common Patterns in Recursive Procedures</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../simply.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
+Wright</A><BR>University of California, Santa Barbara</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/ssch14.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../ssch13/convince-recur.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="number-name.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
+Press web page for <CITE>Simply Scheme</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+
+<P><A NAME="g1"></A>
+<A NAME="g2"></A>
+
+<P>
+<P>There are two ideas about how to solve programming problems.<A NAME="text1" HREF="recur-patterns#ft1">[1]</A> One idea is that programmers work mostly by
+recognizing categories of problems that come up repeatedly and remembering
+the solution that worked last time; therefore, programming students should
+learn a lot of program <EM>patterns,</EM> or <EM>templates,</EM> and fill
+in the blanks for each specific problem.  Another idea is that there are a
+few powerful principles in programming, and that if a learner understands
+the principles, they can be applied to <EM>any</EM> problem, even one that
+doesn't fit a familiar pattern.
+
+<P>Research suggests that an expert programmer, like an expert at any skill,
+<EM>does</EM> work mainly by recognizing patterns.  Nevertheless, we lean
+toward the powerful-principle idea.  The expert's memory is not full of
+arbitrary patterns; it's full of <EM>meaningful</EM> patterns, because the
+expert has gone through the process of struggling to reason out how each
+procedure works and how to write new procedures.
+
+<P>Still, we think it's worth pointing out a few patterns that are so common
+that you'll have seen several examples of each before you finish this book.
+Once you learn these patterns, you can write similar procedures almost
+automatically.  But there's an irony in learning patterns:  In Scheme, once
+you've identified a pattern, you can write a general-purpose procedure that
+handles all such cases without writing individual procedures for each
+situation.  Then you don't have to use the pattern any more!
+Chapter 8 presents several general pattern-handling procedures, called <EM>higher-order</EM> procedures.  In this chapter we'll
+consider the patterns corresponding to those higher-order procedures, and
+we'll use the names of those procedures to name the patterns.
+
+<P>What's the point of learning patterns if you can use higher-order procedures
+instead?  There are at least two points.  The first, as you'll see very
+soon, is that some problems <EM>almost</EM> follow one of the patterns; in
+that case, you can't use the corresponding higher-order procedure, which
+works only for problems that <EM>exactly</EM> follow the pattern.  But you
+can use your understanding of the pattern to help with these related
+problems.  The second point is that in Chapter 19 we'll show how the
+higher-order functions are themselves implemented using these recursive
+patterns.
+
+<P>This chapter isn't an official list of all important patterns; as you gain
+programming experience, you'll certainly add more patterns to your repertoire.
+
+<P><H2>The <CODE><B>Every</B></CODE> Pattern</H2>
+
+<P>Here's a procedure to square every number in a sentence of numbers:
+
+<P><PRE>(define (square-sent sent)
+  (if (empty? sent)
+      '()
+      (se (square (first sent))
+          (square-sent (bf sent)))))
+</PRE>
+
+<P>Here's a procedure to translate every word of a sentence into Pig Latin:
+
+<P><PRE>(define (pigl-sent sent)
+  (if (empty? sent)
+      '()
+      (se (pigl (first sent))
+          (pigl-sent (bf sent)))))
+</PRE>
+
+<P>The pattern here is pretty clear.  Our recursive case will do something
+straightforward to the <CODE>first</CODE> of the sentence, such as <CODE>square</CODE>ing it
+or <CODE>pigl</CODE>ing it, and we'll combine that with the result of a recursive
+call on the <CODE>butfirst</CODE> of the sentence.
+
+<P>The <CODE>letter-pairs</CODE> procedure that we wrote in Chapter 11 is
+an example of a procedure that follows the <CODE>every</CODE> pattern pretty
+closely, but not exactly.  The difference is that <CODE>letter-pairs</CODE> looks
+at its argument sentence two words at a time.
+
+<P><PRE>(define (<A NAME="g3"></A>letter-pairs wd)
+  (if (= (count wd) 1)
+      '()
+      (se (word (first wd) (first (bf wd)))
+          (letter-pairs (bf wd)))))
+</PRE>
+
+<P>Compare this with the earlier definition of <CODE>square-sent</CODE>.  The recursive case still uses <CODE>se</CODE> to combine one
+part of the result with a recursive call based on the <CODE>butfirst</CODE> of
+the argument, but here both the first letter and the second letter of the
+argument contribute to the first word of the result.  That's why the base
+case also has to be different; the recursive case requires at least two
+letters, so the base case is a one-letter word.<A NAME="text2" HREF="recur-patterns#ft2">[2]</A>
+
+<P>Let's solve a slightly different problem.  This time, we want to break the
+word down into <EM>non-overlapping</EM> pairs of letters, like this:
+
+<P><PRE>&gt; (disjoint-pairs 'tripoli)                  ;; the new problem
+(TR IP OL I)
+
+&gt; (letter-pairs 'tripoli)                    ;; compare the old one
+(TR RI IP PO OL LI)
+</PRE>
+
+<P>The main difference between these two functions is that in <CODE>disjoint-pairs</CODE> we eliminate two letters at once in the recursive call.  A
+second difference is that we have to deal with the special case of
+odd-length words.
+
+<P><PRE>(define (<A NAME="g4"></A>disjoint-pairs wd)
+  (cond ((empty? wd) '())
+	((= (count wd) 1) (se wd))
+	(else (se (word (first wd) (first (bf wd)))
+		  (disjoint-pairs (bf (bf wd)))))))
+</PRE>
+
+<P><H2>The <CODE><B>Keep</B></CODE> Pattern</H2>
+
+<P>In the <CODE>every</CODE> pattern, we collect the results of transforming each
+element of a word or sentence into something else.  This time we'll consider
+a different kind of problem: choosing some of the elements and forgetting
+about the others.  First, here is a procedure to select the three-letter
+words from a sentence:
+
+<P>
+<PRE>(define (keep-three-letter-words sent)
+  (cond ((empty? sent) '())
+        ((= (count (first sent)) 3)
+         (se (first sent) (keep-three-letter-words (bf sent))))
+        (else (keep-three-letter-words (bf sent)))))
+
+&gt; (keep-three-letter-words '(one two three four five six seven))
+(ONE TWO SIX)
+</PRE>
+
+<P> 
+Next, here is a procedure to select the vowels from a word:
+
+<P><PRE>(define (keep-vowels wd)
+  (cond ((empty? wd) &quot;&quot;)
+        ((vowel? (first wd))
+         (word (first wd) (keep-vowels (bf wd))))
+        (else (keep-vowels (bf wd)))))
+
+&gt; (keep-vowels 'napoleon)
+AOEO
+</PRE>
+
+<P>Let's look at the differences between the <CODE>every</CODE> pattern and the
+<A NAME="g5"></A><A NAME="g6"></A> pattern.  First of all, the <CODE>keep</CODE> procedures have three
+possible outcomes, instead of just two as in most <CODE>every</CODE>-like
+procedures.  In the <CODE>every</CODE> pattern, we only have to distinguish between
+the base case and the recursive case.  In the <CODE>keep</CODE> pattern, there is
+still a base case, but there are <EM>two</EM> recursive cases; we have to
+decide whether or not to keep the first available element in the return
+value.  When we do keep an element, we keep the element itself, not some
+function of the element.
+
+<P>As with the <CODE>every</CODE> pattern, there are situations that follow the <CODE>keep</CODE> pattern only approximately.  Suppose we want to look for doubled
+letters within a word:
+
+<P>
+<PRE>&gt; (doubles 'bookkeeper)
+OOKKEE
+
+&gt; (doubles 'mississippi)
+SSSSPP
+</PRE>
+
+<P>This isn't a pure <CODE>keep</CODE> pattern example because we can't
+decide whether to keep the first letter by looking at that letter alone; we
+have to examine two at a time.  But we can write a procedure using more or
+less the same pattern:
+
+<P><PRE>(define (<A NAME="g7"></A>doubles wd)
+  (cond ((= (count wd) 1) &quot;&quot;)
+        ((equal? (first wd) (first (bf wd)))
+         (word (first wd) (first (bf wd)) (doubles (bf (bf wd)))))
+        (else (doubles (bf wd)))))
+</PRE>
+
+<P>As in the <CODE>evens</CODE> example of Chapter 12, the base case of
+<CODE>doubles</CODE> is unusual, and one of the recursive calls chops off two
+letters at once in forming the smaller subproblem.  But the structure of the
+<CODE>cond</CODE> with a base case clause, a clause for keeping letters, and a
+clause for rejecting letters is maintained.
+
+<P><H2>The <CODE><B>Accumulate</B></CODE> Pattern</H2>
+
+<P>Here are two recursive procedures for functions that combine all of the
+elements of the argument into a single result:
+
+<P><PRE>(define (<A NAME="g8"></A>addup nums)
+  (if (empty? nums)
+      0
+      (+ (first nums) (addup (bf nums)))))
+
+(define (<A NAME="g9"></A>scrunch-words sent)
+  (if (empty? sent)
+      &quot;"
+      (word (first sent) (scrunch-words (bf sent)))))
+
+&gt; (addup '(8 3 6 1 10))
+28
+
+&gt; (scrunch-words '(ack now ledge able))
+ACKNOWLEDGEABLE
+</PRE>
+
+<P>What's the pattern?  We're using some combiner (<CODE>+</CODE> or <CODE>word</CODE>) to connect the word we're up to with the result of the recursive
+call.  The base case tests for an empty argument, but the base case return
+value must be the identity element of the combiner function.
+
+<P>If there is no identity element for the combiner, as in the case of <CODE>max</CODE>, we modify the pattern slightly:<A NAME="text3" HREF="recur-patterns#ft3">[3]</A>
+
+<P><PRE>(define (<A NAME="g10"></A>sent-max sent)
+  (if (= (count sent) 1)
+      (first sent)
+      (max (first sent)
+	   (sent-max (bf sent)))))
+</PRE>      
+
+<P><H2>Combining Patterns</H2>
+
+<P><PRE>(define (<A NAME="g11"></A>add-numbers sent)
+  (cond ((empty? sent) 0)
+	((number? (first sent))
+	 (+ (first sent) (add-numbers (bf sent))))
+	(else (add-numbers (bf sent)))))
+
+&gt; (add-numbers '(if 6 were 9))
+15
+</PRE>
+
+<P>This procedure combines aspects of <CODE>keep</CODE> with aspects of <CODE>accumulate</CODE>.  We want to do two things at once: get rid of the words that
+aren't numbers and compute the <EM>sum</EM> of those that are numbers.  (A
+simple <CODE>keep</CODE> would construct a sentence of them.)  <CODE>Add-numbers</CODE>
+looks exactly like the <CODE>keep</CODE> pattern, except that there's a funny
+combiner and a funny base case, which look more like <CODE>accumulate</CODE>.<A NAME="text4" HREF="recur-patterns#ft4">[4]</A>
+
+<P> 
+Here's an example that combines <CODE>every</CODE> and <CODE>keep</CODE>.  We want a
+procedure that takes a sentence as its argument and translates every word of
+the sentence into Pig Latin, but leaves out words that have no vowels,
+because the Pig Latin translator doesn't work for such words.  The procedure
+<CODE>safe-pigl</CODE> will be like a <CODE>keep</CODE> pattern in that it keeps only
+words that contain vowels, but like an <CODE>every</CODE> in that the result
+contains transformed versions of the selected words, rather than the words
+themselves.
+
+<P><PRE>(define (<A NAME="g12"></A>safe-pigl sent)
+  (cond ((empty? sent) '())
+	((has-vowel? (first sent))
+	 (se (pigl (first sent)) (safe-pigl (bf sent))))
+	(else (safe-pigl (bf sent)))))
+
+(define (<A NAME="g13"></A>has-vowel? wd)
+  (not (empty? (keep-vowels wd))))
+
+&gt; (safe-pigl '(my pet fly is named xyzzy))
+(ETPAY ISAY AMEDNAY)
+</PRE>
+
+<P>
+Finally, here's an example that combines all three patterns.  In Chapter
+1 we wrote (using higher-order procedures) the <CODE>acronym</CODE>
+procedure, which selects the &quot;real&quot; words of a sentence (the <CODE>keep</CODE>
+pattern), takes the first letter of each word (the <CODE>every</CODE> pattern), and
+combines these initial letters into a single word (the <CODE>accumulate</CODE>
+pattern).  In a recursive procedure we can carry out all three steps at once:
+
+<P><PRE>(define (<A NAME="g14"></A>acronym sent)
+  (cond ((empty? sent) &quot;&quot;)
+	((real-word? (first sent))
+	 (word (first (first sent))
+	       (acronym (bf sent))))
+	(else (acronym (bf sent)))))
+</PRE>
+
+<P>Don't become obsessed with trying to make every recursive problem fit one of
+the three patterns we've shown here.  As we said at the beginning of the
+chapter, what's most important is that you understand the principles of
+recursion in general, and understand how versatile recursion is.  The
+patterns are just special cases that happen to come up fairly often.
+
+<P><H2>Helper Procedures</H2>
+
+<P>Let's say we want a procedure <CODE>every-nth</CODE> that takes a number <EM>n</EM> and a
+sentence as arguments and selects every <EM>n</EM>th word from the sentence.
+
+<P><PRE>&gt; (every-nth 3 '(with a little help from my friends))
+(LITTLE MY)
+</PRE>
+
+<P>We get in trouble if we try to write this in the obvious way, as a sort of
+<CODE>keep</CODE> pattern.
+
+<P><PRE>(define (every-nth n sent)                   ;; wrong!
+  (cond ((empty? sent) '())
+        ((= n 1)
+         (se (first sent) (every-nth <STRONG><BIG>n</BIG></STRONG> (bf sent))))
+        (else (every-nth (- n 1) (bf sent)))))
+</PRE>
+
+<P>The problem is with the <CODE><B>n</B></CODE> that's in boldface.
+We're thinking that it's going to be the <CODE>n</CODE> of the <EM>original</EM>
+invocation of <CODE>every-nth</CODE>, that is, 3.  But in fact, we've already counted
+<CODE>n</CODE> down so that in this invocation its value is 1.  (Check out the first
+half of the same <CODE>cond</CODE> clause.)  This procedure will correctly skip the
+first two words but will keep all the words after that point.  That's
+because we're trying to remember two different numbers: the number we
+should always skip between kept words, and the number of words we still need
+to skip this time.
+
+<P> 
+If we're trying to remember two numbers, we need two names for them.  The
+way to achieve this is to have our official <CODE>every-nth</CODE> procedure call a
+<A NAME="g15"></A><A NAME="g16"></A>helper procedure that takes an extra argument and does the real work:
+
+<P><PRE>(define (<A NAME="g17"></A>every-nth n sent)
+  (every-nth-helper n n sent))
+
+(define (<A NAME="g18"></A>every-nth-helper interval remaining sent)
+  (cond ((empty? sent) '())
+        ((= remaining 1)
+         (se (first sent)
+             (every-nth-helper interval interval (bf sent))))
+        (else (every-nth-helper interval (- remaining 1) (bf sent)))))
+</PRE>
+
+<P>This procedure always calls itself recursively with the same value
+of <CODE>interval</CODE>, but with a different value of <CODE>remaining</CODE> each time.
+<CODE>Remaining</CODE> keeps getting smaller by one in each recursive call until it
+equals 1.  On that call, a word is kept for the return value, and we call
+<CODE>every-nth-helper</CODE> recursively with the value of <CODE>interval</CODE>, that is,
+the <EM>original</EM> value of <CODE>n</CODE>, as the new <CODE>remaining</CODE>.
+If you like, you can think of this combination of an <EM>initialization</EM>
+<A NAME="g19"></A>
+<A NAME="g20"></A>
+procedure and a <EM>helper</EM> procedure as another pattern for your
+collection.
+
+<P>
+<P><H2>How to Use Recursive Patterns</H2>
+
+<P>One way in which recursive patterns can be useful is if you think of them as
+templates with empty slots to fill in for a particular problem.  Here are
+template versions of the <CODE>every</CODE>, <CODE>keep</CODE>, and <CODE>accumulate</CODE>
+patterns as applied to sentences:
+
+<P><PRE>(define (<B>every-something</B> sent)
+  (if (empty? sent)
+      '()
+      (se (______ (first sent))
+	  (<B>every-something</B> (bf sent)))))
+
+(define (<B>keep-if-something</B> sent)
+  (cond ((empty? sent) '())
+	((______<STRONG><BIG>?</BIG></STRONG> (first sent))
+	 (se (first sent) (<B>keep-if-something</B> (bf sent))))
+	(else (<B>keep-if-something</B> (bf sent)))))
+</PRE>
+
+<P>
+<A NAME="keeptemplate"></A>
+<PRE>(define (<B>accumulate-somehow</B> sent)
+  (if (empty? sent)
+      ______
+      (______ (first sent)
+              (<B>accumulate-somehow</B> (bf sent)))))
+</PRE>
+
+<P>Suppose you're trying to write a procedure <CODE>first-number</CODE> that takes a
+sentence as its argument and returns the first number in that sentence, but
+returns the word <CODE>no-number</CODE> if there are no numbers in the argument.
+The first step is to make a guess about which pattern will be most useful.
+In this case the program should start with an entire sentence and select a
+portion of that sentence, namely one word.  Therefore, we start with the
+<CODE>keep</CODE> pattern.
+
+<P><PRE>(define (first-number sent)                  ;; first guess
+  (cond ((empty? sent) '())
+	((______ (first sent))
+	 (se (first sent) (first-number (bf sent))))
+	(else (first-number (bf sent)))))
+</PRE>
+
+<P>The next step is to fill in the blank.  Obviously, since we're looking for a
+number, <CODE>number?</CODE> goes in the blank.
+
+<P>The trouble is that this procedure returns <EM>all</EM> the numbers in the
+given sentence.  Now our job is to see how the pattern must be modified to
+do what we want.  The overall structure of the pattern is a <CODE>cond</CODE> with three clauses; we'll consider each clause separately.
+
+<P>What should the procedure return if <CODE>sent</CODE> is empty?  In that case,
+there is no first number in the sentence, so it should return <CODE>no-number</CODE>:
+
+<P><PRE>((empty? sent) <B>'no-number</B>)
+</PRE>
+
+<P>What if the first word of the sentence is a number?  The program should
+return just that number, ignoring the rest of the sentence:
+
+<P><PRE>((number? (first sent)) <B>(first sent)</B>)
+</PRE>
+
+<P>What if the first word of the sentence isn't a number?  The procedure must
+make a recursive call for the <CODE>butfirst</CODE>, and whatever that recursive
+call returns is the answer.  So the <CODE>else</CODE> clause does not have to be
+changed.
+
+<P>Here's the whole procedure:
+
+<P><PRE>(define (<A NAME="g21"></A>first-number sent)
+  (cond ((empty? sent) 'no-number)
+	((number? (first sent)) (first sent))
+	(else (first-number (bf sent)))))
+</PRE>
+
+<P>After filling in the blank in the <CODE>keep</CODE> pattern, we solved this problem
+by focusing on the details of the procedure definition.  We examined each
+piece of the definition to decide what changes were necessary.  Instead, we
+could have focused on the <EM>behavior</EM> of the procedure.  We would have
+found two ways in which the program didn't do what it was supposed to do:
+For an argument sentence containing numbers, it would return all of the
+numbers instead of just one of them.  For a sentence without numbers, it
+would return the empty sentence instead of <CODE>no-number</CODE>.  We would then
+have finished the job by <EM>debugging</EM> the procedure to fix each of these
+problems.  The final result would have been the same.
+
+<P> 
+<H2>Problems That Don't Follow Patterns</H2>
+
+<P>We want to write the procedure <CODE>sent-before?</CODE>, which takes two sentences
+as arguments and returns <CODE>#t</CODE> if the first comes alphabetically before
+the second.  The general idea is to compare the sentences word by word.  If
+the first words are different, then whichever is alphabetically earlier
+determines which sentence comes before the other.  If the first words are
+equal, we go on to compare the second words.<A NAME="text5" HREF="recur-patterns#ft5">[5]</A>
+
+<P><PRE>&gt; (sent-before? '(hold me tight) '(sun king))
+#T
+
+&gt; (sent-before? '(lovely rita) '(love you to))
+#F
+
+&gt; (sent-before? '(strawberry fields forever)
+		'(strawberry fields usually))
+#T
+</PRE>
+
+<P>Does this problem follow any of the patterns we've seen?  It's not an <CODE>every</CODE>, because the result isn't a sentence in which each word is a
+transformed version of a word in the arguments.  It's not a <CODE>keep</CODE>,
+because the result isn't a subset of the words in the arguments.  And it's
+not exactly an <CODE>accumulate</CODE>.  We do end up with a single true or
+false result, rather than a sentence full of results.  But in a typical <CODE>accumulate</CODE> problem, every word of the argument contributes to the solution.
+In this case only one word from each sentence determines the overall result.
+
+<P>On the other hand, this problem does have something in common with the <CODE>keep</CODE> pattern:  We know that on each invocation there will be three
+possibilities.  We might reach a base case (an empty sentence); if not, the
+first words of the argument sentences might or might not be relevant to the
+solution.
+
+<P>We'll have a structure similar to the usual <CODE>keep</CODE> pattern, except that
+there's no <CODE>se</CODE> involved; if we find unequal words, the problem is
+solved without further recursion.  Also, we have two arguments, and either
+of them might be empty.
+
+<P><PRE>(define (<A NAME="g22"></A>sent-before? sent1 sent2)
+  (cond ((empty? sent1) #t)
+	((empty? sent2) #f)
+	((before? (first sent1) (first sent2)) #t)
+	((before? (first sent2) (first sent1)) #f)
+	(else (sent-before? (bf sent1) (bf sent2)))))
+</PRE>
+
+<P>Although thinking about the <CODE>keep</CODE> pattern helped us to work
+out this solution, the result really doesn't look much like a <CODE>keep</CODE>.
+We had to invent most of the details by thinking about this particular
+problem, not by thinking about the pattern.
+
+<P>In the next chapter we'll look at examples of recursive procedures that are
+quite different from any of these patterns.  Remember, the patterns are a
+shortcut for many common problems, but don't learn the shortcut at the
+expense of the general technique.
+
+<P><H2>Pitfalls</H2>
+
+<P>Review the pitfalls from Chapter 12; they're still relevant.
+
+<P>
+<P>How do you test for the base case?  Most of the examples in this
+chapter have used <CODE>empty?</CODE>, and it's easy to fall into the habit of
+using that test without thinking.  But, for example, if the argument is a
+number, that's probably the wrong test.  Even when the argument is a
+sentence or a non-numeric word, it may not be empty in the base case, as in
+the Pig Latin example.  
+
+<P>
+A serious pitfall is failing to recognize a situation in which you need
+an extra variable and therefore need a helper procedure.  If at
+each step you need the entire original argument as well as the argument
+that's getting closer to the base case, you probably need a helper
+procedure.  For example, write a procedure <CODE>pairs</CODE> that takes a word as
+argument and returns a sentence of all possible two-letter words made of
+letters from the argument word, allowing duplicates, like this:
+
+<P><PRE>&gt; (pairs 'toy)
+(TT TO TY OT OO OY YT YO YY)
+</PRE>
+
+<P>
+
+<P>A simple pitfall, when using a helper procedure, is to write a recursive
+call in the helper that calls the main procedure instead of calling the
+helper.  (For example, what would have happened if we'd had <CODE>every-nth-helper</CODE> invoke <CODE>every-nth</CODE> instead of invoking itself?)
+
+<P>Some recursive procedures with more than one argument require more than
+one base case.  But some don't.  One pitfall is to leave out a necessary
+base case; another is to include something that looks like a base case but
+doesn't fit the structure of the program.
+
+<P>For example, the reason <CODE>sent-before?</CODE> needs two base cases is that on
+each recursive call, both <CODE>sent1</CODE> and <CODE>sent2</CODE> get smaller.  Either
+sentence might run out first, and the procedure should return different values
+in those two cases.
+
+<P>On the other hand, Exercise <A HREF="../ssch11/recursion.html#copies">11.7</A> asked you to write a procedure that has
+two arguments but needs only one base case:
+
+<P><PRE>(define (<A NAME="g23"></A>copies num wd)
+  (if (= num 0)
+      '()
+      (se wd (copies (- num 1) wd))))
+</PRE>
+
+<P>In this example, the <CODE>wd</CODE> argument <EM>doesn't</EM> get smaller
+from one invocation to the next.  It would be silly to test for <CODE>(empty? wd)</CODE>.
+
+<P>A noteworthy intermediate case is <CODE><A NAME="g24"></A>every-nth-helper</CODE>.  It does
+have two <CODE>cond</CODE> clauses that check for two different arguments reaching
+their smallest allowable values, but the <CODE>remaining</CODE> clause isn't a base
+case.  If <CODE>remaining</CODE> has the value 1, the procedure still invokes itself
+recursively.
+
+<P>The only general principle we can offer is that you have to think about what
+base cases are appropriate, not just routinely copy whatever worked last
+time.
+
+<P>
+<H2>Exercises</H2>
+
+<P>Classify each of these problems as a pattern (<CODE>every</CODE>, <CODE>keep</CODE>, or
+<CODE>accumulate</CODE>), if possible, and then write the procedure recursively.  In
+some cases we've given an example of invoking the procedure we want you to
+write, instead of describing it.
+
+<P><B>14.1</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g25"></A>remove-once 'morning '(good morning good morning))
+(GOOD GOOD MORNING)
+</PRE>
+
+<P>(It's okay if your solution removes the other <CODE>MORNING</CODE>
+instead, as long as it removes only one of them.)
+<A NAME="remonce"></A>
+
+  
+
+<P>
+<B>14.2</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g26"></A>up 'town)
+(T TO TOW TOWN)
+</PRE>
+
+<P>
+<B>14.3</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g27"></A>remdup '(ob la di ob la da))              ;; remove duplicates
+(OB LA DI DA)
+</PRE>
+
+<P><A NAME="remdup"></A>
+(It's okay if your procedure returns <CODE>(DI OB LA DA)</CODE> instead,
+as long as it removes all but one instance of each duplicated word.)
+
+
+<P>
+<P>
+<B>14.4</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g28"></A>odds '(i lost my little girl))
+(I MY GIRL)
+</PRE><A NAME="exodds"></A>
+
+<P>
+<B>14.5</B>&nbsp;&nbsp;[<A HREF="../ssch8/higher.html#lettcount">8.7</A>]
+Write a procedure <CODE><A NAME="g29"></A>letter-count</CODE> that takes a sentence as its
+argument and returns the total number of letters in the sentence:
+<A NAME="lettcrec"></A>
+
+<P><PRE>&gt; (letter-count '(fixing a hole))
+11
+</PRE>
+
+<P>
+<B>14.6</B>&nbsp;&nbsp;Write <CODE>member?</CODE>.
+
+
+<P>
+<B>14.7</B>&nbsp;&nbsp;Write <CODE>differences</CODE>, which takes a sentence of numbers as its argument
+and returns a sentence containing the differences between adjacent elements.
+(The length of the returned sentence is one less than that of the argument.)
+
+<P><PRE>&gt; (<A NAME="g30"></A>differences '(4 23 9 87 6 12))
+(19 -14 78 -81 6)
+</PRE>
+
+<P>
+<B>14.8</B>&nbsp;&nbsp;Write <CODE>expand</CODE>, which takes a sentence as its argument.  It returns
+a sentence similar to the argument, except that if a number appears in
+the argument, then the return value contains that many copies of the
+following word:
+
+<P><PRE>&gt; (expand '(4 calling birds 3 french hens))
+(CALLING CALLING CALLING CALLING BIRDS FRENCH FRENCH FRENCH HENS)
+
+&gt; (expand '(the 7 samurai))
+(THE SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI)
+</PRE>
+
+<P>
+<B>14.9</B>&nbsp;&nbsp;Write a procedure called <CODE><A NAME="g31"></A>location</CODE> that takes two arguments, a
+word and a sentence.  It should return a number indicating where in the
+sentence that word can be found.  If the word isn't in the sentence, return
+<CODE>#f</CODE>.  If the word appears more than once, return the location of the
+first appearance.
+
+<P><PRE>&gt; (location 'me '(you never give me your money))
+4
+</PRE>
+
+<P>
+<B>14.10</B>&nbsp;&nbsp;Write the procedure <CODE><A NAME="g32"></A>count-adjacent-duplicates</CODE> that takes a
+sentence as an argument and returns the number of words in the sentence that
+are immediately followed by the same word:
+
+<P><PRE>&gt; (count-adjacent-duplicates '(y a b b a d a b b a d o o))
+3
+
+&gt; (count-adjacent-duplicates '(yeah yeah yeah))
+2
+</PRE>
+
+<P>
+<B>14.11</B>&nbsp;&nbsp;Write the procedure <CODE><A NAME="g33"></A>remove-adjacent-duplicates</CODE> that takes a
+sentence as argument and returns the same sentence but with any word that's
+immediately followed by the same word removed:
+
+<P><PRE>&gt; (remove-adjacent-duplicates '(y a b b a d a b b a d o o))
+(Y A B A D A B A D O)
+
+&gt; (remove-adjacent-duplicates '(yeah yeah yeah))
+(YEAH)
+</PRE>
+
+<P>
+<B>14.12</B>&nbsp;&nbsp;Write a procedure <CODE><A NAME="g34"></A>progressive-squares?</CODE> that takes a sentence of
+numbers as its argument.  It should return <CODE>#t</CODE> if each number (other
+than the first) is the square of the number before it:
+
+<P><PRE>&gt; (progressive-squares? '(3 9 81 6561))
+#T
+
+&gt; (progressive-squares? '(25 36 49 64))
+#F
+</PRE>
+
+<P>
+<B>14.13</B>&nbsp;&nbsp;What does the <CODE>pigl</CODE> procedure from Chapter 11 do if you invoke
+it with a word like &quot;frzzmlpt&quot; that has no vowels?  Fix it so that it
+returns &quot;frzzmlptay.&quot;
+
+
+<P>
+<B>14.14</B>&nbsp;&nbsp;Write a predicate <CODE>same-shape?</CODE> that takes two sentences as arguments.
+It should return <CODE>#t</CODE> if two conditions are met:  The two sentences must
+have the same number of words, and each word of the first sentence must have
+the same number of letters as the word in the corresponding position in the
+second sentence.
+
+<P><PRE>&gt; (same-shape? '(the fool on the hill) '(you like me too much))
+#T
+
+&gt; (same-shape? '(the fool on the hill) '(and your bird can sing))
+#F
+</PRE>
+
+
+<P>
+<P>
+<B>14.15</B>&nbsp;&nbsp;<A NAME="mergeex"></A>
+Write <CODE><A NAME="g35"></A>merge</CODE>, a procedure that takes two sentences of numbers as
+arguments.  Each sentence must consist of numbers in increasing order.  <CODE>Merge</CODE> should return a single sentence containing all of the numbers, in
+order.  (We'll use this in the next chapter as part of a sorting algorithm.)
+
+<P><PRE>&gt; (merge '(4 7 18 40 99) '(3 6 9 12 24 36 50))
+(3 4 6 7 9 12 18 24 36 40 50 99)
+</PRE>
+
+<P>
+<B>14.16</B>&nbsp;&nbsp;Write a procedure <CODE><A NAME="g36"></A>syllables</CODE> that takes a word as its argument
+and returns the number of syllables in the word, counted according to the
+following rule: the number of syllables is the number of vowels, except that
+a group of consecutive vowels counts as one.  For example, in the word
+&quot;soaring,&quot; the group &quot;oa&quot; represents one syllable and the vowel &quot;i&quot;
+represents a second one.
+
+<P>Be sure to choose test cases that expose likely failures of your procedure.
+For example, what if the word ends with a vowel?  What if it ends with two
+vowels in a row?  What if it has more than two consecutive vowels?
+
+<P>(Of course this rule isn't good enough.  It doesn't deal with things like
+silent &quot;e&quot;s that don't create a syllable (&quot;like&quot;), consecutive vowels
+that don't form a diphthong (&quot;cooperate&quot;), letters like &quot;y&quot; that are
+vowels only sometimes, etc.  If you get bored, see whether you can teach the
+program to recognize some of these special cases.)  
+
+<P>
+
+<HR>
+<A NAME="ft1" HREF="recur-patterns#text1">[1]</A> That's
+because there are two kinds of people: those who think there are two kinds
+of people, and those who don't.<P>
+<A NAME="ft2" HREF="recur-patterns#text2">[2]</A> If
+you've read Chapter 8, you know that you could implement <CODE>square-sent</CODE> and <CODE>pigl-sent</CODE> without recursion, using the <CODE>every</CODE>
+higher order function.  But try using <CODE>every</CODE> to implement <CODE>letter-pairs</CODE>; you'll find that you can't quite make it work.<P>
+<A NAME="ft3" HREF="recur-patterns#text3">[3]</A> Of course, if your version of
+Scheme has &minus;&infin;, you can use it as the
+return value for an empty sentence, instead of changing the pattern.<P>
+<A NAME="ft4" HREF="recur-patterns#text4">[4]</A> Here's the higher-order function version, from Chapter 8:
+
+<P><PRE>(define (add-numbers sent)
+  (accumulate + (keep number? sent)))
+</PRE>
+
+<P>The higher-order function version is more self-documenting and easier to
+write.  The recursive version, however, is slightly more efficient, because
+it avoids building up a sentence as an intermediate value only to discard it
+in the final result.  If we were writing this program for our own use, we'd
+probably choose the higher-order function version; but if we were dealing
+with sentences of length 10,000 instead of length 10, we'd pay more
+attention to efficiency.<P>
+<A NAME="ft5" HREF="recur-patterns#text5">[5]</A> Dictionaries use a
+different ordering rule, in which the sentences are treated as if they were
+single words, with the spaces removed.  By the dictionary rule, &quot;a c&quot; is
+treated as if it were &quot;ac&quot; and comes after &quot;ab&quot;; by our rule, &quot;a c&quot;
+comes before &quot;ab&quot; because we compare the first words (&quot;a&quot; and &quot;ab&quot;).<P>
+<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
+<A HREF="../ssch13/convince-recur.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="number-name.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>
diff --git a/js/games/nluqo.github.io/~bh/ssch14/recur-patterns.html b/js/games/nluqo.github.io/~bh/ssch14/recur-patterns.html
new file mode 100644
index 0000000..10e4fc4
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch14/recur-patterns.html
@@ -0,0 +1,789 @@
+<P>
+
+<A NAME="fish"></A>
+<P><CENTER><IMG SRC="../ss-pics/fish.jpg" ALT="figure: fish"></CENTER>
+<HTML>
+<HEAD>
+<TITLE>Simply Scheme: Introducing Computer Science ch 14: Common Patterns in Recursive Procedures</TITLE>
+</HEAD>
+<BODY>
+<HR>
+<CITE>Simply Scheme:</CITE>
+<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
+<H2>Chapter 14</H2>
+<H1>Common Patterns in Recursive Procedures</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../simply.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
+Wright</A><BR>University of California, Santa Barbara</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/ssch14.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../ssch13/convince-recur.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="number-name.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
+Press web page for <CITE>Simply Scheme</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+
+<P><A NAME="g1"></A>
+<A NAME="g2"></A>
+
+<P>
+<P>There are two ideas about how to solve programming problems.<A NAME="text1" HREF="recur-patterns.html#ft1">[1]</A> One idea is that programmers work mostly by
+recognizing categories of problems that come up repeatedly and remembering
+the solution that worked last time; therefore, programming students should
+learn a lot of program <EM>patterns,</EM> or <EM>templates,</EM> and fill
+in the blanks for each specific problem.  Another idea is that there are a
+few powerful principles in programming, and that if a learner understands
+the principles, they can be applied to <EM>any</EM> problem, even one that
+doesn't fit a familiar pattern.
+
+<P>Research suggests that an expert programmer, like an expert at any skill,
+<EM>does</EM> work mainly by recognizing patterns.  Nevertheless, we lean
+toward the powerful-principle idea.  The expert's memory is not full of
+arbitrary patterns; it's full of <EM>meaningful</EM> patterns, because the
+expert has gone through the process of struggling to reason out how each
+procedure works and how to write new procedures.
+
+<P>Still, we think it's worth pointing out a few patterns that are so common
+that you'll have seen several examples of each before you finish this book.
+Once you learn these patterns, you can write similar procedures almost
+automatically.  But there's an irony in learning patterns:  In Scheme, once
+you've identified a pattern, you can write a general-purpose procedure that
+handles all such cases without writing individual procedures for each
+situation.  Then you don't have to use the pattern any more!
+Chapter 8 presents several general pattern-handling procedures, called <EM>higher-order</EM> procedures.  In this chapter we'll
+consider the patterns corresponding to those higher-order procedures, and
+we'll use the names of those procedures to name the patterns.
+
+<P>What's the point of learning patterns if you can use higher-order procedures
+instead?  There are at least two points.  The first, as you'll see very
+soon, is that some problems <EM>almost</EM> follow one of the patterns; in
+that case, you can't use the corresponding higher-order procedure, which
+works only for problems that <EM>exactly</EM> follow the pattern.  But you
+can use your understanding of the pattern to help with these related
+problems.  The second point is that in Chapter 19 we'll show how the
+higher-order functions are themselves implemented using these recursive
+patterns.
+
+<P>This chapter isn't an official list of all important patterns; as you gain
+programming experience, you'll certainly add more patterns to your repertoire.
+
+<P><H2>The <CODE><B>Every</B></CODE> Pattern</H2>
+
+<P>Here's a procedure to square every number in a sentence of numbers:
+
+<P><PRE>(define (square-sent sent)
+  (if (empty? sent)
+      '()
+      (se (square (first sent))
+          (square-sent (bf sent)))))
+</PRE>
+
+<P>Here's a procedure to translate every word of a sentence into Pig Latin:
+
+<P><PRE>(define (pigl-sent sent)
+  (if (empty? sent)
+      '()
+      (se (pigl (first sent))
+          (pigl-sent (bf sent)))))
+</PRE>
+
+<P>The pattern here is pretty clear.  Our recursive case will do something
+straightforward to the <CODE>first</CODE> of the sentence, such as <CODE>square</CODE>ing it
+or <CODE>pigl</CODE>ing it, and we'll combine that with the result of a recursive
+call on the <CODE>butfirst</CODE> of the sentence.
+
+<P>The <CODE>letter-pairs</CODE> procedure that we wrote in Chapter 11 is
+an example of a procedure that follows the <CODE>every</CODE> pattern pretty
+closely, but not exactly.  The difference is that <CODE>letter-pairs</CODE> looks
+at its argument sentence two words at a time.
+
+<P><PRE>(define (<A NAME="g3"></A>letter-pairs wd)
+  (if (= (count wd) 1)
+      '()
+      (se (word (first wd) (first (bf wd)))
+          (letter-pairs (bf wd)))))
+</PRE>
+
+<P>Compare this with the earlier definition of <CODE>square-sent</CODE>.  The recursive case still uses <CODE>se</CODE> to combine one
+part of the result with a recursive call based on the <CODE>butfirst</CODE> of
+the argument, but here both the first letter and the second letter of the
+argument contribute to the first word of the result.  That's why the base
+case also has to be different; the recursive case requires at least two
+letters, so the base case is a one-letter word.<A NAME="text2" HREF="recur-patterns.html#ft2">[2]</A>
+
+<P>Let's solve a slightly different problem.  This time, we want to break the
+word down into <EM>non-overlapping</EM> pairs of letters, like this:
+
+<P><PRE>&gt; (disjoint-pairs 'tripoli)                  ;; the new problem
+(TR IP OL I)
+
+&gt; (letter-pairs 'tripoli)                    ;; compare the old one
+(TR RI IP PO OL LI)
+</PRE>
+
+<P>The main difference between these two functions is that in <CODE>disjoint-pairs</CODE> we eliminate two letters at once in the recursive call.  A
+second difference is that we have to deal with the special case of
+odd-length words.
+
+<P><PRE>(define (<A NAME="g4"></A>disjoint-pairs wd)
+  (cond ((empty? wd) '())
+	((= (count wd) 1) (se wd))
+	(else (se (word (first wd) (first (bf wd)))
+		  (disjoint-pairs (bf (bf wd)))))))
+</PRE>
+
+<P><H2>The <CODE><B>Keep</B></CODE> Pattern</H2>
+
+<P>In the <CODE>every</CODE> pattern, we collect the results of transforming each
+element of a word or sentence into something else.  This time we'll consider
+a different kind of problem: choosing some of the elements and forgetting
+about the others.  First, here is a procedure to select the three-letter
+words from a sentence:
+
+<P>
+<PRE>(define (keep-three-letter-words sent)
+  (cond ((empty? sent) '())
+        ((= (count (first sent)) 3)
+         (se (first sent) (keep-three-letter-words (bf sent))))
+        (else (keep-three-letter-words (bf sent)))))
+
+&gt; (keep-three-letter-words '(one two three four five six seven))
+(ONE TWO SIX)
+</PRE>
+
+<P> 
+Next, here is a procedure to select the vowels from a word:
+
+<P><PRE>(define (keep-vowels wd)
+  (cond ((empty? wd) &quot;&quot;)
+        ((vowel? (first wd))
+         (word (first wd) (keep-vowels (bf wd))))
+        (else (keep-vowels (bf wd)))))
+
+&gt; (keep-vowels 'napoleon)
+AOEO
+</PRE>
+
+<P>Let's look at the differences between the <CODE>every</CODE> pattern and the
+<A NAME="g5"></A><A NAME="g6"></A> pattern.  First of all, the <CODE>keep</CODE> procedures have three
+possible outcomes, instead of just two as in most <CODE>every</CODE>-like
+procedures.  In the <CODE>every</CODE> pattern, we only have to distinguish between
+the base case and the recursive case.  In the <CODE>keep</CODE> pattern, there is
+still a base case, but there are <EM>two</EM> recursive cases; we have to
+decide whether or not to keep the first available element in the return
+value.  When we do keep an element, we keep the element itself, not some
+function of the element.
+
+<P>As with the <CODE>every</CODE> pattern, there are situations that follow the <CODE>keep</CODE> pattern only approximately.  Suppose we want to look for doubled
+letters within a word:
+
+<P>
+<PRE>&gt; (doubles 'bookkeeper)
+OOKKEE
+
+&gt; (doubles 'mississippi)
+SSSSPP
+</PRE>
+
+<P>This isn't a pure <CODE>keep</CODE> pattern example because we can't
+decide whether to keep the first letter by looking at that letter alone; we
+have to examine two at a time.  But we can write a procedure using more or
+less the same pattern:
+
+<P><PRE>(define (<A NAME="g7"></A>doubles wd)
+  (cond ((= (count wd) 1) &quot;&quot;)
+        ((equal? (first wd) (first (bf wd)))
+         (word (first wd) (first (bf wd)) (doubles (bf (bf wd)))))
+        (else (doubles (bf wd)))))
+</PRE>
+
+<P>As in the <CODE>evens</CODE> example of Chapter 12, the base case of
+<CODE>doubles</CODE> is unusual, and one of the recursive calls chops off two
+letters at once in forming the smaller subproblem.  But the structure of the
+<CODE>cond</CODE> with a base case clause, a clause for keeping letters, and a
+clause for rejecting letters is maintained.
+
+<P><H2>The <CODE><B>Accumulate</B></CODE> Pattern</H2>
+
+<P>Here are two recursive procedures for functions that combine all of the
+elements of the argument into a single result:
+
+<P><PRE>(define (<A NAME="g8"></A>addup nums)
+  (if (empty? nums)
+      0
+      (+ (first nums) (addup (bf nums)))))
+
+(define (<A NAME="g9"></A>scrunch-words sent)
+  (if (empty? sent)
+      &quot;"
+      (word (first sent) (scrunch-words (bf sent)))))
+
+&gt; (addup '(8 3 6 1 10))
+28
+
+&gt; (scrunch-words '(ack now ledge able))
+ACKNOWLEDGEABLE
+</PRE>
+
+<P>What's the pattern?  We're using some combiner (<CODE>+</CODE> or <CODE>word</CODE>) to connect the word we're up to with the result of the recursive
+call.  The base case tests for an empty argument, but the base case return
+value must be the identity element of the combiner function.
+
+<P>If there is no identity element for the combiner, as in the case of <CODE>max</CODE>, we modify the pattern slightly:<A NAME="text3" HREF="recur-patterns.html#ft3">[3]</A>
+
+<P><PRE>(define (<A NAME="g10"></A>sent-max sent)
+  (if (= (count sent) 1)
+      (first sent)
+      (max (first sent)
+	   (sent-max (bf sent)))))
+</PRE>      
+
+<P><H2>Combining Patterns</H2>
+
+<P><PRE>(define (<A NAME="g11"></A>add-numbers sent)
+  (cond ((empty? sent) 0)
+	((number? (first sent))
+	 (+ (first sent) (add-numbers (bf sent))))
+	(else (add-numbers (bf sent)))))
+
+&gt; (add-numbers '(if 6 were 9))
+15
+</PRE>
+
+<P>This procedure combines aspects of <CODE>keep</CODE> with aspects of <CODE>accumulate</CODE>.  We want to do two things at once: get rid of the words that
+aren't numbers and compute the <EM>sum</EM> of those that are numbers.  (A
+simple <CODE>keep</CODE> would construct a sentence of them.)  <CODE>Add-numbers</CODE>
+looks exactly like the <CODE>keep</CODE> pattern, except that there's a funny
+combiner and a funny base case, which look more like <CODE>accumulate</CODE>.<A NAME="text4" HREF="recur-patterns.html#ft4">[4]</A>
+
+<P> 
+Here's an example that combines <CODE>every</CODE> and <CODE>keep</CODE>.  We want a
+procedure that takes a sentence as its argument and translates every word of
+the sentence into Pig Latin, but leaves out words that have no vowels,
+because the Pig Latin translator doesn't work for such words.  The procedure
+<CODE>safe-pigl</CODE> will be like a <CODE>keep</CODE> pattern in that it keeps only
+words that contain vowels, but like an <CODE>every</CODE> in that the result
+contains transformed versions of the selected words, rather than the words
+themselves.
+
+<P><PRE>(define (<A NAME="g12"></A>safe-pigl sent)
+  (cond ((empty? sent) '())
+	((has-vowel? (first sent))
+	 (se (pigl (first sent)) (safe-pigl (bf sent))))
+	(else (safe-pigl (bf sent)))))
+
+(define (<A NAME="g13"></A>has-vowel? wd)
+  (not (empty? (keep-vowels wd))))
+
+&gt; (safe-pigl '(my pet fly is named xyzzy))
+(ETPAY ISAY AMEDNAY)
+</PRE>
+
+<P>
+Finally, here's an example that combines all three patterns.  In Chapter
+1 we wrote (using higher-order procedures) the <CODE>acronym</CODE>
+procedure, which selects the &quot;real&quot; words of a sentence (the <CODE>keep</CODE>
+pattern), takes the first letter of each word (the <CODE>every</CODE> pattern), and
+combines these initial letters into a single word (the <CODE>accumulate</CODE>
+pattern).  In a recursive procedure we can carry out all three steps at once:
+
+<P><PRE>(define (<A NAME="g14"></A>acronym sent)
+  (cond ((empty? sent) &quot;&quot;)
+	((real-word? (first sent))
+	 (word (first (first sent))
+	       (acronym (bf sent))))
+	(else (acronym (bf sent)))))
+</PRE>
+
+<P>Don't become obsessed with trying to make every recursive problem fit one of
+the three patterns we've shown here.  As we said at the beginning of the
+chapter, what's most important is that you understand the principles of
+recursion in general, and understand how versatile recursion is.  The
+patterns are just special cases that happen to come up fairly often.
+
+<P><H2>Helper Procedures</H2>
+
+<P>Let's say we want a procedure <CODE>every-nth</CODE> that takes a number <EM>n</EM> and a
+sentence as arguments and selects every <EM>n</EM>th word from the sentence.
+
+<P><PRE>&gt; (every-nth 3 '(with a little help from my friends))
+(LITTLE MY)
+</PRE>
+
+<P>We get in trouble if we try to write this in the obvious way, as a sort of
+<CODE>keep</CODE> pattern.
+
+<P><PRE>(define (every-nth n sent)                   ;; wrong!
+  (cond ((empty? sent) '())
+        ((= n 1)
+         (se (first sent) (every-nth <STRONG><BIG>n</BIG></STRONG> (bf sent))))
+        (else (every-nth (- n 1) (bf sent)))))
+</PRE>
+
+<P>The problem is with the <CODE><B>n</B></CODE> that's in boldface.
+We're thinking that it's going to be the <CODE>n</CODE> of the <EM>original</EM>
+invocation of <CODE>every-nth</CODE>, that is, 3.  But in fact, we've already counted
+<CODE>n</CODE> down so that in this invocation its value is 1.  (Check out the first
+half of the same <CODE>cond</CODE> clause.)  This procedure will correctly skip the
+first two words but will keep all the words after that point.  That's
+because we're trying to remember two different numbers: the number we
+should always skip between kept words, and the number of words we still need
+to skip this time.
+
+<P> 
+If we're trying to remember two numbers, we need two names for them.  The
+way to achieve this is to have our official <CODE>every-nth</CODE> procedure call a
+<A NAME="g15"></A><A NAME="g16"></A>helper procedure that takes an extra argument and does the real work:
+
+<P><PRE>(define (<A NAME="g17"></A>every-nth n sent)
+  (every-nth-helper n n sent))
+
+(define (<A NAME="g18"></A>every-nth-helper interval remaining sent)
+  (cond ((empty? sent) '())
+        ((= remaining 1)
+         (se (first sent)
+             (every-nth-helper interval interval (bf sent))))
+        (else (every-nth-helper interval (- remaining 1) (bf sent)))))
+</PRE>
+
+<P>This procedure always calls itself recursively with the same value
+of <CODE>interval</CODE>, but with a different value of <CODE>remaining</CODE> each time.
+<CODE>Remaining</CODE> keeps getting smaller by one in each recursive call until it
+equals 1.  On that call, a word is kept for the return value, and we call
+<CODE>every-nth-helper</CODE> recursively with the value of <CODE>interval</CODE>, that is,
+the <EM>original</EM> value of <CODE>n</CODE>, as the new <CODE>remaining</CODE>.
+If you like, you can think of this combination of an <EM>initialization</EM>
+<A NAME="g19"></A>
+<A NAME="g20"></A>
+procedure and a <EM>helper</EM> procedure as another pattern for your
+collection.
+
+<P>
+<P><H2>How to Use Recursive Patterns</H2>
+
+<P>One way in which recursive patterns can be useful is if you think of them as
+templates with empty slots to fill in for a particular problem.  Here are
+template versions of the <CODE>every</CODE>, <CODE>keep</CODE>, and <CODE>accumulate</CODE>
+patterns as applied to sentences:
+
+<P><PRE>(define (<B>every-something</B> sent)
+  (if (empty? sent)
+      '()
+      (se (______ (first sent))
+	  (<B>every-something</B> (bf sent)))))
+
+(define (<B>keep-if-something</B> sent)
+  (cond ((empty? sent) '())
+	((______<STRONG><BIG>?</BIG></STRONG> (first sent))
+	 (se (first sent) (<B>keep-if-something</B> (bf sent))))
+	(else (<B>keep-if-something</B> (bf sent)))))
+</PRE>
+
+<P>
+<A NAME="keeptemplate"></A>
+<PRE>(define (<B>accumulate-somehow</B> sent)
+  (if (empty? sent)
+      ______
+      (______ (first sent)
+              (<B>accumulate-somehow</B> (bf sent)))))
+</PRE>
+
+<P>Suppose you're trying to write a procedure <CODE>first-number</CODE> that takes a
+sentence as its argument and returns the first number in that sentence, but
+returns the word <CODE>no-number</CODE> if there are no numbers in the argument.
+The first step is to make a guess about which pattern will be most useful.
+In this case the program should start with an entire sentence and select a
+portion of that sentence, namely one word.  Therefore, we start with the
+<CODE>keep</CODE> pattern.
+
+<P><PRE>(define (first-number sent)                  ;; first guess
+  (cond ((empty? sent) '())
+	((______ (first sent))
+	 (se (first sent) (first-number (bf sent))))
+	(else (first-number (bf sent)))))
+</PRE>
+
+<P>The next step is to fill in the blank.  Obviously, since we're looking for a
+number, <CODE>number?</CODE> goes in the blank.
+
+<P>The trouble is that this procedure returns <EM>all</EM> the numbers in the
+given sentence.  Now our job is to see how the pattern must be modified to
+do what we want.  The overall structure of the pattern is a <CODE>cond</CODE> with three clauses; we'll consider each clause separately.
+
+<P>What should the procedure return if <CODE>sent</CODE> is empty?  In that case,
+there is no first number in the sentence, so it should return <CODE>no-number</CODE>:
+
+<P><PRE>((empty? sent) <B>'no-number</B>)
+</PRE>
+
+<P>What if the first word of the sentence is a number?  The program should
+return just that number, ignoring the rest of the sentence:
+
+<P><PRE>((number? (first sent)) <B>(first sent)</B>)
+</PRE>
+
+<P>What if the first word of the sentence isn't a number?  The procedure must
+make a recursive call for the <CODE>butfirst</CODE>, and whatever that recursive
+call returns is the answer.  So the <CODE>else</CODE> clause does not have to be
+changed.
+
+<P>Here's the whole procedure:
+
+<P><PRE>(define (<A NAME="g21"></A>first-number sent)
+  (cond ((empty? sent) 'no-number)
+	((number? (first sent)) (first sent))
+	(else (first-number (bf sent)))))
+</PRE>
+
+<P>After filling in the blank in the <CODE>keep</CODE> pattern, we solved this problem
+by focusing on the details of the procedure definition.  We examined each
+piece of the definition to decide what changes were necessary.  Instead, we
+could have focused on the <EM>behavior</EM> of the procedure.  We would have
+found two ways in which the program didn't do what it was supposed to do:
+For an argument sentence containing numbers, it would return all of the
+numbers instead of just one of them.  For a sentence without numbers, it
+would return the empty sentence instead of <CODE>no-number</CODE>.  We would then
+have finished the job by <EM>debugging</EM> the procedure to fix each of these
+problems.  The final result would have been the same.
+
+<P> 
+<H2>Problems That Don't Follow Patterns</H2>
+
+<P>We want to write the procedure <CODE>sent-before?</CODE>, which takes two sentences
+as arguments and returns <CODE>#t</CODE> if the first comes alphabetically before
+the second.  The general idea is to compare the sentences word by word.  If
+the first words are different, then whichever is alphabetically earlier
+determines which sentence comes before the other.  If the first words are
+equal, we go on to compare the second words.<A NAME="text5" HREF="recur-patterns.html#ft5">[5]</A>
+
+<P><PRE>&gt; (sent-before? '(hold me tight) '(sun king))
+#T
+
+&gt; (sent-before? '(lovely rita) '(love you to))
+#F
+
+&gt; (sent-before? '(strawberry fields forever)
+		'(strawberry fields usually))
+#T
+</PRE>
+
+<P>Does this problem follow any of the patterns we've seen?  It's not an <CODE>every</CODE>, because the result isn't a sentence in which each word is a
+transformed version of a word in the arguments.  It's not a <CODE>keep</CODE>,
+because the result isn't a subset of the words in the arguments.  And it's
+not exactly an <CODE>accumulate</CODE>.  We do end up with a single true or
+false result, rather than a sentence full of results.  But in a typical <CODE>accumulate</CODE> problem, every word of the argument contributes to the solution.
+In this case only one word from each sentence determines the overall result.
+
+<P>On the other hand, this problem does have something in common with the <CODE>keep</CODE> pattern:  We know that on each invocation there will be three
+possibilities.  We might reach a base case (an empty sentence); if not, the
+first words of the argument sentences might or might not be relevant to the
+solution.
+
+<P>We'll have a structure similar to the usual <CODE>keep</CODE> pattern, except that
+there's no <CODE>se</CODE> involved; if we find unequal words, the problem is
+solved without further recursion.  Also, we have two arguments, and either
+of them might be empty.
+
+<P><PRE>(define (<A NAME="g22"></A>sent-before? sent1 sent2)
+  (cond ((empty? sent1) #t)
+	((empty? sent2) #f)
+	((before? (first sent1) (first sent2)) #t)
+	((before? (first sent2) (first sent1)) #f)
+	(else (sent-before? (bf sent1) (bf sent2)))))
+</PRE>
+
+<P>Although thinking about the <CODE>keep</CODE> pattern helped us to work
+out this solution, the result really doesn't look much like a <CODE>keep</CODE>.
+We had to invent most of the details by thinking about this particular
+problem, not by thinking about the pattern.
+
+<P>In the next chapter we'll look at examples of recursive procedures that are
+quite different from any of these patterns.  Remember, the patterns are a
+shortcut for many common problems, but don't learn the shortcut at the
+expense of the general technique.
+
+<P><H2>Pitfalls</H2>
+
+<P>Review the pitfalls from Chapter 12; they're still relevant.
+
+<P>
+<P>How do you test for the base case?  Most of the examples in this
+chapter have used <CODE>empty?</CODE>, and it's easy to fall into the habit of
+using that test without thinking.  But, for example, if the argument is a
+number, that's probably the wrong test.  Even when the argument is a
+sentence or a non-numeric word, it may not be empty in the base case, as in
+the Pig Latin example.  
+
+<P>
+A serious pitfall is failing to recognize a situation in which you need
+an extra variable and therefore need a helper procedure.  If at
+each step you need the entire original argument as well as the argument
+that's getting closer to the base case, you probably need a helper
+procedure.  For example, write a procedure <CODE>pairs</CODE> that takes a word as
+argument and returns a sentence of all possible two-letter words made of
+letters from the argument word, allowing duplicates, like this:
+
+<P><PRE>&gt; (pairs 'toy)
+(TT TO TY OT OO OY YT YO YY)
+</PRE>
+
+<P>
+
+<P>A simple pitfall, when using a helper procedure, is to write a recursive
+call in the helper that calls the main procedure instead of calling the
+helper.  (For example, what would have happened if we'd had <CODE>every-nth-helper</CODE> invoke <CODE>every-nth</CODE> instead of invoking itself?)
+
+<P>Some recursive procedures with more than one argument require more than
+one base case.  But some don't.  One pitfall is to leave out a necessary
+base case; another is to include something that looks like a base case but
+doesn't fit the structure of the program.
+
+<P>For example, the reason <CODE>sent-before?</CODE> needs two base cases is that on
+each recursive call, both <CODE>sent1</CODE> and <CODE>sent2</CODE> get smaller.  Either
+sentence might run out first, and the procedure should return different values
+in those two cases.
+
+<P>On the other hand, Exercise <A HREF="../ssch11/recursion.html#copies">11.7</A> asked you to write a procedure that has
+two arguments but needs only one base case:
+
+<P><PRE>(define (<A NAME="g23"></A>copies num wd)
+  (if (= num 0)
+      '()
+      (se wd (copies (- num 1) wd))))
+</PRE>
+
+<P>In this example, the <CODE>wd</CODE> argument <EM>doesn't</EM> get smaller
+from one invocation to the next.  It would be silly to test for <CODE>(empty? wd)</CODE>.
+
+<P>A noteworthy intermediate case is <CODE><A NAME="g24"></A>every-nth-helper</CODE>.  It does
+have two <CODE>cond</CODE> clauses that check for two different arguments reaching
+their smallest allowable values, but the <CODE>remaining</CODE> clause isn't a base
+case.  If <CODE>remaining</CODE> has the value 1, the procedure still invokes itself
+recursively.
+
+<P>The only general principle we can offer is that you have to think about what
+base cases are appropriate, not just routinely copy whatever worked last
+time.
+
+<P>
+<H2>Exercises</H2>
+
+<P>Classify each of these problems as a pattern (<CODE>every</CODE>, <CODE>keep</CODE>, or
+<CODE>accumulate</CODE>), if possible, and then write the procedure recursively.  In
+some cases we've given an example of invoking the procedure we want you to
+write, instead of describing it.
+
+<P><B>14.1</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g25"></A>remove-once 'morning '(good morning good morning))
+(GOOD GOOD MORNING)
+</PRE>
+
+<P>(It's okay if your solution removes the other <CODE>MORNING</CODE>
+instead, as long as it removes only one of them.)
+<A NAME="remonce"></A>
+
+  
+
+<P>
+<B>14.2</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g26"></A>up 'town)
+(T TO TOW TOWN)
+</PRE>
+
+<P>
+<B>14.3</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g27"></A>remdup '(ob la di ob la da))              ;; remove duplicates
+(OB LA DI DA)
+</PRE>
+
+<P><A NAME="remdup"></A>
+(It's okay if your procedure returns <CODE>(DI OB LA DA)</CODE> instead,
+as long as it removes all but one instance of each duplicated word.)
+
+
+<P>
+<P>
+<B>14.4</B>&nbsp;&nbsp;<PRE>&gt; (<A NAME="g28"></A>odds '(i lost my little girl))
+(I MY GIRL)
+</PRE><A NAME="exodds"></A>
+
+<P>
+<B>14.5</B>&nbsp;&nbsp;[<A HREF="../ssch8/higher.html#lettcount">8.7</A>]
+Write a procedure <CODE><A NAME="g29"></A>letter-count</CODE> that takes a sentence as its
+argument and returns the total number of letters in the sentence:
+<A NAME="lettcrec"></A>
+
+<P><PRE>&gt; (letter-count '(fixing a hole))
+11
+</PRE>
+
+<P>
+<B>14.6</B>&nbsp;&nbsp;Write <CODE>member?</CODE>.
+
+
+<P>
+<B>14.7</B>&nbsp;&nbsp;Write <CODE>differences</CODE>, which takes a sentence of numbers as its argument
+and returns a sentence containing the differences between adjacent elements.
+(The length of the returned sentence is one less than that of the argument.)
+
+<P><PRE>&gt; (<A NAME="g30"></A>differences '(4 23 9 87 6 12))
+(19 -14 78 -81 6)
+</PRE>
+
+<P>
+<B>14.8</B>&nbsp;&nbsp;Write <CODE>expand</CODE>, which takes a sentence as its argument.  It returns
+a sentence similar to the argument, except that if a number appears in
+the argument, then the return value contains that many copies of the
+following word:
+
+<P><PRE>&gt; (expand '(4 calling birds 3 french hens))
+(CALLING CALLING CALLING CALLING BIRDS FRENCH FRENCH FRENCH HENS)
+
+&gt; (expand '(the 7 samurai))
+(THE SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI SAMURAI)
+</PRE>
+
+<P>
+<B>14.9</B>&nbsp;&nbsp;Write a procedure called <CODE><A NAME="g31"></A>location</CODE> that takes two arguments, a
+word and a sentence.  It should return a number indicating where in the
+sentence that word can be found.  If the word isn't in the sentence, return
+<CODE>#f</CODE>.  If the word appears more than once, return the location of the
+first appearance.
+
+<P><PRE>&gt; (location 'me '(you never give me your money))
+4
+</PRE>
+
+<P>
+<B>14.10</B>&nbsp;&nbsp;Write the procedure <CODE><A NAME="g32"></A>count-adjacent-duplicates</CODE> that takes a
+sentence as an argument and returns the number of words in the sentence that
+are immediately followed by the same word:
+
+<P><PRE>&gt; (count-adjacent-duplicates '(y a b b a d a b b a d o o))
+3
+
+&gt; (count-adjacent-duplicates '(yeah yeah yeah))
+2
+</PRE>
+
+<P>
+<B>14.11</B>&nbsp;&nbsp;Write the procedure <CODE><A NAME="g33"></A>remove-adjacent-duplicates</CODE> that takes a
+sentence as argument and returns the same sentence but with any word that's
+immediately followed by the same word removed:
+
+<P><PRE>&gt; (remove-adjacent-duplicates '(y a b b a d a b b a d o o))
+(Y A B A D A B A D O)
+
+&gt; (remove-adjacent-duplicates '(yeah yeah yeah))
+(YEAH)
+</PRE>
+
+<P>
+<B>14.12</B>&nbsp;&nbsp;Write a procedure <CODE><A NAME="g34"></A>progressive-squares?</CODE> that takes a sentence of
+numbers as its argument.  It should return <CODE>#t</CODE> if each number (other
+than the first) is the square of the number before it:
+
+<P><PRE>&gt; (progressive-squares? '(3 9 81 6561))
+#T
+
+&gt; (progressive-squares? '(25 36 49 64))
+#F
+</PRE>
+
+<P>
+<B>14.13</B>&nbsp;&nbsp;What does the <CODE>pigl</CODE> procedure from Chapter 11 do if you invoke
+it with a word like &quot;frzzmlpt&quot; that has no vowels?  Fix it so that it
+returns &quot;frzzmlptay.&quot;
+
+
+<P>
+<B>14.14</B>&nbsp;&nbsp;Write a predicate <CODE>same-shape?</CODE> that takes two sentences as arguments.
+It should return <CODE>#t</CODE> if two conditions are met:  The two sentences must
+have the same number of words, and each word of the first sentence must have
+the same number of letters as the word in the corresponding position in the
+second sentence.
+
+<P><PRE>&gt; (same-shape? '(the fool on the hill) '(you like me too much))
+#T
+
+&gt; (same-shape? '(the fool on the hill) '(and your bird can sing))
+#F
+</PRE>
+
+
+<P>
+<P>
+<B>14.15</B>&nbsp;&nbsp;<A NAME="mergeex"></A>
+Write <CODE><A NAME="g35"></A>merge</CODE>, a procedure that takes two sentences of numbers as
+arguments.  Each sentence must consist of numbers in increasing order.  <CODE>Merge</CODE> should return a single sentence containing all of the numbers, in
+order.  (We'll use this in the next chapter as part of a sorting algorithm.)
+
+<P><PRE>&gt; (merge '(4 7 18 40 99) '(3 6 9 12 24 36 50))
+(3 4 6 7 9 12 18 24 36 40 50 99)
+</PRE>
+
+<P>
+<B>14.16</B>&nbsp;&nbsp;Write a procedure <CODE><A NAME="g36"></A>syllables</CODE> that takes a word as its argument
+and returns the number of syllables in the word, counted according to the
+following rule: the number of syllables is the number of vowels, except that
+a group of consecutive vowels counts as one.  For example, in the word
+&quot;soaring,&quot; the group &quot;oa&quot; represents one syllable and the vowel &quot;i&quot;
+represents a second one.
+
+<P>Be sure to choose test cases that expose likely failures of your procedure.
+For example, what if the word ends with a vowel?  What if it ends with two
+vowels in a row?  What if it has more than two consecutive vowels?
+
+<P>(Of course this rule isn't good enough.  It doesn't deal with things like
+silent &quot;e&quot;s that don't create a syllable (&quot;like&quot;), consecutive vowels
+that don't form a diphthong (&quot;cooperate&quot;), letters like &quot;y&quot; that are
+vowels only sometimes, etc.  If you get bored, see whether you can teach the
+program to recognize some of these special cases.)  
+
+<P>
+
+<HR>
+<A NAME="ft1" HREF="recur-patterns.html#text1">[1]</A> That's
+because there are two kinds of people: those who think there are two kinds
+of people, and those who don't.<P>
+<A NAME="ft2" HREF="recur-patterns.html#text2">[2]</A> If
+you've read Chapter 8, you know that you could implement <CODE>square-sent</CODE> and <CODE>pigl-sent</CODE> without recursion, using the <CODE>every</CODE>
+higher order function.  But try using <CODE>every</CODE> to implement <CODE>letter-pairs</CODE>; you'll find that you can't quite make it work.<P>
+<A NAME="ft3" HREF="recur-patterns.html#text3">[3]</A> Of course, if your version of
+Scheme has &minus;&infin;, you can use it as the
+return value for an empty sentence, instead of changing the pattern.<P>
+<A NAME="ft4" HREF="recur-patterns.html#text4">[4]</A> Here's the higher-order function version, from Chapter 8:
+
+<P><PRE>(define (add-numbers sent)
+  (accumulate + (keep number? sent)))
+</PRE>
+
+<P>The higher-order function version is more self-documenting and easier to
+write.  The recursive version, however, is slightly more efficient, because
+it avoids building up a sentence as an intermediate value only to discard it
+in the final result.  If we were writing this program for our own use, we'd
+probably choose the higher-order function version; but if we were dealing
+with sentences of length 10,000 instead of length 10, we'd pay more
+attention to efficiency.<P>
+<A NAME="ft5" HREF="recur-patterns.html#text5">[5]</A> Dictionaries use a
+different ordering rule, in which the sentences are treated as if they were
+single words, with the spaces removed.  By the dictionary rule, &quot;a c&quot; is
+treated as if it were &quot;ac&quot; and comes after &quot;ab&quot;; by our rule, &quot;a c&quot;
+comes before &quot;ab&quot; because we compare the first words (&quot;a&quot; and &quot;ab&quot;).<P>
+<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
+<A HREF="../ssch13/convince-recur.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="number-name.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>