CSC151 2007S, Class 21: Discussion of Exam 1 Admin: * In spite of the storm (which had us without power on the night I intended to do grading), I got your exams graded. * There may be a slight delay, however, in getting the readings online (there are two, one on input an one on output). * Homework extended to Friday because of power failure. Overview: * Notes on exam 1. /Returning Exams/ * Returned at the end of class (so that you pay attention) * Sam does not report median, mean, stddev, max, min, etc. * Time spent does not correlate to grade Time spent now does not correlate well to time spent at the end of the semester * If you don't get the key idea in a reasonable amount of time, email or visit SamR * Remember: Tutors are available On To The Problems /Problem 1: Describing Types/ * Sam looked for: Type coverage - Handling of numeric types * A clever solution (cond ... ((number? val) (string-append (if (exact? val) "an exact " "an inexact ") (cond ((integer? val) "integer") ((real? val) "real") ((complex? val) "complex number") (else "number")))) * If you don't have the else for "number", you should use it for complex. * Flaw (cond ((complex? val) "complex number") ((real? val) "real") ((integer? val) "integer") (else "number")))) * Flaw: Too much mixing of if and cond (if (cond (if (cond (if * Flaw: Testing for lists (cond ... ((null? val) "an empty list") ((list? val) "a list") * Flaw: exact/inexact integer/complex * What about keywords? (and, or, cond, if, ...) * They are not values (define mystery? (lambda (val) (if (symbol? val) #t (if (string? val) #t #f)))) (define symbol-or-string? (lambda (val) (or (symbol? val) (string? val)))) (b) (5 points) (define puzzle? (lambda (a b c) (if (< a b) (if (< b c) #t #f) (if (< b c) #f #t)))) (define puzzle? (lambda (a b c) (if (< a b) (< b c) (not (< b c))))) (define puzzle? (lambda (a b c) (if (< a b) (< b c) (not (< b c))))) if test1 test2 test3) => (or (and test1 test2) (and (not test1) test3)) (define puzzle? (lambda (a b c) (or (and (< a b) (< b c)) (and (not (< a b)) (not (< b c)))))) (define puzzle? (lambda (a b c) (or (< a b c) (and (>= a b)) (>= b c)))))) (define descending-or-strictly-ascending? (lambda (a b c) (or (< a b c) (>= a b c)))) A problem: * Some of you wrote (define descending-or-strictly-ascending? (lambda (a b c) (or (< a b c) (> a b c)))) (c) (5 points) (define conundrum? (lambda (lst) (if (list? lst) (if (null? lst) #f (null? (cdr lst))) #f))) # (if test1 test2 #f) => (and test1 test2) (define conundrum? (lambda (lst) (and (list? lst) (if (null? lst) #f (null? (cdr lst)))))) (if test1 #f test2) (if (not test1) test2 #f) (and (not test1) test2) (define conundrum? (lambda (lst) (and (list? lst) (and (not (null? lst)) (null? (cdr lst)))))) Combine the ands! (define one-element-list? (lambda (lst) (and (list? lst) (not (null? lst)) (null? (cdr lst))))) (d) (10 points) Note that this procedure is recursive. (define enigma? (lambda (lst) (if (null? lst) #t (if (symbol? (car lst)) (enigma? (cdr lst)) #f)))) (define list-of-symbols? (lambda (lst) (or (null? lst) (and (symbol? (car lst)) (list-of-symbols? (cdr lst)))))) /Problem 3/ (define join (lambda (val1 val2) (if (list? val1) (if (list? val2) ; list list (append val1 val2) ; list val (add-to-end val1 val2)) (if (list? val2) ; val list (cons val1 val2) ; val val (list val1 val2))))) (define add-to-end (lambda (lst val) (if (null? lst) (list val) (cons (car lst) (add-to-end (cdr lst) val))))) (define add-to-end (lambda (lst val) (append lst (list val)))) (define add-to-end (lambda (lst val) (reverse (cons val (reverse lst))))) Many people wrote (define join (lambda (val1 val2) (cond ((and (list? val1) (list? val2)) ...) ((and (list? val1) (simple? val2)) ...) ((and (simple? val1) (list? val2)) ...) ((and (simple? val1) (simple? val2)) ...)))) "Inefficient" Try to avoid repeating tests (define join (lambda (val1 val2) (let ((islist1? (list? val1)) (islist2? (list? val2))) (cond ((and islist1? islist2?) ...) ((and islist1? (not islist2?)) ...) ((and (not islist1?) islist2?) ...) ((and (not islist1?) (not islist2?)) ...) /Problem 4/ /Problem 4/ (define matching-courses (lambda (characteristic lst) (if (null? lst) null (if (member? characteristic (car lst)) (cons (car lst) (matching-courses characteristic (cdr lst))) (matching-courses characteristic (cdr lst)))))) (define extract-names (lambda (lst) (if (null? lst) null (cons (caar lst) (extract-names (cdr lst)))))) (define find-courses (lambda (characteristic courses) (extract-names (matching-courses characteristic courses)))) (define f-c (lambda (characteristic lst) (if (null? lst) null (if (member? characteristic (car lst)) (cons (caar lst) (f-c characteristic (cdr lst))) (f-c characteristic (cdr lst)))))) Which is better? * f-c is a bit more efficient than find-courses * Perhaps the second permits more activities Should we use letrec for the helpers? * Yes, if you only intend to use them here. * No, if you might use them elsewhere. DON'T CALL YOUR PROCEDURES 'match'