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)