about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt')
-rw-r--r--js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt609
1 files changed, 609 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt b/js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt
new file mode 100644
index 0000000..701905a
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/61a-pages/Volume2/Midterm2/mt2-2.soln.txt
@@ -0,0 +1,609 @@
+CS 61A          Solutions to sample midterm 2 #2
+
+1.  What will Scheme print?
+
+Please put in the start arrows!  Sometimes it's hard to know where your
+diagrams are supposed to begin, especially if you use leftward and upward
+pointing arrows.
+
+> (list (cons 2 3) 4)
+((2 . 3) 4)
+
+          +---+---+     +---+---+
+          |   |   |     |   |  /|
+--------->| | | ------->| | | / |
+          | | |   |     | | |/  |
+          +-|-+---+     +-|-+---+
+            |             | 
+            |             V 
+            |                               
+            |             4
+            |                                  
+            V                                  
+          +---+---+
+          |   |   |
+          | | | | |
+          | | | | |
+          +-|-+-|-+
+            |   |
+            V   V
+
+            2   3
+
+Most people got this.  The ones who didn't most often left out the dot
+in the printed version.
+
+
+> (append (cons '(a) '(b)) '(c))
+((A) B C)
+
+           +---+---+   +---+---+   +---+---+
+           |   |   |   |   |   |   |   |  /|
+---------> | | | ----->| | | ----->| | | / |
+           | | |   |   | | |   |   | | |/  |
+           +-|-+---+   +-|-+---+   +-|-+---+
+             |           |           |
+             |           V           V
+             |
+             |           B           C
+             V
+           +---+---+
+           |   |  /|
+           | | | / |
+           | | |/  |
+           +-|-+---+
+             | 
+             V 
+
+             A 
+
+Many people were confused about this one, especially the CONS part.
+Here is a box and pointer diagram of (cons '(a) '(b)).  The starred
+pair is the one created by the CONS:
+
+
+          ***********
+          *+---+---+*        +---+---+
+          *|   |   |*        |   |  /|
+--------->*| | | ----------->| | | / |
+          *| | |   |*        | | |/  |
+          *+-|-+---+*        +-|-+---+
+          ***|*******          | 
+             |                 V 
+             |                                 
+             |                 B 
+             |                                  
+             V                                  
+	   +---+---+
+	   |   |  /|
+	   | | | / |
+	   | | |/  |
+	   +-|-+---+
+	     | 
+	     V 
+
+	     A 
+
+Even though this structure was created using CONS rather than LIST,
+it's a list, because the cdr of the new pair is a list.  This list
+has two elements; the first is (A) and the second is B.  So in
+effect the call to APPEND is (append '((a) b) '(c)).
+
+We weren't very sympathetic to people who drew diagrams like this:
+
+	   +---+---+
+	   |   |   |
+---------->| | | ------> etc
+	   | | |   |
+	   +-|-+---+
+	     | 
+	     V 
+
+	    (A)
+
+Things in parentheses in the printed representation must be shown
+as pairs in the diagram!
+
+
+
+> (cdadar '((e (f) g) h))
+()
+
+Note that the result is (), not '()!
+
+There really is no need for a box-and-pointer diagram for an empty
+list, which is an atom.  We accepted
+
+	   +---+
+	   |  /|
+---------->| / |
+	   |/  |
+	   +---+
+
+but *NOT* this:
+
+	   +---+---+
+	   |  /|  /|
+---------->| / | / |
+	   |/  |/  |
+	   +---+---+
+
+because that would be a pair, representing the list (()), not an empty list.
+
+Some people got this wrong because they figured the cdadar incorrectly.
+Here's how to get there:
+
+(car '((e (f) g) h))  ===>   (e (f) g)
+(cdr '(e (f) g))      ===>   ((f) g)
+(car '((f) g))        ===>   (f)
+(cdr '(f))            ===>   ()
+
+CDADAR is an abbreviation for (cdr (car (cdr (car ...)))), so you have
+to start at the inside and take the CAR of the argument first.  Some
+people read CDADAR left to right as "take the cdr, then the car, ..."
+but that's wrong.
+
+Scoring:  One point for each, with both printed form and b&p diagram
+correct to get the point.  One point total for people who got all three
+printed results correct but left out the b&p diagrams.
+
+
+
+2.  Fill in the blank.
+
+> (CADADR '(g (h i) j))
+I
+
+
+The letter I is the second element of (H I), so it's
+      (cadr '(h i))
+But the sublist (h i) is the second element of the entire argument,
+so it's
+      (cadr '(g (h i) j))
+So we want
+      (cadr (cadr '(g (h i) j)))
+and that's abbreviated as CADADR.
+
+Scoring: one point, all or nothing!
+
+
+3.  Proj2 data abstraction
+
+(a)  Type-tagged segment ADT.  The solution we wanted was this:
+
+(define (make-segment start end)
+  (attach-tag 'segment (cons start end)))
+
+(define (start-segment seg)
+  (car (contents seg)))
+
+(define (end-segment seg)
+  (cdr (contents seg)))
+
+Alternatively, you could use LIST instead of CONS and CADR instead of CDR.
+
+Here is the crucial point to understand about data abstraction:  WE WANT
+THIS CHANGE NOT TO BREAK EXISTING PROCEDURES IN THE PROJECT!  That means
+that start-segment, for example, must return a vector, just as it did
+before the change.
+
+Some people wrote
+
+(define (start-segment seg)    ;; wrong!!!
+  (attach-tag 'segment (car seg)))
+
+One problem with this is that the start-segment of a segment isn't the
+car of the argument anymore, once we have a type attached.  But it's
+much worse to attach the SEGMENT type to the result, because the result
+isn't a segment!  It's a vector.
+
+Other people gave make-segment only one argument.  Probably this means
+that you don't know what a segment is, because you let your partner do
+all the work on the project.
+
+
+Scoring:
+2  As shown above.
+1  Working code, but not respecting the tagged-data abstraction
+     (e.g., cons instead of attach-tag, cadr and cddr in the selectors).
+0  Anything else.
+
+
+(b) Find the midpoint of a segment or frame.
+
+(define (midpoint shape)
+  (cond ((eq? (type-tag shape) 'segment)
+	 (scale-vect 0.5
+		     (add-vect (start-segment shape)
+			       (end-segment shape))))
+	((eq? (type-tag shape) 'frame)
+	 ((frame-coord-map shape) (make-vect 0.5 0.5)))
+	(else #f)))
+
+We accepted less elegant but correct algorithms for the midpoints of
+the shapes.  For a segment another approach is
+
+         (make-vect (/ (+ (xcor-vect (start-segment shape))
+			  (xcor-vect (end-segment shape)))
+		       2)
+		    (/ (+ (ycor-vect (start-segment shape))
+			  (ycor-vect (end-segment shape)))
+		       2))
+
+For frames we saw two other correct approaches.  One was essentially
+to rewrite frame-coord-map:
+
+         (add-vect (origin-frame shape)
+		   (scale-vect 0.5
+			       (add-vect (edge1-frame shape)
+					 (edge2-frame shape))))
+
+Another was to find the midpoint of a diagonal of the parallelogram:
+
+         (midpoint (make-segment (add-vect (origin-frame shape)
+					   (edge1-frame shape))
+				 (add-vect (origin-frame shape)
+					   (edge2-frame shape))))
+
+Most people had correct algorithms for the midpoint of a segment.  There
+were two common incorrect algorithms for frames; one wrong approach was
+to ignore the frame's origin, and the other was to assume that the frame's
+edge1 contributes only to the x-coordinate of the midpoint and that its
+edge2 contributes only to the y-coordinate.
+
+One reason for incorrect solutions to the midpoint of a frame was that
+people confused the origin of the FRAME with the origin of the COORDINATE
+SYSTEM -- that is, the point (0, 0).  The vector returned by
+(origin-frame shape) points from the coordinate system origin (0, 0) to
+the frame's origin, which is one of its corners.  That corner might or
+might not be at (0,0)!  For example, when you wrote procedures like
+BELOW in the project that combine two pictures in adjacent frames, at
+least one of those frames doesn't begin at (0, 0).
+
+Some people wrote a data-directed solution, including things like
+
+   (put 'frame 'midpoint frame-midpoint)
+
+This was okay, but more work than the problem required.  Other people
+tried to use message passing, with less success.  A correct use of
+message passing means that the data -- the frames and segments -- must
+be represented as procedures:
+
+(define (make-segment start end)
+  (lambda (message)
+     ...))
+
+But this is incompatible with part (a)!  Some people tried to use a
+dispatch procedure for the *operator*:
+
+(define (midpoint shape)   ;; wrong!
+   (lambda (message)
+      ...))
+
+but that doesn't make any sense.  You send messages to objects, not
+to operators.  In general, the way to learn in this course is to focus
+on the IDEAS, not on the SYNTAX.  Don't think:  "Message passing means
+that you say (lambda (message) ...) somewhere."  Instead think:
+"Message passing means that the data objects in the system know how
+to carry out operations on themselves."
+
+
+Some people either didn't read or didn't understand the sample exams
+in the course reader.  Here is a quote from the spring 1995 solutions:
+
+    *** RESPECTING THE DATA ABSTRACTION DOES **NOT** MEAN SAYING "DATUM"
+    *** WHENEVER YOU MEAN CAR, AND "CHILDREN" WHENEVER YOU MEAN CDR!!  That
+    is precisely DISrespecting the data abstraction!  Respecting it means to
+    distinguish between a Tree, whose component parts are called datum and
+    children, and other data types that have other component parts, such as
+    forests (car and cdr, since a forest is just a particular kind of
+    sequence), rational numbers (numer and denom), and so on.
+
+The same thing is true here, except that instead of Trees, this problem
+used tagged data.  RESPECTING THE DATA ABSTRACTION DOES **NOT** MEAN
+SAYING "TYPE-TAG" WHENEVER YOU MEAN CAR, AND "CONTENTS" WHENEVER YOU MEAN CDR!
+That is precisely DISrespecting the data abstraction!  Respecting it means
+to distinguish between a type-tagged datum, whose component parts are
+called type-tag and children, and other data types that have other component
+parts, such as segments, frames, and vectors.
+
+
+Scoring:
+
+3  Correct.
+
+2  The structure of the COND correct, and also
+     (a) both algorithms work, but have data abstraction violations, or
+     (b) one algorithm is correct, and there are no DAVs.
+
+1  At least one working algorithm.
+
+0  Other.
+
+
+4.  Maximum path in Tree
+
+(define (maxpath tree)
+  (if (null? (children tree))
+      (datum tree)
+      (+ (datum tree)
+	 (biggest (map maxpath (children tree))))))
+
+Notice that there is no CAR or CDR in this program!
+
+If you didn't want to use MAP, the equivalent recursive solution is
+
+(define (maxpath tree)
+  (if (null? (children tree))
+      (datum tree)
+      (+ (datum tree)
+	 (maxpath-forest (children tree)))))
+
+(define (maxpath-forest forest)
+  (if (null? (cdr forest))
+      (maxpath (car forest))
+      (max (maxpath (car forest))
+	   (maxpath-forest (cdr forest)))))
+
+This solution does take the CAR and the CDR of a forest (which is
+a sequence of Trees), but still does not apply CAR or CDR to a Tree.
+
+In either case, the algorithm is to find the maxpath of each child,
+take the biggest of those, and add the value at the root.  So, for
+the example in the exam, the maxpath values for the three children
+are 10 (7+3), 11 (2+9), and 10 (4+6).  The biggest of those is 11,
+so we add 5 to that and the overall answer is 16.
+
+It doesn't work to find the largest immediate child of the root
+and work downward from there.  In this example, the largest of the
+children is 7, the first child, but the largest overall path doesn't
+go through that child.
+
+
+PLEASE don't ever try to solve a tree problem iteratively!  Iteration
+is good for sequences of information -- that is, for one-dimensional
+structures.  But tree problems are fundamentally recursive.  A lot of
+solutions had the form
+
+(define (maxpath tree)
+  (maxpath-helper tree (children tree) tree '() '() 0 (datum tree)))
+
+or some similar thing with zillions of extra arguments.  All such
+solutions turned out to be quite wrong, and what's worse, they take
+a long time for us to grade!  :-(
+
+
+Here's another correct solution that some people tried:
+
+(define (maxpath tree)
+  (biggest (maxpath-helper tree)))
+
+(define (maxpath-helper tree)
+  (if (null? (children tree))
+      (LIST (datum tree))
+      (map (lambda (t) (+ (MAXPATH t) (datum tree)))
+	   (children tree))))
+
+Unfortunately, most people who tried this made two mistakes; one was
+to leave out the LIST, using just (datum tree) as the base case, and
+the other was to call maxpath-helper instead of the capitalized
+MAXPATH above.  Both of these errors could be avoided by thinking
+about the domains and ranges of the functions involved:
+
+	function	argument	  return
+
+	biggest		list of numbers	  number
+	maxpath		Tree		  number
+	maxpath-helper	Tree		  list of numbers
+
+Since BIGGEST expects a list as its argument, maxpath-helper
+must return a list, even in the base case.  And since + expects
+numbers as arguments, you can't use maxpath-helper to provide
+one of the arguments to +, because maxpath-helper returns a list.
+
+
+This was apparently the hardest problem, mainly because people don't
+understand the Tree Abstract Data Type.  The two parts of a Tree
+are its DATUM, which is a number, and its CHILDREN, which is a forest,
+that is, a list of Trees.  A list of Trees is not a Tree!  An expression
+such as (maxpath (children tree)) has to be wrong because maxpath
+requires a Tree as its argument, not a list of Trees.
+
+
+Scoring:  There were so many wrong approaches that I can't possibly
+list them all.  The general strategy we tried to follow was
+
+5     correct
+3-4   has the idea
+1-2   has an idea
+0     no idea
+
+Here are a few common cases:
+
+4   correct except for the base case
+3   recursive call to maxpath-helper as described above
+2   (maxpath (children tree))
+2   binary tree ADT (e.g., calls to left-branch and right-branch)
+1   (biggest (children tree)) with no recursion
+
+
+5.  Debugging the broken EVAL-1.
+
+Of the six test cases given, the four that don't give error messages
+give the correct answer; it's the two that say ERROR that are wrong.
+What do those two have in common?  A compound expression -- a procedure
+call -- is used as an argument to another procedure.
+
+(In the first case, the expression (* 2 2) provides an argument to +;
+in the second, the expression (+ 1 1) provides an argument to the
+procedure created by the lambda expression.)
+
+So there's something wrong with the evaluation of argument subexpressions.
+That evaluation of subexpressions happens on line 11.  The correct line is
+
+	(map eval-1 (cdr exp)) ))  ; closing earlier open parentheses
+
+The reason some of the test cases *do* work is that numbers are
+self-evaluating, so using the argument expressions instead of the argument
+values doesn't matter if the argument is just a number.  The student said
+
+	(cdr exp) ))	; This is what you should have in your solution.
+
+leaving out the MAP EVAL-1 part.
+
+The most common error was to say that the error was
+
+	(eval-1 (cdr exp)) ))
+
+omitting just the MAP.  But that would be a disaster; none of the examples
+would have worked.  Take the first test case: (+ 2 3).  If that's EXP,
+then (CDR EXP) is (2 3).  But if we try to EVAL-1 that list, we are asking
+to invoke the procedure 2 with the argument 3!
+
+By the way, the reason the last test case doesn't fail is that IF is a
+special form, so eval-1 never reaches line 11; the subexpressions are
+evaluated on lines 6-8.
+
+Scoring: 5 if correct, 2 if line 11 changed incorrectly, otherwise 0.
+(But in the rare cases where the correct change was attributed to line
+10 or 12, we figured you just misread the line numbers and didn't take
+off points.)  We ignored any explanations you gave, which was a good thing
+in some cases because the explanations were iffy.
+
+
+6.  Data directed programming
+
+I said at least twice in lecture that data-directed programming does NOT
+mean using get and put; the book's example of data-directed programming
+is just one example of a more general idea.  The idea is that instead of
+building the specific details of one problem into our procedures, we
+write more general procedures that use some auxiliary data structure to
+specify the precise problem we're supposed to solve.  In this case, the
+list of transitions ((1 A 2) (1 B 3) ...) is the data structure that
+tells our GENERAL fsm interpreter which SPECIFIC fsm we're using.
+
+To make that clearer, here is a program for the particular fsm used as
+the example in the question, NOT using data-directed programming:
+
+(define (transition state letter)
+  (cond ((= state 1) (state1 letter))
+	((= state 2) (state2 letter))
+	((= state 3) (state3 letter))
+	((= state 4) (state4 letter)) ))
+
+(define (state1 letter)
+  (cond ((eq? letter 'A) 2)
+	((eq? letter 'B) 3)
+	((eq? letter 'C) 4)
+	(else 0) ))
+
+(define (state2 letter)
+  (cond ((eq? letter 'A) 1)
+	(else 0) ))
+
+... and so on for the other two states.  This program has the specific
+transition information built into its procedures.  If you wanted to
+change a transition, you'd have to rewrite some procedure.  Some people
+did in fact offer solutions like this, and got no credit.  Here is the
+solution we had in mind:
+
+(define (transition fsm state letter)
+  (cond ((null? fsm) 0)
+	((and (= state (caar fsm))
+	      (eq? letter (cadar fsm)) )
+	 (caddar fsm) )
+	(else (transition (cdr fsm) state letter)) ))
+
+(define (process fsm state wd)
+  (if (empty? wd)
+      state
+      (process fsm (transition fsm state (first wd)) (bf wd)) ))
+
+This program works not only for the particular fsm diagrammed in the
+question, but for ANY fsm, if we give it the appropriate list of
+transitions as an argument.
+
+For some reason that I don't understand, practically everyone returned
+(cddar fsm) instead of the correct (caddar fsm).  You want the third
+ELEMENT of the transition sublist, not a SUBLIST of the transition sublist.
+But we didn't take off for that.
+
+It's perfectly fine if you want to avoid things like "caddar" (pretty hard
+to work through, isn't it?) by defining an abstract data type for
+transitions.  But please don't think that "data-directed programming"
+MEANS using abstract data types.  The two ideas are quite distinct, even
+though we talked about tagged data during the same week as ddp.  If
+you want to use an abstract data type your program will look like this:
+
+(define start-state car)
+(define arrow-label cadr)
+(define end-state caddr)
+
+(define (transition fsm state letter)
+  (cond ((null? fsm) 0)
+	((and (= state (start-state (car fsm)))
+	      (eq? letter (arrow-label (car fsm)) )
+	 (end-state (car fsm)) )
+	(else (transition (cdr fsm) state letter)) ))
+
+You could also define selectors like first-transition and rest-transitions
+for the fsm list itself, but I wouldn't bother.  Car and cdr are clear
+enough for a sequence of any number of the same kind of thing, such as a
+sequence of transition triples.
+
+But, speaking of data types, it won't work at all to use car and cdr on
+the word we're processing in part B!  Car and cdr only work on pairs
+(and lists, which are made of pairs), not on words.
+
+It would indeed be possible to use GET and PUT to implement a data-directed
+fsm program.  You'd set up the program for a particular fsm by PUTting each
+transition, with the start state and letter as the row and column labels,
+and the end state as the contents of each cell.  This isn't exactly what we
+asked for, but we gave full credit if you did that properly.  But we gave
+no credit at all if you tried to invoke the contents of the cell as a
+procedure!  If you did that, you were just blindly copying the example from
+the book without understanding it.
+
+Scoring:  Having the idea in part A meant using the fsm list to write a
+general program.  No credit if the letters A, B, and C appeared in your
+program (not data directed) nor if you invoked something you found in a
+table (totally off the wall).  Having the idea in part B meant using the
+procedure you wrote in part A!  People who tried to do part B from scratch
+invariably wrote programs that CDRed down the fsm list once, then lost it
+and couldn't process the second letter.  If you got part A completely right
+but totally messed up part B, that was three points.  The other way around
+was two points.  If you partially messed up both parts, we used our
+judgement in accord with the standard five-point formula.
+
+
+7. OOP
+
+(a) Parents and children.  A child class is /a kind of/ the parent class, or
+/a specialization of/ the parent class, /not/ a part or subset of the parent.
+
+Is a keypad a kind of cell phone?  NO, a keypad is part of a cell phone.
+
+Is an office building a kind of building?  YES.
+
+Is a staple a kind of stapler?  NO, it's something you put into a stapler.
+
+Is an arm bone a kind of arm?  NO, it's part of the arm.
+
+Is an arm bone a kind of bone?  YES.
+
+Is an arm bone a kind of person?  NO, it's part of a person.
+
+(b) Class or instance variable.  It's a class variable if it's the same for
+every instance of the class; it's an instance variable if each instance has
+its own value.
+
+The number of taxis in the city isn't different for each taxi; it's a property
+of the entire CLASS of taxis.
+
+The number of milk cartons in a fridge is different for each fridge; mine has
+quite a few because my son and I can't agree about whether to use fat-free
+milk or high-fat (2%) milk, so we get both kinds.  A fridge in a photographic
+studio might be full of film, and have no milk cartons at all.  So the number
+is different for each INSTANCE of the fridge class.
+
+Scoring: 1/2 point each, rounded down to an integer.