During the twelve days of christmas, we might be wondering how many items our true love gave us, on the nth day. Let's write a function which takes in a natural number n, and returns the sum of the first n numbers. (Sometimes called the nth triangular number -- think of arranging pennies on a table, into triangles.)
Hmmm, before writing code about natural numbers,
let's be sure we're exactly clear on what
the defintion of a natural number is.
Well, ask any 7-year-old: it's
0, 1, 2, 3, ..., 29, 30, 31, ....
But as a definition, this suffers from the ol' dot-dot-dot flaw:
what explicitly is the pattern?
Here's a hint (-:
0, (add1 0), (add1 (add1 0)),
(add1 (add1 (add1 0))), ...
Admittedly, in everday life, we've given given
shortened names to these things after 0,
but mathematicians consider the natural number
in this sense.
(Some texts use "natural numbers" as starting from 1 and
"whole numbers" as starting from 0;
for our purposes, we'll consider zero as natural :-)
Formally:
; A NatNum is: ; - 0, or ; - (add1 NatNum)(Note: How do mathematicians prove things about all natural numbers? They use induction: prove something about 0, and then prove that add1 preserves the desired property; voila. Actually, when proving things about all lists, or all recipes, ... we generalize induction to structural induction. Take comp280 for details :-).
If add1
constructs new natNums,
how do we tear apart a given non-zero natNum, to find the
smaller natNum it's based on? Yes: sub1
.
(Of course, use
(+ .. 1)
and
(- .. 1)
if you prefer.)
What is the template for natural numbers?
Now (in a different color pen) go back and fill in the template, to get the code for (given n) computing the sum of the first n numbers: n + (n-1) + (n-2) ... + 2 + 1.
To think about: how many presents did our true love give us overall? (This is the sum of the first n triangular numbers, sometimes referred to as the nth pyramidal number -- think of arranging a pyramid of cannonballs.)
How about the product of the first n numbers (some times referred to as "n!").
;; (! n): natNum --> num ;; Given n, return n*(n-1)*...*2*1. ;; (define (! n) (cond [(zero? n) ...] [else ..(! (sub1 n))..])) ; Test cases ; (! 2) 2 (! 3) 6 (! 0) ; ??? what should this be?Think of attaching thought-bubbles to various parts of the code: Taking some concrete input (say, n = 23), What is
(sub1 n)
?
How about (! (sub1 n))
?
With a friend, quickly write the function
;; countdown: natNum --> list-of-natNum-or-symbol ;; Return a list of descending numbers, n .. 1, followed by 'blastoff!. ; Examples (countdown 3) = (cons 3 (cons 2 (cons 1 (cons 'blastoff! empty)))) ; (other examples??)At home:
0 1 2 3 4 [posn's x coordinate] x x x x x x x x x x x x x x x x x ... x x [y = 9] x [y = 10] ... x [y = 16] [y = 17](note that the tallest rectangle might occur first in your list.)
Written by Ian Barland
©2002 Stephen Wong