hw10 - CS 61A - Week 10 Solutions HOMEWORK: 3.16 incorrect...

Info iconThis preview shows pages 1–3. Sign up to view the full content.

View Full Document Right Arrow Icon
Sheet1 Page 1 CS 61A -- Week 10 Solutions HOMEWORK: 3.16 incorrect count-pairs This procedure would work fine for any list structure that can be expressed as (quote <anything>). It fails when there are two pointers to the same pair. (define a '(1 2 3)) (count-pairs a) --> 3 (define b (list 1 2 3)) (set-car! (cdr b) (cddr b)) (count-pairs b) --> 4 (define x (list 1)) (define y (cons x x)) (define c (cons y y)) (count-pairs c) --> 7 (define d (make-cycle (list 1 2 3))) (count-pairs d) --> infinite loop Note from example c that it's not necessary to use mutators to create a list structure for which this count-pairs fails, but it is necessary to have a name for a substructure so that you can make two pointers to it. The name needn't be global, though (define c (let ((x (list 1))) (let ((y (cons x x))) (cons y y) ))) 3.17 correct count-pairs (define (count-pairs lst) (let ((pairlist '()) (count 0)) (define (mark-pair pair) (set! pairlist (cons pair pairlist)) (set! count (+ count 1))) (define (subcount pair) (cond ((not (pair? pair)) 'done) ((memq pair pairlist) 'done) (else (mark-pair pair) (subcount (car pair)) (subcount (cdr pair))))) (subcount lst) count)) The list structure in pairlist can get very complicated, especially if the original structure is complicated, but it doesn't matter. The cdrs of pairlist form a straightforward, non-circular list
Background image of page 1

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full DocumentRight Arrow Icon
Sheet1 Page 2 to anything, but we don't follow down the deep structure of the cars. We use memq, which sees if PAIR (a pair) is eq? (NOT equal?) to the car of some sublist of pairlist. Eq? doesn't care about the contents of a pair looks to see if the two arguments are the very same pair--the same location in the computer's memory. [Non-experts can stop here and go on to the next problem. The following optional material is just for experts, for a deeper understanding.] It's not necessary to use local state and mutation. That just makes the problem easier. The reason is that a general list structure isn't a sequence it's essentially a binary tree of pairs (with non-pairs as the leaves). So you have to have some way to have the pairs you encounter in the left branch still remembered as you traverse the right branch. The easiest way to do this is to remember all the pairs in a variable that's declared outside the SUBCOUNT procedure, so it's not local to a particular subtree. But another way to do it is to have a more complicated helper procedure that takes PAIRLIST as an argument, but also sequentializes the traversal by keeping a list of yet-unvisited nodes, sort of like the breadth-first tree traversal procedure (although this goes depth-first because TODO is a stack, not a queue): (define (count-pairs lst) (define (helper pair pairlist count todo) (if (or (not (pair? pair)) (memq pair pairlist)) (if (null? todo) count (helper (car todo) pairlist count (cdr todo))) (helper (car pair) (cons pair pairlist) (+ count 1) (cons (cdr pair) todo)))) (helper lst '() 0 '())) As you're reading this code, keep in mind that all the calls to HELPER
Background image of page 2
Image of page 3
This is the end of the preview. Sign up to access the rest of the document.

Page1 / 42

hw10 - CS 61A - Week 10 Solutions HOMEWORK: 3.16 incorrect...

This preview shows document pages 1 - 3. Sign up to view the full document.

View Full Document Right Arrow Icon
Ask a homework question - tutors are online