In [1]:
# We always start with this!
%pylab inline
Populating the interactive namespace from numpy and matplotlib

1) Devilish Debugging

Oh no! I wrote a simple little function to remove all instances of the number 6 from a list, and it doesn't work! There must be something terribly evil about the number 6.

Can you figure out the problem, and fix my function?

In [2]:
def remove_all_6s(lst):
    """Removes all 6s in a list, and returns the list."""
    for n in lst:
        if n == 6:
            lst.remove(n)
    return lst

remove_all_6s([1,6,6,3,3,6,4,6,5])
Out[2]:
[1, 3, 3, 4, 6, 5]
Note:

This is actually a rather deep and challenging problem that comes up in many languages and in many forms. Do not be discouraged if you have trouble solving it!

Hints:
  1. Modify the code in a hundred different ways, just to see what happens!

  2. Try using print inside the function to see what is happening at each iteration.

  3. Think about what happens when you remove an item from a list in the middle of a for loop. How could you avoid this?

  4. This is an example of a more general problem known as "iterator invalidation," and a bit of internet searching may prove to be illuminating...

1b) To zip or not to zip

The zip function allows you to iterate through 2 or more lists at the same time:

In [3]:
my_list1 = [1, 2, 3, 4]
my_list2 = [10, 20, 30, 40]

for n,m in zip(my_list1, my_list2):
    print(n, '+', m, '=', n + m)
1 + 10 = 11
2 + 20 = 22
3 + 30 = 33
4 + 40 = 44

How is this different from "nesting" for loops? What happens if I run the following code? How is this different from using zip like above?

my_list1 = [1, 2, 3, 4]
my_list2 = [10, 20, 30, 40]

for n in my_list1:
    for m in my_list2:
        print(n, '+', m, '=', n + m)

2) Shopping list for pumpkin pie

It is fall season - time to bake a pumkin pie! Because I don't really remember what goes into a pumpkin pie, I looked up a recipe. We can keep the needed ingredients in a python list of strings.

ingredients = ["pumpkin","sweetened condensed milk","eggs","cinnamon","ginger","nutmeg","salt","pie crust"]

It turns out I have a bunch of stuff in stock, but not all of it can be used for making my pie.

stock = ["chair","salt","milk","eggs","flour","lemon juice","frozen fish","apples","sugar","dish washing soap","sweetened condensed milk","ginger","garlic","pumpkin","potatoes"]

2a) What do I need to buy?

Write a function shoppinglist(ingredients, stock) that will return a list with all the items that I need for the pie but I don't have in stock.

2b) What's left in stock?

Write a function update_stock that removes all items from stock that I will be using for the pie. The function should return an updated stock list. Assume that an item gets used up entirely when I bake my pie.

3) Smiley competition

Let's draw some smiley faces!

Let's start with the following code:

In [4]:
def draw_circle(radius, npoints=100):
    angles = linspace(0, 2*pi, npoints)
    xs = cos(angles) * radius
    ys = sin(angles) * radius
    
    plot(xs, ys, 'k-')
    axis('equal')
    axis('off')

draw_circle(2.0)

3a) Modify the above code to be able to plot a circle at a different center or with a different angle.

Example function signature:
def draw_circle(radius, center_x=0, center_y=0, start_angle=0.0, end_angle=2*pi, npoints=100):
    # Your code here

3b) Use this function to draw a smiley face!

You can use a circle for the edge of the face, a circle for each of the eyes, and a partial circle (with start_angle and end_angle different from 0 and $2 \pi$) for the smile.

I made the following one before class:

Smiley Face!

4) Extending the Heaviside function to arrays

In class we defined the Heavside function in python as step(x). Unfortunaley it does not work on arrays yet, meaning if the input x is an array python will return an error. Use your method of choice (smart indexing or for loops) to redefine step(x) as better_step(x) such that it will work on arrays too. You may use your own definition of step(x) or you can use the one provided below.

def step(x):
    "This is the Heaviside step function. It returns 0 for x values below 0, 1/2 for x = 0, and 1 for x > 0."
    if x < 0:
        return 0
    elif x == 0:
        return 0.5
    else:
        return 1
Check your function by plotting the output in the range from -1 to +1:
x = linspace(-1,1,num = 1000)
y = better_step(x)
plot(x,y,'o')

5) Finding Prime numbers

5a) Write a program that finds all the factors of a number.

Your function should return a list of all the numbers less than $n$ that $n$ is divisible by.

Example output:
>>> get_factors(7)
[1, 7]
>>> get_factors(12)
[1, 2, 3, 4, 6, 12]
Hints:

You can use for i in range(n, m+1): to loop over all numbers between n and m inclusively.

To check if x is divisible by y, you can use the modulo (or remainder) operator:

>>> 12 % 3 == 0
True
>>> 12 % 5 == 0
False

5b) Write a function that tests if a number is prime.

Remember that a number is prime if its only two factors are 1 and itself.

Example output:
>>> is_prime(7)
True
>>> is_prime(12)
False
Hints:

You can use the get_factors function we defined above!

5c) Print all the prime numbers less than 100.

Example output:
2
3
5
7
11
13
17
19
...