The Sieve of Eratosthenes is a time-honored way to compute prime numbers. The basic idea is this:
Here’s a small example:
Beginning with:
One can actually stop considering factors at \(\sqrt{N}\) because any larger factor would also have a corresponding smaller one. But in today’s program, we’re going to put a twist on the Sieve that requires us to consider all factors from 2 through \(N\).
Rather than crossing out multiples to leave the primes remaining, we’re going to build a list of all of the factors of each number from \(2\) to \(N\).
Here’s the above example again, but keeping a list of the factors of each number. All the numbers from 2 to \(N\) have 1 as a factor, so we start with 1 in every number’s list:
2: 1
3: 1
4: 1
5: 1
6: 1
7: 1
8: 1
9: 1
Then we add 2 to the list for each the multiples of 2; this time we will include 2, because 2 is a factor of 2:
2: 1, 2
3: 1
4: 1, 2
5: 1
6: 1, 2
7: 1
8: 1, 2
9: 1
We’ll continue adding multiples of 3, 4, and so on up to 9, and end up with this:
2: 1, 2
3: 1, 3
4: 1, 2, 4
5: 1, 5
6: 1, 2, 3, 6
7: 1, 7
8: 1, 2, 4, 8
9: 1, 3, 9
Notice that we can still find the primes by looking at which numbers are multiples of only one and themselves (i.e., their lists have length 2).
The skeleton code has only one function for you to implement, but you are encouraged to write helper functions if it would help simplify the code.
The main program takes either one or two command line arguments. The first argument is an integer specifying the number \(N\) from above - the maximum number whose factors are to be computed. If no second argument is printed, the main program prints the factors of all \(N\) numbers in this fashion:
%Run P19_sieve.py 10
2: [1, 2]
3: [1, 3]
4: [1, 2, 4]
5: [1, 5]
6: [1, 2, 3, 6]
7: [1, 7]
8: [1, 2, 4, 8]
9: [1, 3, 9]
10: [1, 2, 5, 10]
If a second argument is provided, then only the list of factors of that number are printed. For example:
>>> %Run P19_sieve.py 32 24
[1, 2, 3, 4, 6, 8, 12, 24]
The main program is not checked by the unit tests, but implementing it correctly will likely help you in testing and debugging.
Implement the following function, without using any built-in
list
methods:
def find(v, lst):
""" Return the index of the first occurrence of v in lst.
Return -1 if v is not in the list. Precondition: lst is a list. """
Implement the following function:
def remove_all(v, lst):
""" Remove all occurrences of v from lst. Precondition: lst is a list. """
Implement the following function:
def without(v, lst):
""" Return a new list that contains all elements in lst except those equal to v.
Precondition: lst is a list. """
*Implement the following function, without using any built-in
list
methods, in such a way that you index into the
list less than len(sorted_lst) times.
def find(v, sorted_lst):
""" Return the index of the first occurrence of v in lst. Return
-1 if v is not in the list. Precondition: lst is a list of things that
can be compared with the < operator, and is in sorted order
(i.e. lst[i] <= lst[i+1] for all i in range(len(lst)-1) """