Homework 6 Solutions
Solution Files
You can find the solutions in hw06.scm.
You may find it useful to try code.cs61a.org/scheme when working through problems, as it can draw environment and box-and-pointer diagrams and it lets you walk your code step-by-step (similar to Python Tutor). Don't forget to submit your code through Ok though!
Scheme Editor
As you're writing your code, you can debug using the Scheme Editor. In your scheme folder you will find a new editor. To run this editor, run python3 editor. This should pop up a window in your browser; if it does not, please navigate to localhost:31415 and you should see it.
Make sure to run python3 ok in a separate tab or window so that the editor keeps running.
If you find that your code works in the online editor but not in your own interpreter, it's possible you have a bug in code from an earlier part that you'll have to track down. Every once in a while there's a bug that our tests don't catch, and if you find one you should let us know!
Required Questions
Q1: Survey
Please fill out the survey at this link
and fill in hw06.py with the token. The link might not work if you are logged
into some google account other than your Berkeley account, so either log out from all
other accounts or open the link in a private/incognito window and sign in to
your Berkeley account there.
To check that you got the correct token run
Use Ok to test your code:
python3 ok -q survey
Scheme
Getting Started Video
Q2: Thane of Cadr
Define the procedures cadr and caddr, which return the second
and third elements of a list, respectively:
(define (cddr s)
(cdr (cdr s)))
(define (cadr s)
(car (cdr s)))
(define (caddr s)
(car (cddr s)))
Following the given example of cddr, defining cadr and caddr should be
fairly straightforward.
Just for fun, if this were a Python linked list question instead, the solution might look something like this:
cadr = lambda l: l.rest.first
caddr = lambda l: l.rest.rest.first
Use Ok to unlock and test your code:
python3 ok -q cadr-caddr -u
python3 ok -q cadr-caddr
Q3: Sign
Using a cond expression, define a procedure sign that takes in one
parameter val and returns -1 if val is negative, 0 if val is zero, and 1 if val
is positive.
(define (sign val)
(cond ((> val 0) 1)
((= val 0) 0)
((< val 0) -1)))
The order of the cases doesn't really matter, and we could also use an else
clause in the place of one of the conditions.
The condition looks something like this in Python:
if val > 0:
return 1
elif val == 0:
return 0
elif val < 0:
return -1
Opinions differ on which is better, but hopefully you can see that the Scheme
cond is quite readable and compact once you get used to it.
Use Ok to unlock and test your code:
python3 ok -q sign -u
python3 ok -q sign
Q4: Pow
Implement a procedure pow for raising the number base to the power of a
nonnegative integer exp for which the number of operations grows logarithmically, rather than linearly (the number of recursive calls should be much smaller than the input exp). For example, for (pow 2 32) should take 5 recursive calls rather than 32 recursive calls. Similarly, (pow 2 64) should take 6 recursive calls.
Hint: Consider the following observations:
- x2y = (xy)2
- x2y+1 = x(xy)2
You may use the built-in predicates
even?andodd?. Scheme doesn't support iteration in the same manner as Python, so consider another way to solve this problem.
(define (square x) (* x x))
(define (pow base exp)
(cond ((= exp 0) 1)
((even? exp) (square (pow base (/ exp 2))))
(else (* base (pow base (- exp 1))))))
Use Ok to unlock and test your code:
python3 ok -q pow -u
python3 ok -q pow
The else clause shows the basic recursive version of pow that we've seen
before in class.
We save time in computation by avoiding an extra n/2 multiplications of the
base. Instead, we just square the result of base^(exp/2).
Video walkthrough:
Submit
Make sure to submit this assignment by running:
python3 ok --submit