CSC153, Class 21: Tail Recursion
Overview:
* Notes on exam 1
* Recurrence relations revisited
* Tail recursion
Notes:
* About my meeting.
* Exam 1 returned.
* Questions on homework 2?
* No lab today.
* No reading tonight.
----------------------------------------
General notes on exam 1
Why not to talk about your score
Format of six P's
Two parts to the six P's
* First four P's: General overview
* Last two P's: Formalize
;;; PWORD
;;; some information
;;; Procedure:
;;; NAME IT
;;; Parameters:
;;; NAME 'em, TYPE 'em
;;; One per line
;;; Purpose:
;;; INFORMAL DESCRIPTION
;;; Produces:
;;; NAME IT, TYPE IT
;;; Preconditions:
;;; RESTRICTIONS THAT MUST BE MET IN ORDER FOR
;;; THE CODE TO WORK
;;; Mark 'em as Verified or Unverified
;;; Postconditions:
;;; Reasonable guarantees about results.
;;; As formal as possible.
Beware:
* Lazy programmers who only want to implement minimal postconds.
* Nasty users who want to use silly parameters
Testing (choosing and showing)
* Think carefully.
* (real? val) 1.5
* Reflect on weird results (even if preconditions are not
met)
Number and name your pages
About extra work
Style
Specific notes on each problem
----------------------------------------
Sum of digits
* Testing: Negative numbers, numbers with leading 0's, ...
* (count-digits 00001) -> 1
* Postcondition
+ "sum is the sum of the digits"
+ Assume val has the form d1 d2 d3 ... dn
sum is d1+d2+...dn
+ If val has only one digit (that is, val < 10),
sum = val.
+ If val has more than one digit,
sum = rightmost digit + sum of other digits
(define cd
(lambda (val)
(apply +
(map (lambda (val) (string->number (string val)))
(string->list (number->string val))))))
> (cd -123)
4
----------------------------------------
markup
* Many of you forgot singleton attributes
* Sam wrote some stupid test cases.
* Sam forgot to say "generate a singleton tag" if there
is no text to mark up.
(markup "img" '(("src" "whatever.img")))
----------------------------------------
member?
(define member?
(lambda (val lst)
(and (not (null? lst))
(or (equal? val (car lst))
(member? val (cdr lst))))))
(define member?
(lambda (val lst)
(if (not (list? val))
(error 'member? "parameter not a list")
(and (not (null? lst))
(or (equal? val (car lst))
(member? val (cdr lst)))))))
First time: n steps for "is it a list"
Recursive call: n-1 steps for "is it a list"
Recursive call: n-2 steps for "is it a list?"
n + n-1 + ... + 1 = O(n^2)
Even the better version is O(n).
A case in which precondition testing is a bad idea.
----------------------------------------
(define contains?
(lambda (structure val)
(or (eq? structure val)
(and (not (null? structure))
(or (contains? (car structure) val)
(contains? (cdr structure) val))))))
----------------------------------------
(define union
(lambda (set1 set2)
(append (difference set1 set2) set2)))
(append (difference set1 set2)
(insersection set1 set2)
(difference set2 set1)))
----------------------------------------
Some more fun recurrence relations
f(n) = c + f(n/2)
= c + c + f(n/4)
= c + c + c + f(n/8) = 3c + f(n/8)
= 3c * c + f(n/16) = 4c + f(n/16)
= k*c + f(n/(2^k))
When k is log_2(n),
= log_2(n)*c + f(n/2^(log_2(n)))
= log_2(n)*c + f(n/n)
= log_2(n)*c + f(1)
= log_2(n)*c + 1
f(n) = c + 2*f(n/2)
= c + 2*(c+2*f(n/4)) = 3*c + 4*f(n/4)
= 3*c + 4*(c + 2*f(n/8)) = 7*c + 8*f(n/8)
= 7*c + 8(c + 2*f(n/16)) = 15c + 16*f(n/16)
= ((2^k)-1)*c + (2^k)*f(n/2^k)
When 2^k = n
= (n-1)*c + n*f(1)
f(n) = n + f(n/2)
f(n) = n + 2*f(n/2)
f(n) = c * f(n/2)