15-110 Fall 2010
Midterm Exam #2
90 Minutes

Part 1 (Lists)

 

1.1 (10 points).  Fill in the blanks with Python code in the function below that, given two lists, returns a list which contains the values that are in either one of the input lists but not in both of them. Your function should work for any two lists of any size. This function returns an empty list if there are no values satisfying the condition explained above. Examples:

 

lstA = ['e', 'a', 'l']

lstB = []

result: ['e', 'a', 'l']

lstA = ['e', 'a', 'l']

lstB = ['e', 'a', 'l']

result: []

lstA = ['e', 'a', 'l', 't', 'z']

lstB = ['e','l', 'p']

result: ['a', 't', 'z', 'p']

 

Fill in the blanks:

 

def eitherOr(lstA, lstB):

    lstC = _____________________

 

    sizeA = len(lstA)

    sizeB = len(lstB)

 

    if(___________________________):

        return lstC

    elif(sizeA == 0):

        return _______________

    elif(sizeB == 0):

        return _______________

    else:

        for item in lstA:

            if(_____________________):

                lstC.append(item)

        for item in lstB:

            if(_____________________):

                lstC.append(item)

        return _______________

 

 

1.2 (5 points). What will the following code print?

 

def mystery(li):

    rows = len(li)

    cols = len(li[0]) – 2 #this is very unusual

    newList = [0]*cols

    for i in range(cols):

        newList[i] = [0]*rows

    for j in range(cols):

        for k in range(rows):

            newList[k][j] = li[j][k]

    return newList

 

li = [[3,4,2,6,3], [2,5,7,6,8], [1,5,3,2,9]]

print mystery(li)

 

1.3 (10 points). Write a function findTreasure(myList) that traverses a list of integers simulating a treasure hunt. Begin searching for the treasure (the only element in the list with value -1) starting from the first element. The value of each element represents the index of next element to be visited. Your function will print one out of three messages:

1) if the treasure is found, print "Found treasure in X steps.", where X is the actual number of steps it took to find to the treasure;

2) if the first element in the list is the treasure, print "No steps were needed.";

3) if there is a bad clue (a clue indexing a non existing element), print "Bad clue!".

 

For example, given  myList = [2, -1, 1], your function will print “Found treasure in 2 steps”.  This is because you always start with the first element, myList[0], which has value 2.  This means that the next element to go to is myList[2].  myList[2] has value 1 which means that the next element to be visited is myList[1].  Finally, we realize that myList[1] has value -1 (we have found the treasure!) . It took two clues (or steps) to find the treasure.  Other examples:

 

myList = [3, -1, 1, 5, 5, 2]

Found treasure in 4 steps.

 

myList = [2, -1, 10]

Bad clue!

 

myList = [-1]

No steps were needed.

 

 

Part 2 (Dictionaries)

 

2.1 (9 points). Indicate what each of the following will print. Hint: Each prints no more than 4 lines.

A

d = { }
for value in range(4):
    key = value % 2
    d[key] = value
    print d

 

B

d = { }
s = "AMAZING!!!"
for ch in s:
    if (ch in d):
        print ch
    else:
        d[ch] = 1

 

C

d = dict([(2,3),(17,5),(5,11),(7,7),(8,1)])
for key in sorted(d.keys()):
    if (d[key] in d):
        print key

 

 


2.2 (9 points). The following function is supposed to return True if the two dictionary parameters are equal (same keys all mapped to the same values), but it contains a bug.

 

def equal(d1, d2):
    for key in d1:
        if (key not in d2) or (d1[key] != d2[key]):
            return False
    return True

2.2A) In just a few words of English, describe the bug.

 

2.2.B) Give example values for d1 and d2 such that the buggy equal(d1, d2) will return a wrong answer.


 

C) Write some additional code that fixes the bug.  Include an arrow back to the original function above indicating where your code should be inserted.  You may not change any code, but only add more code to the function.


2.3 (7 points). Write the function inverse(d), which takes a dictionary mapping people’s names to their home state, and returns the inverse dictionary, mapping states to a list of the people with that home state.  For example, say that d equals this dictionary: 

     {'Bob': 'PA', 'Dan': 'NY', 'Ann': 'OH', 'Cam': 'PA'}
 

This means that Bob is from PA, Ann is from OH, Cam is from PA, and Dan is from NY.  Then:

inverse(d) returns this dictionary:
 

     {'NY': ['Dan'], 'PA': ['Bob', 'Cam'], 'OH': ['Ann']}
 

Do not worry about the order of any of the keys or the values.

 

Part 3 (Events and animations)

 

3.1 (8 points). Tracing.

 

3.1A) Assuming the usual run function with a 300x300 canvas, state in just a few words of plain English what this animation does in general:

 

def mousePressed(event):
    canvas = event.widget.canvas
    canvas.data["x"] = event.x
    canvas.data["y"] = event.y
    redrawAll(canvas)

def redrawAll(canvas):
    canvas.delete(ALL)
    x = canvas.data["x"]
    y = canvas.data["y"]
    canvas.create_rectangle(0,0,x,y)

def init(canvas):
    canvas.data["x"] = 100
    canvas.data["y"] = 100

 

3.1.B) In the following 300x300 canvas, draw the preceding animation after the user presses the mouse at (150,50).


           


3.1.C) Assuming the usual run function with a 300x300 canvas, state in just a few words of plain English what this animation does in general:

 

def keyPressed(event):
    canvas = event.widget.canvas
    key = event.char
    if ((key < "A") or (key > "Z")):
        canvas.data["keys"] += key
    redrawAll(canvas)

def redrawAll(canvas):
    canvas.delete(ALL)
    keys = canvas.data["keys"]
    x = len(keys)
    canvas.create_text(150,100,text=str(x))
    canvas.create_text(150,200,text=keys[x-3:x])

def init(canvas):
    canvas.data["keys"] = "..."

 

 

 

3.1.D) In the following 300x300 canvas, draw the preceding animation after the user types this:  Hi#Ho!


           



3.2 (8 points). Assuming the usual run function, the following animation is supposed to display a rectangle that alternates between green and yellow, with the animation pausing or unpausing each time the user presses “p”.  The pause feature is broken, unfortunately, so as it is now, the program pauses on “p” but never unpauses.  For this problem, you will fix this bug in two separate ways.

 

def keyPressed(event):
    canvas = event.widget.canvas
    if (event.char == "p"):
        canvas.data["paused"] = not canvas.data["paused"]

def timerFired(canvas):
    redrawAll(canvas)
    if (canvas.data["paused"] == False):
        canvas.data["counter"] += 1
        delay = 250 # milliseconds
        canvas.after(delay, timerFired, canvas)

def redrawAll(canvas):
    canvas.delete(ALL)
    color = "green"
    if (canvas.data["counter"] % 2 == 0):
        color = "yellow"
    canvas.create_rectangle(100, 100, 200, 200, fill=color)

def init(canvas):
    canvas.data["counter"] = 0
    canvas.data["paused"] = False

3.2.A) Fix the pause bug by changing the timerFired function (and nothing else).  You may make edits to the following code:

 

def timerFired(canvas):
    redrawAll(canvas)
    if (canvas.data["paused"] == False):
        canvas.data["counter"] += 1
        delay = 250 # milliseconds
        canvas.after(delay, timerFired, canvas)


 


3.2.B) Fix the pause bug by changing the keyPressed function (and nothing else).  You may make edits to the following code:

 

def keyPressed(event):
    canvas = event.widget.canvas
    if (event.char == "p"):
        canvas.data["paused"] = not canvas.data["paused"]

3.3 (9 points). Assuming the usual run function with a 300x300 canvas, write an animation that first displays a horizontal line of length 100 that is centered in the canvas, and a ball of radius 10 that is centered on the right endpoint of the line.  Each time the user presses the left arrow, the ball moves one pixel left, until the center of the ball reaches the left endpoint of the line, after which left presses are ignored.

 

Part 4 (File IO, web scraping, intro to data analysis)

 

4.1 (6 points) What will the following code print?

 

A

fileHandler = open("myfile.txt", "wt")

fileHandler.write("one\ntwo")

fileHandler.write("threefour\n")

fileHandler.write("five")

fileHandler.close()

fileHandler = open("myfile.txt", "rt")

text = fileHandler.read()

fileHandler.close()

print text

 

B

fileHandler = open("myfile.txt", "wt")

fileHandler.write("501234\n")

fileHandler.write("3\n")

fileHandler.close()

fileHandler = open("myfile.txt", "rt")

lines = fileHandler.readlines()

fileHandler.close()

s1 = lines[0]

s2 = lines[1]

print s1[0:2] * int(s2)

 


 

4.2 (7 points) The function mixUpLines(fileName) is supposed to take a file name, read that file, crazily swap its lines around, and save it back. Clumsily, I ran this function on the same "py" file that defined it, and now it's all messed up! Would you reorder the lines to reconstruct the original function?

                                                                                                                          line:                 correct order:

    inputFileHandler.close()

1

 

 

    lines = inputFileHandler.readlines()

2

 

 

        lines[lineIndex] = lines[swapLineIndex]

3

 

 

        tempLine = lines[lineIndex]

4

 

 

    inputFileHandler = open(fileName, "rt")

5

 

 

    outputFileHandler.writelines(lines)

6

 

 

    outputFileHandler = open(fileName, "wt")

7

 

 

    for lineIndex in range(len(lines)):

8

 

 

        swapLineIndex = (lineIndex * 2) % len(lines)

9

 

 

def mixUpLines(fileName):

10

 

 

    outputFileHandler.close()

11

 

 

        lines[swapLineIndex] = tempLine

12

 

 

 

4.3 (5 points) True or false?

 

A

Files on a hard disk can hold data permanently, whereas variables in the computer's main memory are lost when the computer is turned off.

TRUE

FALSE

B

Scraping data from the web is an effective way to obtain fresh, up to date data.

TRUE

FALSE

C

Discovering patterns from raw data is an important step towards the acquisition of actionable knowledge supported by the data.

TRUE

FALSE

D

To scrape data from a web page, we need to find appropriate patterns in the page's source.

TRUE

FALSE

E

Once we find the right patterns in a website, and write the right code, we will always be able to scrape data from that particular website in the future using the same code.

TRUE

FALSE

 

4.4 (7 points) A restaurant order transaction is composed of the following attributes:

            date, time, food item 1, food item 2, ..., food item N, total price, tip

 

List exactly 7 transactions that collectively exhibit the following patterns:

 

a) People tend to eat soup more often at dinner than lunch.

b) People who eat pasta tend to tip more generously than people who eat pizza.

c) Hamburgers are often eaten with fries, but not with carrots.

 

 

date

time

food1

food2

food3

price

tip

1

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

7

 

 

 

 

 

 

 

 

Part 5 (Bonus/Optional Section)
 

(5 bonus points). Crazy tracing: What will these expressions return?

 

A

[[1,[2,3],4],5][0:3][1]

 

B

[1,{1:2},{1:3}][1:3][1][1]

 

C

[1*3,'1'*3,{1:3},[1]*3][3][1]

 

D

{1:['x','y'],7:'hey',9:1}[1][1]+'ou'

 

E

{'hey':'won','I':'got','do':'it'}[{'I':'hey','you':'do'}['I']]