;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; U. C. Berkeley ;; ;; EECS Computer Science Division ;; ;; CS3 Lecture 16 (Review) Answers ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; COUNT-IF-NOT ;;;;;;;;;;;;;;; ;; NAMING CONVENTION FOR THIS DOCUMENT ;; ;; If I name it "foo-broken", it's broken for one reason or another ;; ;; If I name it "foo1", it's probably an attempt that will work but ;; is not ideal. ;; ;; If I name it "foo", it's ideal ;; Recall count-if (define (count-if pred? s) (count (keep pred? s))) ;; Sample predicate (define (a-word? w) (equal? 'a (first w))) ;; Testing (count-if a-word? '(apples bob cat)) ;; ==> 1 ;; Now, let's try to write count-if-not (define (count-if-not1 pred? s) (count (keep (lambda (w) (if (pred? w) #f #t)) s))) ;; Testing (count-if-not1 a-word? '(apples bob cat)) ==> 2 ;; What's wrong with the above implementation? ;; ==> We almost never need to explicitly put #f/#t ;; ==> in our code, so we can probably simplify it. (define (count-if-not2 pred? s) (count (keep (lambda (w) (if (pred? w) (not (pred? w)) (not (pred? w)))) s))) ;; Testing (count-if-not2 a-word? '(apples bob cat)) ==> 2 ;; What's wrong with the above implementation? ;; ==> Note that the then and else clauses are the same! ;; ==> This means regardless of the test, we'll do the ;; ==> same thing. This then means we don't need the if... ;; Perfect solution below (define (count-if-not pred? s) (count (keep (lambda (w) (not (pred? w))) s))) ;; Testing (count-if-not a-word? '(apples bob cat)) ==> 2 ;; But realize that we also have count-if at our disposal, ;; So why not call it? (define (count-if-not-broken1 pred? s) (not (count-if pred? s))) ;; What's wrong with the code above? ;; ==> The range of count-if is numbers, "not" will always ;; ==> return #f -- Somehow we need to do something with ;; ==> numbers, not with booleans (define (count-if-not-broken2 pred? s) (count-if (not pred?) s)) ;; What's wrong with the code above? ;; ==> Domain of count-if is a procedure ;; ==> and not returs booleans. Not of a ;; ==> procedure is always #f. ;; Written so that we're calling count-if correctly (define (count-if-not pred? s) (count-if (lambda (w) (not (pred? w))) s)) ;; Another perfect solution, better than others ;; because it composes other HOFs without doing ;; all the work of the lambda, which is arguably ;; the same work as writing count-if in the first place. (define (count-if-not pred? s) (- (count s) (count-if pred? s))) ;; Testing (count-if-not a-word? '(apples bob cat)) ;; ==> 2 ;; MAKE-XNOR ;;;;;;;;;;;; (define (make-xnor) (lambda (bool1 bool2) (or (and bool1 bool2) (and (not bool1) (not bool2))))) ;; or (define (make-xnor) (lambda (bool1 bool2) (equal? bool1 bool2))) ;; The difference between the first and the second is that the ;; first handles cases when the input isn't necessarily pure bools. ;; Testing ( (make-xnor) #f #f) ;; ==> #t ( (make-xnor) #f #t) ;; ==> #f ( (make-xnor) #t #f) ;; ==> #f ( (make-xnor) #t #t) ;; ==> #t ;; MAKE-XOR ;;;;;;;;;;; (define (make-xor) (lambda (bool1 bool2) (not ((make-xnor) bool1 bool2)))) ;; or (define (make-xor) (lambda (bool1 bool2) (not (equal? bool1 bool2)))) ;; or (define (make-xor) (lambda (bool1 bool2) (or (and bool1 (not bool2)) (and (not bool1) bool2)))) ;; Testing ( (make-xor) #f #f) ;; ==> #f ( (make-xor) #f #t) ;; ==> #t ( (make-xor) #t #f) ;; ==> #t ( (make-xor) #t #t) ;; ==> #f ;; ADD-SENTS ;;;;;;;;;;;; This problem is "Not within your power...yet!" This isn't meant to be tricky, just meant to highlight that there are some problems which are unsolvable with your current amount of "power