Reading: Practical Programming, Section 7.1 and the start of 7.2.
So far we have used for loops to access each entry in a list or input file in succession and apply one or more operations to each.
Example 1 (from Lecture 7):
co2_levels = [ 320.03, 322.16, 328.07, 333.91, 341.47, 348.92,
357.29, 363.77, 371.51, 382.47, 392.95 ]
avg = sum(co2_levels) / len(co2_levels)
for value in co2_levels:
diff = value - avg
print 'Difference from average is %.2f' %diff, 'ppm'
Example 2 (from HW 3):
# Access the file containing the valid words
words_file = open('words.txt')
# Read each word, remove the white space and the \n and append it to the list
words_list = []
for w in words_file:
w = w.strip().strip('\n')
words_list.append(w)
Example 3 (also from Lecture 1):
def three_double(s):
for i in range(0, len(s)-5):
if s[i] == s[i+1] and s[i+2] == s[i+3] and s[i+4] == s[i+5]:
return True
return False
We already started using ranges in HW 3, but we will go over them in detail here.
A range is a function to generate a list of integers. For example,
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Notice this is up through and not including the last value specified!
If we want to start with something other than 0, we provide the starting values
>>> range(3,8)
[3, 4, 5, 6, 7]
We can create increments. For example,
>>> range(4,20,3)
[4, 7, 10, 13, 16, 19]
starts at 4, increments by 3, stops when 20 is reached or surpassed.
We can create backwards increments
>>> range(-1, -10, -1)
[-1, -2, -3, -4, -5, -6, -7, -8, -9]
We can use the range to generate the list of values in a for loop. Our first example is printing the contents of the planets list
planets = [ 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter',
'Saturn', 'Uranus', 'Neptune', 'Pluto' ]
for i in range(len(planets)):
print planets[i]
The variable i is variously known as the “index” or the “loop index variable” or the “subscript”.
We will modify the loop in class to do the following:
Generate a range for the positive integers less than 100. Use this to calculate the sum of these values, with and without a for loop.
Use a range and a for loop to print the even numbers less than a given integer n.
The years for the CO2 levels were in parts per million every 5 years starting in 1960. Generate a range based on this and on the length of co2_levels. Assign the resulting list to the variable year.
Suppose we want a list of the squares of the digits 0..9. The following does NOT work
squares = range(10)
for s in squares:
s = s*s
Why not? Write a different for loop that uses indexing into the squares list to accomplish our goal.
These types of operations are used over and over again in different programming problems.
We can use our generated list, years, from the third exercise just above, to solve the problem of printing both the year and the CO2 level.
for i in range(len(co2_levels)):
print "Year %d: CO2 level %.2f" %(years[i], co2_levels[i])
Notice that we created a second range of indices and used these to index both years and co2_levels.
We can solve the same problem without using the years range, as in
for i in range(len(co2_levels)):
print "Year %d: CO2 level %.2f" %(1960 + i*5, co2_levels[i])
Sometimes the loop index should not go over the entire range of indices, and we need to think about where to stop it “early”, as the next two examples show.
Example 1: We’d like to count how many years the CO2 level has risen relative to the previous five years. We’ll write a simple loop to do this.
Example 2: Returning to our example from Lecture 1 and HW 3, we will briefly re-examine our solution to the following problem: Given a string, how can we write a function that decides if it has three consecutive double letters?
def has_three_doubles(s):
for i in range(0, len(s)-5):
if s[i] == s[i+1] and s[i+2] == s[i+3] and s[i+4] == s[i+5]:
return True
return False
In each case, we have to think carefully about where to start our looping and where to stop!
The following code for finding out if a word has two consecutive double letters is wrong. Why? When, specifically, does it fail?
def has_two_doubles(s):
for i in range(0, len(s)-5):
if s[i] == s[i+1] and s[i+2] == s[i+3]:
return True
return False
A local maximum, or peak, in a list is a value that is larger than the values next to it. For example,
L = [ 10, 3, 4, 9, 19, 12, 15, 18, 15, 11, 14 ]
has local maxima at indices 4 and 7. (Note that the beginning and end values are not considered local maxima.) Write code to print the index and the value of each local maximum.
Some problems require “iterating” over either
As an example, here is code to print all of the products of digits:
digits = range(10)
for i in digits:
for j in digits:
print "%d x %d = %d" %(i,j,i*j)
How does this work?
We will look at finding the two closest points in a list...
A tuple is simply a list that can not be changed, e.g.
>>> x = (4, 5, 10) # note the parentheses rather than [ ]
>>> print x[0]
4
>>> print x[2]
10
A list can be converted to a tuple:
>>> L = [ 'a', 6 ]
>>> T = tuple(L) # T is a copy of L that can not be changed.
>>> print T[0]
a
>>> L[0] = 'b'
>>> print L[0] # The original list is changed.
b
>>> print T[0] # The tuple created from the list has not.
a
Suppose we are given a list of point locations in two dimensions, where each point is a tuple. For example,
points = [ (1,5), (13.5, 9), (10, 5), (8, 2), (16,3) ]
Our problem is to find the two points that are closest to each other.
The natural idea is to compute the distance between any two points and find the minimum.
We will work through the approach to this and post the result on the Piazza site.
The following simple exercise will help you understand loops better. Show the output of each of the following pairs of for loops. The first two pairs are nested loops, and the third pair is formed by consecutive, or “sequential”, loops.
# Version 1
sum = 0
for i in range(10):
for j in range(10):
sum += 1
print sum
# Version 2
sum = 0
for i in range(10):
for j in range(i+1,10):
sum += 1
print sum
# Version 3
sum = 0
for i in range(10):
sum += 1
for j in range(10):
sum += 1
print sum