Practice with Mutation and Loops
As always, work with your neighbor and talk about the problems. Also, upload your answers.
Mutation Toy Examples
Quiz 5 had several problems checking whether you understood mutation on lists. Here are a few more, some of which are trickier. What does each print? Try to figure each out before running it in CodeSkulptor.
-
list1 = range(5) list1[1:3] = list1[3:5] print list1
-
list2 = range(5) list2[1:3] = list2 print list2
-
This one might be surprising. Remember that a list can contain any kind of value.
list3 = range(5) list3[2] = range(5) print list3
-
And now for the toughest one. Try drawing a picture with arrows pointing to each object, as in the Programming Tips video you watched before today.
list4 = range(5) list4[2] = list4 print list4
Loops
-
We've had examples which repeatedly appended new elements to the back of a list. What is the effective difference if you instead repeatedly add new elements to the front of a list? E.g., what is the resulting difference between the following two functions?
numbers = [4, 8, 3, 7] def add_to_back(numbers): """Repeatedly adds elements to the back of the new resulting list.""" result = [] for number in numbers: result.append(number) return result def add_to_front(numbers): """Repeatedly adds elements to the front of the new resulting list.""" result = [] for number in numbers: result.insert(0, number) return result
Try to figure out the difference before trying each of them in CodeSkulptor.
-
In the previous class, you wrote
evens_list()
, which takes a list of numbers and returns a list of all of the even integers in the list. Now write a similar functionevens_noduplicates()
, which takes a list of numbers and returns a list of all the even integers in the list, but without any duplicates.For example,
evens_list([4, 8, 3, 7, 4])
should return[4, 8, 4]
, whileevens_noduplicates([4, 8, 3, 7, 4])
should return[4, 8]
.Hint: Check whether the element you're about to add to the resulting list is in the result already.
-
Write
noduplicates()
that takes a list and returns a list with the same elements, but without duplicates.For example,
noduplicates([5, 8, 3, 5, 8, 2])
should return[5, 8, 3, 2]
.Hint: Use the approach of the previous example. You'll find it easier than trying to remove elements from the input list.
Note that a simpler approach uses Python sets, but we haven't introduced those yet.
Deleting elements of a list
In the previous example, one approach to implement noduplicates()
would be to remove elements from the input list. In general, this is a common
goal. For example, in a video game we might have a list of enemy ships, and
we want to remove those that we've shot.
-
Here is one attempt that fails. Can you figure out why?
numbers = range(10) numbers_to_remove = [3, 7, 2] def remove_elements1(input_list, elements_to_remove): for idx in range(len(input_list)): if input_list[idx] in elements_to_remove: input_list.pop(idx) return input_list # so that the function can be tested. remove_elements1(numbers, numbers_to_remove) print numbers
Hint: Add some
print
statements to print out the local variables and see what's happening in the loop. Try adding one right after thefor
and another right after theif
. Addingprint
statements is a very useful debugging technique that you'll probably want to use frequently.(If you want to try running the above function through the OwlTest unit tests via the link below, please change the name of the function to
remove_elements
because that is the name the unit tests are expecting.) -
Here is a similar attempt that fails. Can you figure out why?
numbers = range(10) numbers_to_remove = [3, 7, 2] def remove_elements2(input_list, elements_to_remove): for elt in input_list: if elt in elements_to_remove: input_list.remove(elt) return input_list # so that the function can be tested. remove_elements2(numbers, numbers_to_remove) print numbers
Hint: Again, add some
print
statements to print out the local variables and see what's happening in the loop.(If you want to try running the above function through the OwlTest unit tests via the link below, please change the name of the function to
remove_elements
because that is the name the unit tests are expecting.) -
Define a version of
remove_elements()
that works. It takes the same two arguments as in the previous versions. Unlike the previous two versions, loop overelements_to_remove
, and remove each element frominput_list
.This illustrates the standard two-stage approach of removing undesired elements from a list. First, build up a list of elements that you want to remove. Then, loop over those undesired elements, removing each from your original list.
Test your
remove_elements
function using OwlTest. -- Be sure that yourremove_elements
function returns theinput_list
!
Collatz Conjecture
Back on Quiz 4, question 4 asked you to write a program for the Collatz Conjecture. The problem was pretty tough, especially given that loops had just been introduced. You've now had more practice with loops, so if you couldn't solve it then, try again now.
For your assignment
Here is an implementation of the predator-prey algorithm, in case you were unable to finish it in the previous class.
import simpleplot def delta_h(h, l, hare_birth, hare_predation): """Returns the predicted annual change in hare population.""" return h * hare_birth - h * l * hare_predation def delta_l(h, l, lynx_birth, lynx_death): """Returns the predicted annual change in lynx population.""" return h * l * lynx_birth - l * lynx_death def populations(h, l, hare_birth, hare_predation, lynx_birth, lynx_death, years): """Returns the predicted populations of hare and lynx for the given inputs.""" hare_pop = [(0, h)] lynx_pop = [(0, l)] for y in range(1, years + 1): h, l = (h + delta_h(h, l, hare_birth, hare_predation), l + delta_l(h, l, lynx_birth, lynx_death)) hare_pop.append((y, h)) lynx_pop.append((y, l)) simpleplot.plot_lines("Hares and Lynx Populations", 600, 400, "Years", "Population", [hare_pop, lynx_pop], False, ["Hares", "Lynx"]) populations(100, 50, .4, .003, .004, .2, 50)
As you are working on assignment 2, there is one mysterious behavior you might encounter, and you would want to know why. As you try inputs for the predator-prey populations problem, your program might get very slow and even timeout. It is possible that the populations can get very big, and unfortunately CodeSkulptor's math is very slow with really big numbers. There's nothing you can do about it, except to use different inputs which don't lead to really big populations.