CS106A Midterm + solutions

Stanford, Fall 2022-23

Instructions

1. Short Answer (5 points)

a. By each ???, write what value comes from the Python expression:

>>> 1 + 2 * 3 - 2 - 1
???


>>> s = 'Code'
>>> s[2]
???


>>> s[:2]
???


b. What 3 numbers print when the caller() function runs? This code runs without error.

def foo(a):
    b = a + 2
    return b


def caller():
    a = 2
    b = 3
    c = foo(b)
    print(a, b, c)
# What 3 numbers print ???

2. Bit (8 points)

(See the before/after picture below) Bit is at the top of a cliff, facing the right side of the world. Move bit forward, over the valley, to the top of the opposite cliff. Then move bit up to the top of the world, painting every square blue. Leave bit facing up at the top of the world. The valley between the cliffs will be at least 1 square wide.

Bit before and after:
alt: bit before and after

def cross_cliff(filename):
    bit = Bit(filename)
    # Your code here

3. Image (25 points)

Given an image filename and int n which is 1 or more. Produce a new out image made of a horizontally flipped copy of the original image, with an n pixel wide yellow stripe added on its right side. Much of the code is provided, and you fill in key lines in three parts: (a) create the out image, (b) fill in the get_pixel() call for the flipped image, (c) write all the yellow stripe code. The code for the function is below, with spaces (a) (b) (c) where you add your code.

alt: horizontall flipped image with yellow stripe on right side

a. Write one line of code to create the out image.

b. Almost all of the code to write the flipped image is provided — looping over the original image, writing the colors at each "pixel" to "pixel_out". Write the one line of code which sets the "pixel_out" variable used by the later lines in this loop.

c. Write the loops and other needed code to set the n pixel wide stripe to the right of the flipped image to be yellow. These are separate loops, not nested inside the earlier loops for (b). Recall that you can make yellow by setting the blue value to 0.

def flippy(filename, n):
    image = SimpleImage(filename)
    #### a. Create "out" image (Your one-line here)


    # Write flipped image to out
    for y in range(image.height):
        for x in range(image.width):
            pixel = image.get_pixel(x, y)
            #### b. Set "pixel_out" (Your one-line here)


            pixel_out.red = pixel.red
            pixel_out.green = pixel.green
            pixel_out.blue = pixel.blue

    #### c. Write yellow stripe to right of image
    # (Your code here)

4. Strings (17 points)

a. Given a string s. Return a new string made of 2 copies of each non-digit char in s. You may use any loop form.

'ya42y!' -> 'yyaayy!!'
'Blaa423' -> 'BBllaaaa'
'999' -> ''
def double(s):
    # Your code here









b. triple_hat(s): We'll call a substring of 3 up-hats '^^^' a "triple". The string s is guaranteed to contain either 2 separate triples, or zero triples (as shown in the examples below). If the string contains 2 triples, return the substring after the second triple, followed by the substring after the first triple. If there are zero triples, return None. Use the str.find() function.

'this^^^is^^^it' -> 'itis'
'apple^^^1-2-3^^^donut' -> 'donut1-2-3'
'aaabbbccc' -> None
def triple_hat(s):
    # Your code here










5. Grid (25 points)

This problem has two parts, and you can get full credit for each part regardless of what you did on the other part. We have a Grid representing Yosemite national park, and every square is either a bear 'b', honey 'h', or empty None. Bears love honey. In this world, a bear eats honey when the honey is in the one square which is diagonally up and to the right from the bear.

a. Write code for the function: try_snack(grid, x, y) — given a grid and an in-bounds x,y. If there is a bear at that x,y and the one square diagonally up and to the right contains honey, then the bear eats the honey and the snack is a success. For this "success" case, the function should set the honey-containing square to be empty None and return True. If, for whatever reason, the bear snack is not a success at that x,y, then the function should return False and not change the grid.

For the following example grid, try_snack() will succeed only for the two squares x=0, y=1 and x=2, y=1.
alt: 5 x 2 grid of bears and honey

def try_snack(grid, x, y):
    # Your code here










b. Write code for the function: snack_all(grid) — use loops to call the try_snack() function once for every square in the grid. The snacking may proceed through the squares in any order. Count the number of successful snacks in the grid, and return that number when finished. For example, with the grid shown above, snack_all() should return 2, since there are 2 squares where try_snack() succeeds.

def snack_all(grid):



6. 3-Layer Encryption (20 points)

This problem uses a 3-layer encryption scheme somewhat like the homework. As a simplification, all text in the inputs, outputs, and lists for this problem will use non-uppercase chars. The encryption uses three input lists, all the same length, source, nums, and slug, like this:

source = ['b', 'a', 'c', 'd']
nums   = [ 1 ,  2 ,  3,   0 ]
slug   = ['c', 'a', 'd', 'b']

indexes    0    1    2    3

How to encrypt a char ch:

1. If the input char ch is in the source list, look at the same index in the "nums" list — the number found there is the index of the encrypted form of ch in the slug list. The index into the slug list will be correct and in-bounds.

2. If the input ch is not in the source list, its encrypted form is ch unchanged.

Example encryption of 'a' with lists shown above: 'a' is at index 1 in source list. Look at index 1 in nums list: the number there is 2. Therefore the encrypted form of ch is at index 2 in the slug list: 'd'.

# Examples using above 3 lists:
Encrypt of 'a' is 'd'
Encrypt of 'b' is 'a'
Encrypt of 'd' is 'c'
Encrypt of '@' is '@'
def encrypt_char(source, nums, slug, ch):
    # Your code here
    

Solutions

#### 1 Warmups

4
d
Co

2 3 5

#### 2 Bit

def cross_cliff(filename):
    bit = Bit(filename)
    # Move to opposite cliff
    # must move first
    bit.move()
    while bit.right_clear():
        bit.move()
    
    # Up to top of world, every square blue
    bit.left()
    bit.paint('blue')
    while bit.front_clear():
        bit.move()
        bit.paint('blue')


#### 3 Image

def flippy(filename, n):
    image = SimpleImage(filename)
    #### a. Create "out" image (Your one-line here)
    out = SimpleImage.blank(image.width + n, image.height)

    # Write flipped image to out
    for y in range(image.height):
        for x in range(image.width):
            pixel = image.get_pixel(x, y)
            #### b. Set "pixel_out" (Your one-line here)
            pixel_out = out.get_pixel(image.width - 1 - x, y)


            pixel_out.red = pixel.red
            pixel_out.green = pixel.green
            pixel_out.blue = pixel.blue

    #### c. Write yellow stripe to right of image
    # (Your code here)
    for y in range(image.height)
        for x in range(n):
            # correct x on this line is most impt of this part
            out_pix = out.get_pixel(image.width + x, y) # or out.width - 1 - x
            out_pix.blue = 0



#### 4 Strings

def double(s):
    result = ''
    for ch in s:  # or for/i/range
        if not ch.isdigit():
            result += ch + ch
    return result


def triple_hat(s):
    hat1 = s.find('^^^')
    if hat1 == -1:
        return None
    hat2 = s.find('^^^', hat1 + 1)  # need + 1
    second = s[hat2 + 3:]
    first = s[hat1 + 3:hat2] 
    return second + first



#### 5  Grid

def try_snack(grid, x, y):
    if grid.get(x, y) != 'b':
        return False

    # check diagonal honey
    # 'b' check above could be added in here with "and"
    if grid.in_bounds(x + 1, y - 1) and grid.get(x + 1, y - 1) == 'h':'
        grid.set(x + 1, y - 1, None)  # eat honey
        return True
    
    return False


def snack_all(grid):
    count = 0
    for y in range(grid.height):
        for x in range(grid.width):
            if try_snack(grid, x, y):
                count += 1
    return count


#### 6 Encryption

# A fair amount of thinking, not much code for this one

def encrypt_char(source, nums, slug, ch):
    if ch in source:
        idx = source.index(ch)  # index in source
        num = nums[idx]         # get num at same index
        return slug[num]        # use that num in slug
    return ch

# Can nest the 3 accesses in one long expr,
# rather a lot for one line
#
#       return slug[nums[source.index(ch)]]