cs150  Spring 2009

cs150: Computer Science
from Ada and Euclid to Quantum Computing and the World Wide Web


Instructor
Westley Weimer

Teaching Assistants
Zak Fry
Paul DiOrio
Rachel Lathbury

Email Address
cs150-staff@cs.virginia.edu

Class Meetings
Mondays and Wednesdays, 3:30-4:45pm in MEC 341
Structured Lab Hours
Wednesdays, 7:00-8:00pm and 8:00-9:00pm in OLS 001
Staffed Lab Hours
(Small Hall Lab)

Monday 5:00-6:00 (Zak)
Tuesday 3:15-4:15 (Rachel)
Thursday 5:00-6:00 (Paul)
Sunday 3:00-4:00 (on request)
Office & Lab Hours
(Small Hall Lab)

Monday 2:00-3:00 (Rachel)
Tuesday 11:00-12:00 (Wes in Olsson 219)
Tuesday 3:00-4:00 (Zak)
Wednesday 1:00-2:00 (Paul)

Problem Set 7: Hints

You are on your honor to make a good-faith effort to solve problems on your own, or with your partners, before using these hints. This typically means at least 10 minutes of brainstorming, attacking the problem with pencil and paper, drawing small diagrams, and so on. The hints are provided with the intention of reducing frustration when course staff support is not available.

If you use the hints, you should indicate them in your sources list. Using the hints will not influence your grade in any way. However, telling us which hints you used will allow us to know which problems were considered difficult. Example: (define sources (list "I used the hints for problems 3 and 7. The hint for problem 3 was helpful, the hint for problem 7 did not help at all."))

In Python:

sources = ["first source", "second source"]
The hints are written in white text on a white background. On most browsers you make the hint visible by moving your mouse over it. If that doesn't work, click your mouse on the screen and drag it over the box: the text will become visible. Try it out on the apparently-empty box below:

If you can read these words, you are doing it correctly.




Question 1

Hint 1 (getting started):

def intsto(n):
  # put something here 







Hint 2 (more detailed outline):

def intsto(n):
  if n == 0:
    # put something here 
  else:
    # put something else here 







Hint 3 (appending to a list):

    # you may use code like this in the recursive case: 
    res = # ... recursive call
    res.append(n) 
    # ...







Hint 4 (full answer):

def intsto(n):
  if n == 0:
    return []
  else:
    res = intsto(n-1)
    res.append(n)
    return res







Question 2

Hint 1 (general hints, getting started):

The basic form of your answer should be:

charmeFactorialDefinition = '(define factorial ... write stuff here ...)'
You will definitely want to use lambda (because factorial is a function). Since factorial is recursive, it has a base case and an inductive step. You'll need to be check the input to distinguish between those two cases. Unfortunately, Charme does not have an if expression, so you'll need to improvise. Consider using cond.







Hint 2 (if-then-else):

You can convert (if (predicate) A B) into (cond ((predicate) A) (#t B)).







Question 3

Hint 1 (general hints, getting started):

There are two big steps. First, you'll have to add a variable to the globalEnvironment. Second, you'll have to write a Python procedure, such as primitiveLessThanOrEqualTo, that actually implements the <= functionality.







Hint 2 (global environment):

Find the definition of initializeGlobalEnvironment and copy the line with primitiveLessThan, changing it to refer to the '<=' symbol and primitiveLessThanOrEqualTo procedure (which you'll be definining).







Hint 3 (primitive definition):

Find and copy the definition of primitiveLessThan, changing < to <= in both places.







Question 4

Hint 1 (general hints, getting started):

There are three big steps. First, you'll have to add three variables to the globalEnvironment ('cons', 'car' and 'cdr'). Second, you'll have to write three Python procedures: primitiveCons, primitiveCar, and primitiveCdr. Third, you'll have to define a Cons class. The first two parts are largely the same as in Question 3.







Hint 2 (Cons class fields):

To make instance variables (or "fields") in a Python class, just make up names. You might call the parts of your Cons cell _left and _right, for example. If you do so, you can assign to them with statements like self._left = initial_left_value and read from them with self._left.







Hint 3 (Cons class):

Consider making __init__(self,left,right), car(self) and cdr(self) methods for your Cons class. They should each be one or two lines long.







Hint 4 (__str__):

The __str__ method, to pretty-print a Cons cell, is the most complicated part of the class. You'll return to it in Question 6 when you add support for Lists. For now, consider this example (which contains one bug):

  return "(%s . %s)" % (str(self._right), str(self._left))







Question 5

Hint 1:

As usual, you'll want to add two variables to the globalEnvironment: this time they are 'null' and 'null?'. You might associate the former with None and the latter with primitiveIsNull, a Python procedure you write. To check if X is None, use X == None in Python.







Question 6

Hint 1 (general hints, getting started, primitiveList):

You'll want to add one variables to the globalEnvironment: 'list' which references primitiveList, a function that you write. Your primitiveList function will be a recursive Python procedure. If there are no operands (i.e., if the length of operands is 0), it should return None. Otherwise, use your own Cons class: if you say return Cons(X,Y) it will have the same effect as calling the __init__ procedure of your Cons class with X,Y as the second and third arguments.







Hint 2 (detecting lists):

I recommend writing an isList recursive Python procedure that determines if a Cons cell is a list. Recall the definition: None (or null) is a List. A Cons cell is a list if its Cdr is a list. Everything else is not a list.







Hint 3 (__str__):

Now that you can detect a list (see Hint 2), consider code like this:

    def __str__(self):
        if isList(self):
            return "(%s)" % self.strAsList()
        return # ... as before
You just have to write the recursive strAsList method to the Cons class.







Hint 4 (strAsList):

If self._right is None, just return str(self._left). Otherwise return A + " " + B where A corresponds to _left and B corresponds to a recursive call.







Question 7

Hint 1 (general hints, getting started):

Since if is a special form, you do not put it in the globalEnvironment. Go back to Exam 1 Question 2 to review the difference between a speical form and a function.

Instead, you'll want to change meval. Try putting a check for isIf(expr): after the one for isConditional(expr):. Make an evalIf(expr,env) Python procedure.







Hint 2 (evalIf)

As a sanity check, you should check that the length of your expression is 4. Call meval on your first argument (expr[1]). If it's not False, evaluate the second argument. Otherwise, evaluate the third argument.







Question 7

Hint 1 (general hints, getting started):

The basic idea here is to change mapply so that the Procedure case checks to see if we have a stored result for those operands. If so, return the stored result. If not, use the existing code to evaluate the procedure as normal, but then just before you would return, store the result so that we can reuse it later.







Hint 2 (memoization):

Add a _memos field to the Procedure class. Set it to { } in __init__. Add methods like hasResult(self, operands), storeResult(self, operands, result) and getResult(self, operands).

Go look up the Python dictionary datatype to see how to add things to a dictionary, etc. Hint: .has_key, [ ]. I recommend using str(operands) as the key.







[an error occurred while processing this directive]