Chapter 14
The sieve of Eratosthenes is an algorithm for making a list of primes that dates back to at least the third century BC:
List the integers, beginning with 2.
Circle 2 (it must be prime),
and cross out all of its multiples. They cannot be prime.
Circle the next integer that is not yet crossed out (3),
and cross out its multiples.
Repeat.
Here is a straight-forward implementation that creates a list of the primes. Recall that the output of the range() function is not itself a list but may be converted to one.
Listing 14.1: Sieve of Eratosthenes
1 # sieve.py
2
3 def sieve(n):
4 primes = list(range(2, n + 1))
5 for k in range(2, n + 1):
6 if k in primes:
7 for j in range(2 * k, n + 1, k):
8 if j in primes:
9 primes.remove(j)
10 return primes
11
12 def main():
13 n = int(input("Enter upper limit: "))
14 print("The primes up to", n, "are:
", sieve(n))
15
16 main()
This program contains nesting that is about as deep as you ever want to go: there is an if inside of a for inside an if inside of a for loop.
Given our description of the sieve, a list should seem like a natural choice to use for its implementation. You are already somewhat familiar with lists, for two reasons. First, we discussed lists briefly in Chapter 4, and second, lists are very similar to strings.
A Python list stores an ordered sequence of items. But while every item in a string is a single character, list elements may be of any Python type. For example, this list:
items = [10, False, "hello", 3.14159]
contains an integer, a boolean, a string, and a float. Lists are written inside square brackets. A pair of empty brackets [] denotes the empty list.
Lists are stored in memory exactly like strings, except that because some of their objects may be larger than others, they store a reference at each index instead of a single character. A reference in Python is just a memory location that points to where an object is actually stored. (Thus, references are also called pointers.) For example, the list named items given above will be stored in memory something like this:
Each of the individual items in the list is stored somewhere else in memory.
In fact, all Python variables are references, but we have ignored that detail to keep things simpler.
Because lists and strings share this similar structure, the following operations all work the same for lists as they do for strings:
⇒ Caution: Concatenation only works between objects of the same type. For example,
items = [1, 4, 7] + "abc"
will cause an error because the type of [1, 4, 7] (list) doesn’t match the type of "abc" (string).
Several other built-in functions are available for both lists and strings:
len(x) |
Number of elements in x. |
min(x) |
Smallest element in x. |
max(x) |
Largest element in x. |
Finally, recall from Chapter 4 that there is a type conversion function for lists:
list(x) |
Convert x to a list. |
These operations work with lists but not strings:
items[i] = x |
Replace items[i] with x. |
items[i:j] = newitems |
Replace items in slice with newitems. |
items[i:j:k] = newitems |
Replace items in slice with newitems. |
del items[i] |
Remove items[i]. |
del items[i:j] |
Remove items in slice. |
del items[i:j:k] |
Remove items in slice. |
sum(items) |
Sum of the elements in items. |
Except for sum(), these all modify the original list.
⇒ Caution: Never modify a list that is driving a for loop. For example, the loop at line 5 of Listing 14.1 cannot be over the list primes, because that list changes inside the body of the loop.
The random module includes these functions for lists:
choice(items) |
One random element from the items. |
shuffle(items) |
Randomly shuffle the elements in items. |
The choice() function also works on strings; the shuffle() function does not.
There is one more piece of new syntax in Listing 14.1 that is going to take some background explanation. Every data type in Python is what is known as an object data type, and in order to understand some of the functionality of Python lists (and strings), we need to begin to use object terminology.
For our purposes, an object data type is one that not only describes how data will be stored and what operations can be done with it; it also provides additional functionality via methods, which are specialized functions that you can ask the object itself to perform. Programming that focuses on using object data types is referred to as object-oriented. The programming you have done to this point without thinking in terms of objects is usually called imperative or procedural.
The syntax to call a method from an object is called dot notation:
<object>.<method>(<arguments>)
Compare this with the syntax for a function call in Chapter 3. The differences are that you must ask a particular object to perform a method, and there is a dot (period) between the object and the name of the method. Calling the same method from different objects will usually produce different results.
If items is a list object, these are some of the methods that may be called on it:
items.append(x) |
Add item x to the end of items. |
items.insert(i, x) |
Insert item x into items at index i. |
items.pop() |
Remove and return the last item in items. |
items.pop(i) |
Remove and return items[i]. |
items.remove(x) |
Remove item x from items. |
|
Raises ValueError when x not in items. |
items.reverse() |
Reverse the order of the elements in items. |
items.sort() |
Sort the list items. |
The remove() method raises an exception if the requested item is not in the list. Exceptions are a Python mechanism for handling errors; for now, we will just try to avoid them.
⇒ Caution: These methods all modify the list they are called on, and only .pop() returns anything. All others return the Python object None, which is returned by any function that does not specify a return value.
for i = 0 to n − 2:
choose a random j between i and n − 1 (inclusive)
swap items i and j
Explain why the for loop does not need to go to n − 1. Write a main() to test your function.
Find the smallest element and swap it with item 0.
Find the next smallest element and swap it with item 1.
Continue.
Test your function on known lists and random lists.
primefactors(24) = [2, 3]
Test your function on n = 2 through 100.
primefactorization(24) = [2, 2, 2, 3]
Test your function on n = 2 through 100. Hint: think of repeated use of smallestdivisor().
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, . . .
defined by beginning with two 1’s and then adding the two previous numbers to get the next one. Write a function fib(n) that returns a list of the first n Fibonacci numbers. How large is the 100th Fibonacci number?
18.218.65.76