59
Computational discrete mathematics with Python Fred Richman Florida Atlantic University June 21, 2013 Contents 0 Python 2 1 Integers and strings 3 1.1 Decimal and other bases ..................... 5 2 Prime numbers 7 2.1 The smallest prime factor .................... 7 2.2 Using a for-statement ...................... 9 2.3 Testing the algorithm ....................... 10 2.4 Dening a function ........................ 10 2.5 Speeding the algorithm up .................... 11 2.6 Goldbachs conjecture ...................... 12 2.7 Sophie Germain primes ...................... 14 2.8 There are innitely many primes ................ 16 2.9 Largest prime factor ....................... 19 2.10 Complete factorization ...................... 20 2.11 More on recursive functions ................... 21 2.12 Working with lists ........................ 23 3 The Euclidean algorithm 23 3.1 The Euler -function ....................... 25 3.2 The extended Euclidean algorithm ............... 27 3.3 Orders of units modulo n ..................... 29 1

Computational discrete mathematics with Python

  • Upload
    gxsteph

  • View
    130

  • Download
    1

Embed Size (px)

DESCRIPTION

programming with Python

Citation preview

Computational discrete mathematics withPython

Fred RichmanFlorida Atlantic University

June 21, 2013

Contents

0 Python 2

1 Integers and strings 31.1 Decimal and other bases . . . . . . . . . . . . . . . . . . . . . 5

2 Prime numbers 72.1 The smallest prime factor . . . . . . . . . . . . . . . . . . . . 72.2 Using a for-statement . . . . . . . . . . . . . . . . . . . . . . 92.3 Testing the algorithm . . . . . . . . . . . . . . . . . . . . . . . 102.4 Defining a function . . . . . . . . . . . . . . . . . . . . . . . . 102.5 Speeding the algorithm up . . . . . . . . . . . . . . . . . . . . 112.6 Goldbach’s conjecture . . . . . . . . . . . . . . . . . . . . . . 122.7 Sophie Germain primes . . . . . . . . . . . . . . . . . . . . . . 142.8 There are infinitely many primes . . . . . . . . . . . . . . . . 162.9 Largest prime factor . . . . . . . . . . . . . . . . . . . . . . . 192.10 Complete factorization . . . . . . . . . . . . . . . . . . . . . . 202.11 More on recursive functions . . . . . . . . . . . . . . . . . . . 212.12 Working with lists . . . . . . . . . . . . . . . . . . . . . . . . 23

3 The Euclidean algorithm 233.1 The Euler ϕ-function . . . . . . . . . . . . . . . . . . . . . . . 253.2 The extended Euclidean algorithm . . . . . . . . . . . . . . . 273.3 Orders of units modulo n . . . . . . . . . . . . . . . . . . . . . 29

1

4 Sieving for primes 304.1 Counts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

5 Mersenne primes 345.1 The Lucas-Lehmer test . . . . . . . . . . . . . . . . . . . . . . 365.2 Repunits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365.3 Emirps and palindromic primes . . . . . . . . . . . . . . . . . 37

6 Fermat’s theorem 376.1 Carmichael numbers . . . . . . . . . . . . . . . . . . . . . . . 396.2 The Miller-Rabin test . . . . . . . . . . . . . . . . . . . . . . . 40

7 The sum of the squares of the digits of a number 417.1 Happy numbers . . . . . . . . . . . . . . . . . . . . . . . . . . 427.2 Numbers whose digits increase . . . . . . . . . . . . . . . . . . 447.3 Unhappy numbers . . . . . . . . . . . . . . . . . . . . . . . . . 467.4 Changing exponents and bases . . . . . . . . . . . . . . . . . . 47

8 Finding orbits 48

9 Aliquot sequences 51

10 The Collatz function 51

11 Bulgarian solitaire 52

12 The digits of n-factorial 5312.1 Benford’s law . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

13 Sequences of zeros in 2n 56

14 Ciphers 57

15 Stuff 59

0 Python

You can’t do computational mathematics without writing programs. In thiscourse, all of the programs are to be written in Python. There is a lot of

2

material on Python on the web. The particular version I’m going to use isPython 2.7.3. The first thing you need to do is to download Python 2.7.3.You can do this at

http://www.python.org/getit/

After you have downloaded Python, open IDLE, the Python GUI (graph-ical user interface). This gives you an interactive window in which you canplay with Python. The prompt line looks like

>>>

You can try various arithmetic operations first. If you type 2+7, and then“Enter”, you should see

9>>>

Try typing 2*7 and 2/7 and 2**7. The last one should give you 27 which is128. Now try 2**100. The L at the end of the number means that it is a“long integer”.Now type range(10). You should get a list of the first ten numbers,

starting with 0. Lists in Python are enclosed with square brackets, and theentries are separated by commas. Now try range(5,10) and range(-5,10).Try range(a,b) with various values of a and b until you understand how itworks.Now type range(0,100,7) and range(-20,20,3). What do these look

like? Try a few more.Exercise 1. Write down a description of what range(a,b) is for arbi-

trary integers a and b.Exercise 2. Write down a description of what range(a,b,c) is for

arbitrary integers a, b, and c.

1 Integers and strings

We will be working mostly with the integers:

. . .− 5,−4,−3,−2,−1, 0, 1, 2, 3, 4, 5, . . .

3

Your first project is to familiarize yourself with the Python operator %. Getinto the Python interactive mode (shell or console). One way to do this isjust to open IDLE from the start menu. You should see the prompt:

>>>

If you type 2+3, and then “Enter”, you should see

5>>>

If you type 100%17, and then “Enter”, you should see

15>>>

That’s because when you divide 100 by 17 you get a remainder of 15. Thatis, 100 = 5 · 17+15. I have no idea why they use the percent sign to indicatethat function– the same thing is done in the language C.What happens when you type 100%-17 or -100%17 or -100%-17?If you type 100/17, and then “Enter”, you should see

5>>>

That’s because when you divide 100 by 17 you get a quotient of 5 (and aremainder of 15). So 100 is equal to (100/17)*17+(100%17). Type that lastexpression into Python, in the interactive mode, and press “Enter”. Whatdo you get?Exercise 1. Come up with a description of a%b when a and b are arbi-

trary integers.Exercise 2. Describe b/a for arbitrary integers a and b.Exercise 3. Despite its name, the division algorithm is a mathematical

theorem, not an algorithm. One way of stating it is:

If a and b are integers, and a 6= 0, then b = qa + r for uniqueintegers q and r, with 0 ≤ r < |a|. The integer q is called thequotient, and the integer r, the remainder.

Your question is, what is the relationship between q and a/b, and betweenr and b%a? You can only find out by experimenting with Python. You aretrying to describe how Python behaves. Experiment with both negative andpositive values of a and b.

4

1.1 Decimal and other bases

When we write a number like 1776, we use the standard decimal notation.That is, we use ten digits, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and their value depends ontheir position. The first occurrence of the digit 7 in the string of digits ‘1776’stands for seven hundred; the second stands for seventy. The digit 1 standsfor one thousand, and the digit 6 stands for six. That is,

1776 = 1 · 1000 + 7 · 100 + 7 · 10 + 6 · 1

or1776 = 1 · 103 + 7 · 102 + 7 · 101 + 6 · 100

Technically, we can distinguish the numeral ‘1776’from the number 1776, justlike we distinguish the three-letter word ‘cat’from a cat. Another numeralthat stands for 1776 is ‘MDCCLXXVI’.We say that the string of digits ‘1776’is the decimal representation of the

number 1776, or the base-10 representation.If we want to get hold of the last digit in the decimal representation of the

number we can use the Python operation %. The number n%10 is the lastdigit in the decimal representation of n. Try it with 1776. That’s because1776 = 177·10+6. If we want to get hold of the next to the last digit of 1776,we look at 177%10. The number 177 is obtained by by writing 1776/10.Here is a short program that illustrates this:

n = 1776print n, n/10, n%10

Run this program. You should see: 1776 177 6. The two commasseparate the three numbers on the same line, but they don’t appear on thatline with the numbers. Now we want to do the same thing with 177, so weadd two lines to the program:

n = 1776print n, n/10, n%10n = n/10print n, n/10, n%10

The third line replaces n by n/10, that is, it will replace 1776 by 177. Thefourth line is the same as the second line because we want to see the samethings, but with 177 rather than with 1776.

5

Run this program. You should see

1776 177 6

177 17 7

We can continue by repeating those two lines several more times:

n = 1776print n, n/10, n%10n = n/10print n, n/10, n%10n = n/10print n, n/10, n%10n = n/10print n, n/10, n%10n = n/10print n, n/10, n%10

Maybe I went overboard there. Run this program. You should see

1776 177 6

177 17 7

17 1 7

1 0 1

0 0 0

Notice that we have picked off the four digits of 1776 as the last numbers oneach line. I suppose we can consider the number 0 at the end of the fifth lineas the coeffi cien of 104 in the representation of 1776 as

0 · 104 + 1 · 103 + 7 · 102 + 7 · 101 + 6 · 100

but we never write the digit 0 as the first digit in a number. So I should havequit as soon as n became 0. We want to repeat the lines

print n, n/10, n%10n = n/10

as long as n remains positive. But we don’t want to write those lines overand over again. Instead we write

6

n = 1776while n > 0:

print n, n/10, n%10n = n/10

There are several things to notice here. The first is the colon after “while n >0”. That is essential. The second is that the next two lines are both indented.That’s so Python will know to execute both of them until n becomes zero.If you write this program in the IDLE editor (which you should), the colonwill cause the next line to be indented automatically. If we had written

n = 1776while n > 0:

print n, n/10, n%10n = n/10

our program would have printed out 1776 177 6 until doomsday. What doyou think would happen if we had written

n = 1776while n > 0:print n, n/10, n%10n = n/10

Try it.

2 Prime numbers

A prime number is an integer that is greater than 1, but is not the productof two integers that are greater than 1. The two smallest prime numbers are2 and 3. The number 4 is not prime because 4 = 2 · 2; the number 51 is notprime because 51 = 3 · 17. The first twenty prime numbers are

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71

2.1 The smallest prime factor

We want to write a Python program that computes the smallest prime factorp of a given number n. That is, we want to implement Proposition 31 ofBook VII of Euclid’s Elements which says that any number greater than 1is divisible by a prime.

7

You can do this in the interactive mode, but it is less harrowing to do itin the IDLE mode. In that mode, we work with a (built in) text editor on afile containing a Python program. You can create such a file from the IDLEinteractive mode: open a new window by clicking on the “File”button andthen choosing “New Window”. An IDLE editing window comes up. You arenow set to write some Python code which you can save afterwards by clickingon the “File”button and then choosing “Save As”. At that point you willhave to choose where you want to save your file, and what its name willbe. Call it “fiddle.py”, or something more descriptive, but with the “.py”extension.In the IDLE editing window, type the short version of the classic first

program:

print "Hello"

If you are writing a program in the IDLE editing window, you have to usethe word print in order to get any output. The quotation marks indicatethat the word Hello is text. Without the quotation marks, Python wouldassume that it was a variable. You can use single quotes or double quotes.The single quote on my keyboard is on the same key as the double quote. Ican’t seem to get an appropriate single quote with the word processor I’musing. The best I can do is

print ’Hello’

To run the program, press the F5 key. If you haven’t named the programfile before, you will be asked to do so now. Otherwise, Python will simplyask you if it is okay to save the file, which you will normally agree to. Theoutput should then appear in another window called "Python shell". Thiswindow is essentially the interactive window that you worked with before.So you will normally have two windows going: one where you write yourprogram, and one where you see your output. The output for this programshould be Hello.Try running the program after removing the quotation marks. You should

get an ugly error message in red saying that Hello is not defined. Withoutputting back the quotation marks, insert the line

Hello = 3

at the beginning of the file, before the print command. This will set the vari-able named Hello equal to 3. Run the program again to see what happens.

8

The smallest prime factor of n is the smallest integer p greater than 1which divides n. We might as well assume that n ≥ 0 because if n < 0, wecould look at −n instead. If n = 0, then I guess its smallest prime factoris 2; what do you think? If n = 1, then it has no prime factors. (Nobodyconsiders 1 to be a prime, although one can argue that it is.) Those are theonly exceptional cases: The number 0 is exceptional because it is smallerthan its smallest prime factor; the number 1 is exceptional because it has noprime factor.So, for the computation, you may assume that n > 1. You want to try

to divide n successively by 2, 3, 4, 5, . . . until you are successful. You can dothat with the function n % m. So you want to see when n % m is first equalto zero. The condition that n % m is equal to zero is written

n % m == 0

with two equal signs (as in C). A single equal sign is used in an assignmentstatement: x = a+b says to set the value of x equal to a+b. The expressionx == a + b doesn’t say to do anything– it has the value True if x is equalto a + b, and the value False if x is not equal to a + b. An expression thattakes on the values True or False is called a boolean expression. Anotherboolean expression is x < y.A typical use of boolean expressions is in an if statement. The statement

if n % m == 0: print ’Hello’

prints out ‘Hello’if m divides n. The boolean expression is n % m == 0.Note the colon. You need that. It separates the boolean expression from thecommands. Here we have only one command: print ’Hello’.Exercise 1. What do you see if you print the boolean expression 3 % 2

== 0? The boolean expression 2 < 3? What if you print ’2 < 3’?

2.2 Using a for-statement

Suppose n > 1 is an integer. We want to run through the integersm, startingat 2, to see if any of them divide the positive integer n. When we come acrossone that does, we’ll print it out so we can see it. There is at least one thatdoes, namely n itself. We can do this as follows for the integer n = 91:

n = 91

9

for m in range(2,n+1):if n % m == 0:

breakprint m

Note the colons after the for-statement and after the if-statement. The“break” instruction says “get out of this for-statement”. The indentationsare very important in Python. They tell you that the for-statement goes onuntil the statement print m. The list range(2,n+1) consists of those integersm such that 2 ≤ m < n+1. Note that 2 is an allowable value of m, but n+1is not. In general, the set range(a,b) consists of those integers m such thata ≤ m < b. The value of m when we exit the for-loop will be the smallestinteger greater than 1 that divides n.Exercise 1. Write this program in your file fiddle.py, or write it in a

another file with a name like temp.py. Run this program using differentvalues of n. What can you say about n if the program prints out n?

2.3 Testing the algorithm

You should test the program to see if it works. Of course you just could tryit on a few selected numbers, and you should do that. Another thing youcould do is print out what it does on the first 100 numbers greater than 1(for example) and eyeball the results to see if they look okay. This, of course,would be done with another for-loop, which would start:

for n in range(2,102):

Inside that for-loop we have to put our original for-loop. Moreover, youshould not just print out m, you should print out both n and m, so you willget a list of pairs: the number, and its smallest prime factor. Something like

print n,m

which prints out n followed by a space followed by m.

2.4 Defining a function

Better yet, you can define a function that takes a natural number n > 1 andreturns its least prime factor. Then you can call that function instead ofhaving to worry about nested for-loops. You already have the required linesof code, you just have to write it down as a function:

10

def spf(n):for m in range(2,n+1):

if n % m == 0:return m

The first line says that we are defining a function called spf that will acton a variable n. The command “return m”makes m the result of applyingthe function spf to n. You don’t have to write break to get out of the loopbecause a return statement takes you out of the whole function.To test this function, write a for-loop that runs n from 2 to 50, say, and

print out n together with the smallest prime dividing n. Your print statementwill look something like

print n, spf(n)

2.5 Speeding the algorithm up

This is a dumb algorithm. For one thing, it’s pointless to see if m dividesn when m2 is greater than n. Why is that? Well, if m2 > n and m dividesn, then n/m < m also divides n so we would have already broken out of theloop when we tested the smaller number n/m. Once m2 is greater than n, wealready know that n is prime, so we should just return n. Notice that if n isaround 1000000, this means that you will be doing around 1000 tests ratherthan 1000000 tests, so this improvement is well worth doing. It doesn’t takemuch, just (essentially) one more line:

def spf(n):for m in range(2,n+1):

if n % m == 0:return m

if m*m > n:return n

You can write this in fewer lines by putting the return-statements up on thesame lines as the if-statements:

def spf(n):for m in range(2,n+1):

if n % m == 0: return m

11

if m*m > n: return n

The upper limit n+ 1 is only necessary when n = 2, otherwise we could usethe upper limit n (why is that?). We could add a line after the for-loop thatreturns 0, so that the function will return something even if n is less than 2,but we are really only interested in what happens when n ≥ 2.

2.6 Goldbach’s conjecture

Goldbach’s conjecture is that you can write any even number greater than 2as the sum of two primes. Here is a short table showing how that works:

4 = 2 + 2 6 = 3 + 3 8 = 3 + 5 10 = 3 + 7 12 = 5 + 714 = 3 + 11 16 = 3 + 13 18 = 5 + 13 20 = 3 + 17 22 = 3 + 1924 = 5 + 19 26 = 3 + 23 28 = 5 + 23 30 = 7 + 23 32 = 3 + 29

Some even numbers can be written as sums of two primes in more than oneway. For example, 10 = 3 + 7 = 5 + 5 and 22 = 3 + 19 = 5 + 17 = 11 + 11.Goldbach’s conjecture is one of the big unsolved problems in mathematics.Nobody knows whether it is true or false.About twenty years ago, Apostolos Doxiadis wrote a novel called Uncle

Petros and Goldbach’s conjecture. The main character of this novel wasdetermined to settle Goldbach’s conjecture. The publishers offered a prize ofone million dollars to anyone who proved Goldbach’s conjecture within twoyears. As I recall, Uncle Petros goes off the deep end when he finds out thatit is conceivable that Goldbach’s conjecture is true, yet not provable. That’sfrom a famous result in logic by Kurt Gödel, who was a bit crazy himself.Be that as it may, we can write a program that tries to write even numbers

as sums of two primes. The number 4 is an anomaly, as it is the only evennumber that can be written as the sum of two primes where one of theprimes is 2. In fact, Goldbach’s conjecture is often stated in the form: anyeven number greater than 4 is the sum of two odd primes.So we want to run through some even numbers and try to write each one

as the sum of two odd primes. An even number is a multiple of 2, so we wantto run through numbers of the form 2n for n = 2, 3, 4, 5, 6, . . .. Let’s startout by running n from 2 to 16, so that we will duplicate the results in thetable above. We can do that with the line

for n in range(2,17):

12

If 2n is the sum of two primes, then the smaller prime is at most n, so wewant to run through the primes p with p ≤ n. We also want 2n− p to be aprime. So we run through the numbers p with p ≤ n, and test to see if p and2n− p are both primes. That’s why we write the second line as follows:for n in range(2,17):

for p in range(2,n+1):

To test whether p and 2n − p are both primes, we use an if-statement andour function spf. Here is what a third line might look like:

for n in range(2,17):for p in range(2,n+1):

if spf(p) == p and spf(2*n-p) == 2*n-p:print 2*n,"=",p,"+",2*n-p

Notice the use of our function spf to check whether p and 2n− p are primes.Not also the use of the word “and”to make the if-statement dependent ontwo conditions. Finally, notice that we have to write 2*n, not 2n to indicatethe number 2n.Run this program. If everything is working right, it should print out all

possible ways of writing each even number as the sum of two primes. Tryusing different numbers for 17.Exercise 1. Write a program that, instead of printing out the different

ways each even number can be written as the sum of two primes, printsthe number of ways each even number can be written as the sum of twoprimes. So next to the number 90 it would print the number 9, because 90can be written in 9 ways as the sum of two primes. At least according to mycalculations.Exercise 2. What is the smallest even number that can be written as a

sum of two primes in 11 ways? What is the smallest even number that canbe written as the sum of two primes in exactly 11 ways?It’s a little cryptic to use the function spf to see if a number is prime.

Here is an function that does this directly.def prime(n):

if n < 2: return Falsefor m in range(2,n):

if n % m == 0: return Falsereturn True

13

The purpose of the first line is to avoid returning True for negative numbersand for the numbers 0 and 1. The next two lines test to see if n is divisibleby a number m such that 2 ≤ m < n, and returns False if it is. Note that ifn = 2, then there are no such numbers m. If n does not get eliminated thisway, then the last line returns True. A refinement on this function is to adda line that returns True as soon as m2 > n, because in that case we alreadyknow, without further testing, that n must be prime. So we could writedef prime(n):

if n < 2: return Falsefor m in range(2,n):

if n % m == 0: return Falseif m*m > n: return True

return TrueThis refinement helps if we are testing a very large prime.

2.7 Sophie Germain primes

Sophie Germain, a French mathematician who lived from 1776 to 1831,worked on one of the most famous problems in mathematics: Fermat’s lasttheorem. One of her results concerning this problem involved primes p suchthat 2p+ 1 is also a prime. These primes have come to be known as SophieGermain primes. The first few Sophie Germain primes are 2, 3, 5, 11, and23. You can see that 2 ·2+1 = 5 is a prime, as are 2 ·3+1 = 7, 2 ·5+1 = 11,2 · 11 + 1 = 23, and 2 · 23 + 1 = 47. The primes 7 and 13 are not SophieGermain primes because 2 · 7 + 1 = 15 and 2 · 13 + 1 = 27 are not primes.Fermat’s last theorem says that if p is an odd prime, then there are no

solutions to the equationxp + yp = zp

with x, y, and z positive integers. The so-called “first case”of Fermat’s lasttheorem is to show that there are no solutions with x, y, and z, not divisibleby p. Sophie Germain proved that the first case of Fermat’s last theorem istrue if p is a Sophie Germain prime.Fermat’s last theorem was not the last theorem that Fermat proved, or

the last theorem that Fermat claimed to be true. For a long time it wasthe only theorem of Fermat that remained unproved, among the theoremsthat he had claimed were true. In 1995, Andrew Wiles published a proof ofFermat’s last theorem, 358 years after it was stated.

14

If p is a Sophie Germain prime, then the prime q = 2p + 1 is said to bea safe prime. This term has its origin in cryptography. It refers to the factthat q − 1 does not have many prime factors– in fact it has only two: 2 andp. That makes the prime q useful for certain encryption algorithms. A primeq is safe exactly when the number (q − 1) /2 is prime.The largest known Sophie Germain prime is

18543637900515 · 2666667 − 1

A Cunningham chain (of the first kind) is a sequence of primes such thateach one is twice the preceding one plus 1. So the sequence 2, 5, 11, 23, 47 isa Cunningham chain. This chain cannot be extended because 2 · 47+ 1 = 95is not a prime. Another Cunningham chain is the sequence 89, 179, 359, 719,1439, 2879. The longest known Cunningham chain consists of 17 primes, thefirst of which is 2759832934171386593519.A Cunningham chain is complete if it cannot be extended, in either di-

rection, to form a larger Cunningham chain. So the first term in a completeCunningham chain is not a safe prime, and the last term is not a SophieGermain prime. Note that in the Cunningham chain 89, 179, 359, 719, 1439,2879, the number 89 is not safe because (89− 1) /2 = 44 is not a prime, and2879 is not a Sophie Germain prime because 2 · 2879 + 1 = 5759 = 13× 443is not a prime.Here is a simple function that returns True when applied to numbers that

are prime but not safe (unsafe primes), and False otherwise.def unsafe(n):

if prime(n) and not prime((n-1)/2): return Truereturn False

Exercise 1. Write a program to find the longest Cunningham chainwhose first prime is less than 1000. This chain will necessarily be complete.Exercise 2. One can think of the primes as being partitioned into com-

plete Cunningham chains. The chains of length one are the primes that areneither Sophie Germain primes nor safe primes. The first such chain is 13.What is the first chain of length two?Exercise 3. Write a program that lists all the Sophie Germain primes

p less than 1000 that are not safe primes, together with the length of thecomplete Cunningham chain starting at p.

15

2.8 There are infinitely many primes

In Book VII, Proposition 37, Euclid proves that any number greater than 1is divisible by a prime number. The function spf(n) is an implementation ofthat proposition: you give it a number n > 1, and it returns a prime numberthat divides n. Of course what spf(n) actually does is to return the smallestnumber p > 1 that divides n. This number p is necessarily prime because ifp had a nontrivial factor, that factor would be smaller than p and would alsodivide n.There is a great presentation of Euclid’s elements by David Joyce on the

web, complete with Java applets to illustrate the propositions. The url is

aleph0.clarku.edu/~djoyce/java/elements/elements.html

Click on the number of the book that you want, then click on the propositionthat you are interested in.In Book IX, Proposition 20, Euclid proves that prime numbers are more

than any assigned multitude of prime numbers. By that he meant that ifyou are given any (finite) list of prime numbers, then you can construct aprime number that is not on that list. This is a positive formulation of thestatement that there are infinitely many primes. We can implement thisproposition of Euclid also.Euclid’s proof says to multiply all the primes in the given list together to

get a product P , and then consider the number P + 1. The number P + 1cannot be divisible by any of the primes on the list, because P is divisible byall those primes. But Proposition 37 of Book VII says that P +1 is divisibleby some prime. So that prime cannot be on the list.This procedure can be used to generate a sequence of primes, starting

from nothing. To get a prime, we have to start with a list of primes, but wecan take the initial list to be empty! What is the product P of the primes onan empty list? As we shall see, when we actually write down the program,the product of an empty list of numbers is equal to 1. That might seem alittle surprising, but it turns out to be very natural. So P + 1 is equal to 2,the first prime generated by Euclid’s construction.So our list starts out empty, which in Python is the list [ ]. Then we

get the list [2]. Applying Euclid’s construction to that list gives P = 2 andP+1 = 3. So the next prime we get is 3, and our list of primes becomes [2,3].Continuing in this way, you can see that we get the prime 7 = 2 · 3+ 1, thenthe prime 43 = 2·3·7+1. The next number we consider is 2·3·7·43+1 = 1807.

16

But 1807 = 13 · 139 is not prime. So, since we are taking the smallest primedividing P + 1, the next prime on our list is 13.Here is a program that multiplies all the numbers on a list L together:

P = 1for i in L: P = P*i

After this program has executed, the variable P will be the product of thenumbers in the list L. For example, if L = [2,3,5], then P will start out as 1,then become P · i = 1 · 2 = 2, then P · i = 2 · 3 = 6, then 6 · 5 = 30. Youcan see that if the list L is empty, then P remains equal to 1, its initial value,because there are no numbers i in L.So how do we implement Book IX, Proposition 20? First we decide how

many times we want to repeat the basic construction. Let’s call that numberm, and set it equal to 5 at first. So our first line will be m = 5. Then we setup the list L which is initially empty. So our second line will be L = [ ]. Thenhave some variable run through the numbers from 0 to m − 1. It makes nodifference what we call that variable, the idea is simply to repeat the basicconstruction m times. Then we multiply all the numbers in the list L, asbefore. So our first few lines will be

m = 5L = [ ]for n in range(m):

P = 1for i in L: P = P*i

Now what? The construction says to find a prime that divides P +1. So ournext line should be to compute spf(P+1). Call that prime p and print it outso we can see what’s happening. Then, and this is crucial, we have to tackp onto the end of the list L. Perhaps the easiest way to do that is with thecommand L.append(p). Another way is L = L + [p], or even L += [p]. Wecan use a plus sign to put two lists together. I find that easier to remember,but you have to be sure you are putting two lists together, so we need towrite [p] rather than p. So our program becomes

m = 5L = [ ]for n in range(m):

P = 1for i in L: P = P*i

17

p = spf(P+1)print pL.append(p)

Notice that this program calls on the function spf, so the definition of thatfunction has to be in our file also.When I try to run this program for m = 9, Python, or my computer,

gets angry because it can’t hold a list of the size required in the function spf.Because of that, I modified the program for spf so that it doesn’t use therange operation, which is what creates the big list. I rewrote it this way:

def spf(n):i = 2while i*i < n+1:

if n%i == 0: return ii = i+1

return n

Do you see what that does? I got rid of the for-statement and replaced itby a while-statement. The indented commands below the while-statementkeep repeating as long as the condition i2 < n + 1 holds. So we have tochange i by hand, so to speak, whereas before the for-statement changed itautomatically. If we get to the point where the condition i2 < n+ 1 fails tohold, then we know that n is prime because we have tried to divide n by onall numbers whose squares are at most n.With this new definition, I managed to get the program to run with

m = 14. The fourteenth prime that it generated was 5471. With a little morepatience on my part, it ran with m = 15. The fifteenth prime generated was52662739. What is the eighth prime in this sequence?If your program is taking a long time to factor some large number, there

is help on the web. A good site is www.alpertron.com.ar/ECM.HTM whichwill factor very large numbers in very little time.There are at least two other ways to implement Book IX, Proposition 20.

The first is to multiply the first few primes together, add one, and find aprime factor of the result. So we would start with 2. As 2 + 1 = 3 is prime,the next prime we get is 3. As 2 · 3 + 1 = 7 is prime, the next prime we getis 7. As 2 · 3 · 5 + 1 = 31 is prime, the next prime we get is 31. See how thisalgorithm differs from our first in which we looked at 2·3·7+1 = 43, omittingthe prime 5. The next prime we get in this new sequence is 2·3·5·7+1 = 211,

18

which is also prime. If 211 were not a prime, we would calculate its smallestprime factor.Exercise 1. Write a program that computes this sequence. Do you

always get primes without factoring, or do we sometimes get a compositenumber which we have to factor to get our new prime?Another way to show there are infinitely many primes is to show that

for each number n, prime or not, there is a prime greater than n. In a way,this is the simplest algorithm: we simply find a prime factor of n! + 1. Thatnumber cannot be divisible by a prime i ≤ n, because if i ≤ n, then i dividesn!. The first few numbers we get that way are 1! + 1 = 2, 2! + 1 = 3, and3! + 1 = 7. The next number is 4! + 1 = 25, which is not a prime but all ofits prime factors are bigger than 4. The next number is 5! + 1 = 121 which(I think) is a prime.Exercise 2. Write a program that uses this procedure to find a prime

greater than n for as many numbers n as you can. Print out n, followed bythe prime that is greater than n, for each number n.

2.9 Largest prime factor

Suppose we want to calculate the largest prime factor of a number n. Hereis a plan. First compute the smallest prime factor p of n. We already have aprogram for that. If p = n, then p is the largest prime factor of n. Otherwise,the largest prime factor of n is equal to the largest prime factor of n/p. That’sbecause p is the smallest prime factor of n, and n = p · n/p.How to we turn this plan into a program? The first couple of lines are

clear:

def Lpf(n):p = spf(n)if p == n: return n

Now what? What we want to do now is find the largest prime factor of n/p.That is the function that we are in the middle of defining! In fact, we canuse that function as part of its own definition. This is known as a recursivedefinition. So we simply add one more line:

def Lpf(n):p = spf(n)if p == n: return n

19

return Lpf(n/p)

This works because n/p is always smaller than n. What actually happenswhen we compute Lpf(50)? The first line of the definition calculates thesmallest prime factor p = 2 of 50. As 2 is not equal to 50, we go to thethird line which has us compute Lpf(25). Now we are at the first line of theprogram with n = 25, which calculates the smallest prime factor p = 5 of 25.As 5 is not equal to 25, we go to the third line which computes Lpf(5). Todo that, we find the smallest prime factor p = 5 of 5. But then n = p, so,in accordance with the second line of the definition, we return 5, the largestprime factor of 50.

2.10 Complete factorization

How do we get a program to tell us what all the prime factors of a numberare? We want to enter a number n and have the output be a list of the primesdividing n. Probably we want to allow repetitions on this list, so when weenter the number 72, the list that gets returned is [2, 2, 2, 3, 3] rather thanjust [2, 3]. Note that a list is Python is written as a sequence of elements,separated by commas, and enclosed in square brackets. If we “add”two listsin Python, we get the concatenation of the two lists. Thus

[1] + [2] = [1, 2]

[1, 2, 10] + [2, 13] = [1, 2, 10, 2, 13]

[1] + [] = [1]

The natural way to handle this problem is via a recursive function, onethat calls on itself. Let’s denote the function we want to define by allpf (n).Then what we want to do is first compute

m = spf (n)

and then form a list allpf (n) whose first element is m and whose remainingelements form the list allpf (n/m). The list allpf (n) can be constructed inPython as the sum of two lists:

allpf (n) = [m] + allpf (n/m)

20

This last equation is the recursion: we define allpf in terms of itself. Howdoes it work in practice? If n = 12, then m = spf (12) = 2, and n/m = 6, sowe have

allpf (12) = [2] + allpf (6)

Proceeding, we getallpf (6) = [2] + allpf (3)

soallpf (12) = [2] + [2] + allpf (3)

Finally,allpf (3) = [3] + allpf (1) = [3] + [] = [3]

soallpf (12) = [2] + [2] + [3] = [2] + [2, 3] = [2, 2, 3]

This works because of two things. One is that the number n/m that weapply the function allpf to on the right, is always smaller than the numbern that we apply allpf to on the left. The other is that if n is small enough(equal to 1), then we know directly what allpf (n) is.So here is the general idea. If n = 1, then return the empty list. If n > 1,

then set m = spf (n), and return the list [m] + allpf (n/m). Here is a formaldefinition in Python:

def allpf(n):if n == 1: return []m = spf(n)return [m] + allpf(n/m)

2.11 More on recursive functions

The prototype recursive function is one that computes the factorial function,the product of the integers from 1 to n:

n! = n (n− 1) (n− 2) · · · 3 · 2 · 1

The key fact is that n! is equal to n times (n− 1)!, at least if n is positive, asyou can see by looking at the product. Thus if we could compute (n− 1)! we

21

would know how to compute n!. The computation for 4! would go as follows:

4! = 4 · 3!3! = 3 · 2!2! = 2 · 1!1! = 1 · 0!

but now we can’t go further, we have to know what 0! is. Well, 0! is equalto 1. That’s our exit condition. Then we work our way backwards throughthe equations to find that

1! = 1 · 0! = 1 · 1 = 12! = 2 · 1! = 2 · 1 = 23! = 3 · 2! = 3 · 2 = 64! = 4 · 3! = 4 · 6 = 24

The program would look like:

def fac(n):if n == 0: return 1return n*fac(n-1)

What happens when it runs on n = 4? When we run fac(4), it tries toreturn 4*fac(3), so it has to run fac(3). We now have two programs runningat once: fac(4) and fac(3), with fac(4) waiting for the result from fac(3).Similarly fac(3) tries to return 3*fac(2), so it has to run fac(2). We now havethree programs running at once. And so on. We can indicate this by a table:

program returnsfac(4) 4*fac(3)fac(3) 3*fac(2)fac(2) 2*fac(1)fac(1) 1*fac(0)fac(0) 1

At the end we have five fac programs running at once. But fac(0) knowswhat to do without calling fac any more: it returns 1. Now fac(0) = 1 ispassed to the fac(1) program giving the result fac(1) = 1*1 = 1. Then fac(1)= 1 is passed to the fac(2) program giving the result fac(2) = 2*1 = 2. Thisresult is passed to the fac(3) program, yielding fac(3) = 3*2 = 6, and finallythis result is passed to the fac(4) program yielding fac(4) = 4*6 = 24.

22

2.12 Working with lists

A list is a sequence indexed by the integers 0, 1, 2, . . . , n− 1. The n elementsof the list a are denoted a[0], a[1], a[2], . . . , a[n-1]. The number n is thelength of the list and can be accessed by writing len(a).A string s can be thought of as a special type of list whose elements are

alphanumeric characters. Its length is also denoted len(s), but a string ishandled a little bit differently from a list.The simplest way to create a list is by the statement

a = []

which creates a list with no elements– an empty list. An empty list haslength 0. So, if after defining the list a above, you printed out len(a), youshould see 0.You can put an elementm onto the end of an array a by writing a.append(m).

If a is an empty list, then a.append(17) changes a into the list [17]. If youwant a list containing the squares of the numbers from 0 to 9, you can getone by first setting a = [] and then running the loop

for i in range(0,10): a.append(i*i)

We can stick an element m onto the beginning of the list a by writinga.insert(0,m). If take the list a generated by the loop above, and then writea.insert(0,22), the list a would become [22,0,1,4,9,16,25,36,49,64,81].Actually, I have trouble remembering how to use append and insert. I find

it easier to use addition of lists. So instead of writing a.append(m), I writea = a + [m], and instead of writing a.insert(0,m), I write a = [m] + a. Thegeneral idea is that when you add two lists, the result is a list consisting ofthe two lists put together. The list

[22,0,1,4,9] + [16,25,36,49,64,81]

is the list[22,0,1,4,9,16,25,36,49,64,81]

3 The Euclidean algorithm

The Euclidean algorithm is one of the oldest and best algorithms we have.It computes the greatest common divisor of two positive integers a and b.

23

You can find it in Book VII Proposition 2 of Euclid’s Elements. Euclid alsoshowed that any number that divides both a and b divides their greatestcommon divisor. I think of that fact as being the “algebraic gcd property”.Here is a short program that computes the gcd:

def gcd(a,b):while a!=0: a,b = b%a,areturn abs(b)

The Euclidean algorithm is most naturally written recursively. Euclidpointed out that the common divisors of a and b (those numbers that divideboth a and b) are the same as the common divisors of a and b − a. So if0 < a ≤ b, we can reduce the problem of finding gcd (a, b) to that of findinggcd(a, b−a). The latter is a simpler problem because the numbers are smaller(certainly their sum is smaller). We can refine that observation a bit for ourpurposes by noticing that we can repeatedly subtract a from b until we geta number that is smaller than a. Actually, Euclid noted that also: he talkedabout repeatedly subtracting the smaller number from the larger number. Ifyou repeatedly subtract a from b until b becomes smaller than a, you end upwith the remainder you get when you divide b by a. (Recall that division ofpositive integers can be thought of as repeated subtraction.) So using thePython % notation for the remainder, the key equation is

gcd (a, b) = gcd (b% a, a)

Here the b% a is written first because it is (strictly) smaller than a. Ofcourse b% a might be equal to zero, in which case we are done becausegcd (0, a) = a. This gives us our exit condition from the recursion: if a is 0,then gcd (a, b) = b. The usual convention is that gcd (0, 0) = 0 even though,strictly speaking, there is no greatest common divisor of 0 and 0. However,zero is obviously the algebraic gcd of 0 and 0 because any number that dividesboth 0 and 0 divides zero (and zero is the only number with that property).Rather than making your algorithm foolproof, at least at first, just make

it work when it is handed integers a and b with 0 ≤ a ≤ b. Use the exitcondition

gcd(0, b) = b

and the recursion displayed above. Test your algorithm on a few small pairsa and b where you know what the answer is.

24

There is a built-in Python function that will return gcd (a, b). You canimport it from the module fractions. If you put the line from fractions importgcd at the top, then you can use their function gcd(a,b) in your programs.

3.1 The Euler ϕ-function

Two positive integers a and b are said to be relatively prime, or coprime,if they have no common divisors except for 1. Notice that 1 is relatively primeto any positive integer. It’s easy to see that two numbers a and b are relativelyprime exactly when gcd (a, b) = 1, so the Euclidean algorithm provides a testfor when a and b are relatively prime. The Euler ϕ-function is defined, forn > 1, by setting ϕ (n) equal to the number of positive integers less than nthat are relatively prime to n. Thus ϕ (10) = 4 because the numbers lessthan 10 that are relatively prime to 10 are 1, 3, 7, and 9. Usually peopleset ϕ (0) = 0 and ϕ (1) = 1, but we really don’t care about those values,especially ϕ (0). We can justify ϕ (1) = 1 by modifying the definition ofϕ (n) to read “the number of positive integers less than or equal to n thatare relatively prime to n.”This, in fact, is the usual definition. It also givesϕ (0) = 0.Once you get your gcd function working, you can use it to compute the

ϕ function. For each m just run through the numbers 1, 2, . . . ,m, checkingeach one to see if it is relatively prime to m, and counting how many timesthat happens. After writing such a function, test it by printing out, in twocolumns, the values m and ϕ (m) for m = 2, . . . , n.The first few values of the Euler ϕ-function are

n 0 1 2 3 4 5 6 7 8 9 10ϕ (n) 0 1 1 2 2 4 2 6 4 6 4

Verify this table.As a final check on your ϕ function, you can compute it in a different

way. The formula is

ϕ (n) = n∏p∈P

(1− 1

p

)where P is the set of primes that divide n. So

ϕ (10) = 10

(1− 1

2

)(1− 1

5

)

25

and

ϕ (12) = 12

(1− 1

2

)(1− 1

3

)If you write it that way, you will be dealing with real numbers, at least asintermediate values. In order to deal only with integers, you can rewrite theformula as

n∏p∈P

(1− 1

p

)= n

∏p∈P

(p− 1p

)=

n∏p∈P p

∏p∈P

(p− 1)

So for n = 10, the set P is {2, 5} and the product∏p∈P p is 10. The product∏

p∈P (p− 1) is 1 · 4 = 4 so

ϕ (10) =10

104 = 4

For n = 12, the set P is {2, 3} and the product∏p∈P p is 6. The product∏

p∈P (p− 1) is 1 · 2 = 2 so

ϕ (12) =12

62 = 4

You can use allpf(n) to find the set P . What you need to do is to eliminate theduplicates from the list that allpf(n) returns. It’s probably better to modifythe function allpf(n) so that it doesn’t return any duplicates. When you findthe smallest prime dividing n, keep dividing n by that prime until you can’tanymore, then go on to find the smallest prime dividing what’s left. Youshould probably give the modified function a different name.Let’s do it. We’ll call the function allpd(n) for “all prime divisors”.

def allpd(n):if n == 1: return [] #the number 1 has no prime divisorsi = 2 #the number 2 is the smallest primewhile i*i <= n: #looking for the smallest prime divisor of n

if n%i == 0: #found it!while n%i == 0: n = n/i #keep dividing n by ireturn [i] + allpd(n) #put i in front of the list

i = i+1 #increase i and keep tryingreturn [n] #n must be prime, so the list is [n]

Once you get a list A whose entries are the elements of the set P withno duplicates, you can easily compute the two required products

∏p∈P p and

26

∏p∈P (p− 1). Now you can get a third column to your output consisting of

the values of ϕ (n) computed by this formula, and you can see if it agreeswith the values of ϕ (n) that you got by counting.Euler’s Theorem. Fermat’s theorem says that if n is a prime, and n does

not divide a, then an−1 ≡ 1 (modn). When n is a prime, then ϕ (n) = n−1,and n does not divide a exactly when a and n are relatively prime. So wecan rewrite Fermat’s theorem as “if n is a prime, and a and n are relativelyprime, then aϕ(n) ≡ 1 (modn). Euler showed that this is true even when n isnot prime. So, for example, 26 ≡ 1 (mod 9), as you can easily check. Indeed,you should write a program that checks Euler’s theorem for the numbers nfrom 2 to 100.

3.2 The extended Euclidean algorithm

The extended Euclidean algorithm is a refinement of the Euclidean algorithmthat finds integers s and t so that sa+ tb divides both a and b. If sa+ tb ispositive, which we can always arrange, it follows that sa+ tb is the greatestcommon divisor of a and b, which is why this is a refinement of the Euclideanalgorithm The equation

sa+ tb = gcd (a, b)

is known as Bezout’s equation. Usually either s or t is negative.An interesting aspect of Bezout’s equation is that if the left-hand side,

sa + tb, divides both a and b, then sa + tb must be the greatest commondivisor of a and b. Indeed, if d is any common divisor of a and b, then d mustdivide sa + tb (by the distributive law) so, if everything is positive, d mustbe smaller (or equal to) sa+ tb.We will assume that 0 ≤ a ≤ b. If that’s not the case, we can always

replace a and b by their absolute values, and interchange them if necessary.The simplest, if not the most understandable, algorithm is a recursive one.The “exit strategy” is that if a = 0, then we will choose s = 0 and t = 1because gcd (0, b) = b = 0 · 0 + 1 · b. (Is gcd (0, 0) = 0?)The idea behind the Euclidean algorithm is that if b = qa + r, where

0 ≤ r < a, then gcd(a, b) = gcd(r, a). Thus we can reduce the computationof gcd (a, b) to the computation of gcd (r, a), and repeat. In Python, or inC, the number r is equal to b%a. Because r + a < a + b, these reductionseventually end with gcd (0, b) = b.

27

The same thing happens with the extended Euclidean algorithm. Supposeagain that b = qa+ r with 0 ≤ r < a. If

s′r + t′a = gcd (r, a)

then, substituting r = b− qa into this equation gives

s′ (b− qa) + t′a = gcd (r, a)

so(t′ − s′q) a+ s′b = gcd (r, a) = gcd (a, b)

Thus taking s = t′ − s′q and t = s′ solves the Bezout equation. That givesus the following (informal, not Python) algorithm that accepts two integers0 ≤ a ≤ b and returns a pair of integers s and t such that sa+ tb = gcd (a, b):bez (a, b)If a = 0 return (0, 1)Set r = bmod aSet q = (b− r) /aSet (s, t) = bez (r, a)return (t− sq, s)

Of course you have to write that in Python. A pair of integers can beimplemented by a list of length 2 so that you can return the pair at one go.Thus the function bez takes two integers, a and b, and returns an integer listof length 2. To return the pair (0, 1), you simply return the list [0,1]. For thefinal return, you return [t - s*q, s]. What are s and t? If you set a variable yequal to bez (r, a), then s is y[0] and t is y[1].Watch out for the “If a = 0”because “a = 0”in Python, as in C, sets

the variable a equal to zero, it does not test for whether a is equal to zero.That’s done with “a == 0”. Everybody makes that mistake, more thanonce. Fortunately, this gives a syntax error in Python so you know when youmake this mistake.How do you test your function bez once you write it? Run through a

bunch of numbers a and b, and print them out together with the correspond-ing s and t, and also sa+ tb. Maybe run a from 5 to n and b from a to n formodest values of n. See if the answers look correct.You can automate the checking also. Compute sa + tb and check to see

if it divides both a and b.

28

3.3 Orders of units modulo n

If gcd (a, b) = 1, we say that a and b are relatively prime. Now fix a numbern, say n = 15. The numbers that are less than n and relatively prime ton are 1, 2, 4, 7, 8, 11, 13, and 14. Those are called the units modulo 15.If we multiply two of them, and reduce modulo n, we get another. Themultiplication table for n = 15 is

× 1 2 4 7 8 11 13 141 1 2 4 7 8 11 13 142 2 4 8 14 1 7 11 134 4 8 1 13 2 14 7 117 7 14 13 4 11 2 1 88 8 1 2 11 4 13 14 711 11 7 14 2 13 1 8 413 13 11 7 1 14 8 4 214 14 13 11 8 7 4 2 1

If the number a is relatively prime to n, then the order of a modulo n is theleast exponent m ≥ 1 such that am ≡ 1 (modn). So the order of 2 modulo15 is 4 as you can see by the sequence of powers of 2

2, 4, 8, 1

The order of 2 modulo 19 is 18 as you can see by the sequence of powers of 2

2, 4, 8, 16, 13, 7, 14, 9, 18, 17, 15, 11, 3, 6, 12, 5, 10, 1

What is the order of 2 modulo 11?Here is a Python program order(a,n) that is supposed to compute the

order of a modulo n. We need a to be relatively prime to n, so we check forthat right away. You don’t have to do that if you make sure that you neverinvoke order(a,n) except when a is relatively prime to n, but it is safer toguard against that.

def order(a,n):if gcd(a,n) != 1: return 0 #the order of a unit is never 0b = a%n #b will be the various powers of ae = 1 #a to the e is equal to bwhile b != 1: #we quit when b = 1

29

b = (a*b)%n #multiply b by a (modulo n)e += 1 #increase the exponent by 1

return e #when b = 1 for the first time, e is the order of a

Exercise 1. Find the smallest two numbers that have over 30 units oforder 2.Exercise 2. Find the smallest two numbers that have over 20 units of

order 3.Exercise 3. Find out how many units of order 2 there are modulo n if n

is the product of the first k odd primes, for k = 1, 2, 3, 4, 5, 6. Those numbersare 3, 3 · 5, 3 · 5 · 7, 3 · 5 · 7 · 11, . . ..Exercise 4. For what numbers n is the order of 2 equal to ϕ (n)? For

what numbers n is there a number a with order ϕ (n)?

4 Sieving for primes

One way to construct a list of the primes from 1 to 1000 is to test eachnumber from 1 to 1000 to see if it is a prime. A more effi cient way is to usethe “Sieve of Eratosthenes”. This is the same Eratosthenes who, around 240BC, calculated the circumference of the Earth.The idea is to list the numbers from 2 to 1000

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 . . .

then eliminate all multiples of 2 (except 2 itself) which is the first number

2 3 5 7 9 11 13 15 17 19 21 23 25 . . .

then eliminate all multiples of 3 which is the next number remaining

2 3 5 7 11 13 17 19 23 25 . . .

then eliminate all multiples of 5 which is the next number remaining

2 3 5 7 11 13 17 19 23 . . .

If we continue in this way until we eliminate all multiples of 31, then we areleft with exactly the primes from 1 to 1000.One way to implement this sieve in a program is to create a list with

999 entries, indexed by the numbers from 2 to 1000. Fill this array with the

30

boolean value True, indicating that, as far as we now know, it is true thateach of these numbers is prime. Now we change the entries whose indexesare (proper) multiples of 2 to the boolean value False, because we know that4, 6, 8, 10, 12, . . . are not primes. Next we change the entries whose indexesare multiples of 3 to False, because we know that 6, 9, 12, 15, . . . are notprimes. Notice that 6 and 12 get eliminated twice, but that is harmless. Andso on.You can define an empty list A with the line

A = [ ]

in your program. Then, to get a list of length 1001 (indexed by the numbersfrom 0 to 1000), each entry being True, you could have a line like

for i in range(1001): A.append(True)

Alternatively, you get the desired list at one go with the line

A = [True]*1001

Now set A [0] and A [1] equal to False, because 0 and 1 are not primes.That’s the initial set up. The core of the program eliminates all the compositenumbers (they fall through the sieve), by setting some entries equal to False.You will have some prime p, which initially is 2, and you will set A[ip] equalto False for i = 2, 3, 4, . . .. that is, you will set A[ip] equal to False fori = 2, 3, 4, . . .. That line might look like

for i in range(p*p,1001,p): A[i] = False

The third argument to range tells it to only include every p-th number:p2, (p+ 1) p, (p+ 2) p, . . ., where number is less than 1001. Notice that wecan start with p2 because we have already set A [ip] equal to False for i < p.What do we want p to range over? It suffi ces to look at primes that are

smaller than√1001, because if a number less than 1001 is divisible by a

prime, then it is divisible by a prime less than√1001. Now

√1001 is a little

over 31, so we can run p from 2 to 31. So we start with the line

for p in range(2,32):

We don’t have to work with p unless it is prime, so our next statement checksA[p]. The full code for sieving A is

31

A = [True]*1001A[0] = FalseA[1] = Falsefor p in range(2,32):

if A[p]:for i in range(p*p,1001,p): A[i] = False

Computing the number 32 by hand is a little hokey. The Python expressionfor√1001 is 1001**0.5, but we need an integer to replace 32, not a real

number. The simplest thing to use is int(1001**0.5) + 1, which, in fact, is32. The Python function int rounds a positive real number down, so we add1 to make sure the end of the range is large enough.A more flexible arrangement would be to replace both occurrences of 1001

by n+1, and set n = 1000 at the top. Then we can sieve up to whatever wewant, simply by setting n equal to whatever we want at the top. Like 20000,or 1000000.

4.1 Counts

Once we have the boolean list A set up, we can do various counts. Thesimplest is just to count the number of primes between 1 and n. This isaccomplished by counting how many of the entries of A are equal to True.The following function does that:

def nprimes():count = 0for b in A:

if b: count+=1return count

You may not even want a function here. Just use the middle three lines andthen print count.Twin primes are two primes that differ by 2, like 17 and 19, or 71 and

73. While we have known since Euclid that there are an infinite number ofprimes, no one has succeeded in proving that there are an infinite number oftwin primes. We can count the number of (pairs of) twin primes in the sameway we counted the number of primes:

def ntwins(n):count = 0

32

for m in range(2,len(A)):if A[m] and A[m-2]: count+=1

return count

The conditional statement count+=1 is executed exactly when both A[m]and A[m-2] are True, that is, when m− 2,m is a pair of twin primes.The gap between consecutive primes p and q is q − p − 1. The gap

between 2 and 3 is zero (there are no nonprimes between 2 and 3) while thegap between 7 and 11 is three (there are three nonprimes, 8, 9, 10, between7 and 11). The gap between twin primes is 1.Our next task is to count the number of gaps of different sizes between

consecutive primes from 1 to n. Our result should be an array G such thatG [i] is the number of gaps of size i. It will be convenient to focus on thelarger of the two consecutive primes. So our main loop will run i from 3 ton. But we have to compare i with the value of the previous prime, so we willneed a variable to take care of that: say lastprime. Since we are starting ati = 3, we initially set the value of lastprime equal to 2. So our function willcontain the lines:

def gaps(n):lastprime = 2for i in range(3,n-1):

return G

Of course we have to set up G as a list at the beginning, and we will only dosomething in the loop when i is prime. Also, when we find the next prime i,and we do something in the loop, we have to set lastprime equal to i beforewe go looking for the next prime after i. So our function will contain thelines:

def gaps(n):G = []lastprime = 2for i in range(3,n-1):

if(A[i]):

lastprime = i

return G

33

Now what do we want to do with the numbers lastprime and the next primeafter it, which will be i? The gap g between those two consecutive primesis i - lastprime - 1. We want to increase G[g] by 1. A problem here is thatG[g] may not be defined because this may be the first gap of size g or morethat we have encountered. So we test to see if G[g] is defined. If it isn’t, weappend zeros to G until it is. So our function becomes:

def gaps(n):G = []lastprime = 2for i in range(3,n+1):

if A[i]:g = i - lastprime - 1while g >= len(G): G.append(0)G[g]+=1lastprime = i

return G

A prime triple (or triplet) is a sequence of three primes p0 < p1 < p2such that p2 = p0 + 6. Here are the first six examples:

(5, 7, 11), (7, 11, 13), (11, 13, 17), (13, 17, 19), (17, 19, 23), (37, 41, 43)

You can see a list of the first elements of the prime triples of the form(p, p+ 2, p+ 6), like (5, 7, 11), from 5 to 5477 at oeis.org/A022004, and oneof the first elements of the prime triples of the form (p, p+ 4, p+ 6), like(7, 11, 13), from 7 to 5437, at oeis.org/A022005.Exercise 1. Write a program that counts the number of prime triples

of the form (p, p+ 2, p+ 6) in the first two thousand numbers. Compare yourresults with those of Thomas R. Nicely on his site at http://www.trnicely.net/triplets/t3a_0000.htm.

5 Mersenne primes

AMersenne prime is a prime of the form 2n−1. So 3 = 22−1 is a Mersenneprime, as are 7 = 23 − 1 and 31 = 25 − 1. Of course 15 = 24 − 1 is not aprime at all, let alone a Mersenne prime. In fact it is not diffi cult to showthat if 2n − 1 is a prime, then so is n. Essentially the argument is

2ab − 1 = (2a − 1)(2a(b−1) + 2a(b−2) + · · ·+ 2a + 1

)34

if you can call that an argument. It shows that 2a − 1 is a nontrivial factorof 2ab − 1 if a is a nontrivial factor of ab.So the question is, for what primes p is 2p−1 a prime. We denote 2p−1 by

Mp, in honor of Mersenne. We have seen that M2, M3, and M5 are primes.What about M7 = 27 − 1 = 127. Yes, it’s also prime. Marin Mersennesaid, in 1644, that for the primes p ≤ 157, the ones for which Mp is primeare 2, 3, 5, 7, 13, 17, 19, 31, 67, 127, 157. In 1750, Euler showed thatM31 was aprime. In 1883, Pervouchine showed that M61 is prime, so Mersenne missedone.Mersenne primes are interesting because, among other things, they are

tied up with perfect numbers. Euclid talked about perfect numbers, andshowed that an even number is perfect exactly when it is of the form (2n − 1) 2n−1,and 2n − 1 is prime. So we get a perfect number for n = 2, 3, 5, 7, 13, . . ..These numbers are 6, 28, 496, 8128, 33 550 336, . . . . The first four of thesenumbers have been known since antiquity. St. Augustine made a big dealout of the fact that 6 was a perfect number, saying that God created theworld in six days because of this.No one knows whether or not there are any odd perfect numbers.Write a program that figures out for which primes p < 60 the numberMp

is a prime. WhenMp is not prime, this program should print out its smallestprime factor. However, that there is technical problem with the function spfwhen applied to very large numbers. Here is the function spf as we definedit before:

def spf(n):for m in range(2,n+1):

if n % m == 0: return mif m*m > n: return n

The problem is that the list, range(2,n+1), is just too big. What we need todo is to define the function spf without forming that list. For this purposewe use a while-loop instead of a for-loop. The first three lines would be

def spf(n):m = 2while m*m <= n:

First we set m equal to 2, then we run a block of code for as long as m2 doesnot exceed n. Of course that might be forever, so we have to be careful whenwriting the block that m2 eventually exceeds n. To do that, we will increase

35

m by 1 at the end of the block, so that the whole thing acts like a for-loop.We are looking for the smallest nontrivial factor m of n, so we test to see ifm divides n, as before. Here is the whole definition:

def spf(n):m = 2while m*m <= n:

if n % m == 0: return mm = m+1

return n

Notice there are two things we have to do with a while-loop that were takencare of automatically by the for-loop. We have to define the starting valueof m outside the loop, and we have to increase m inside the loop.

5.1 The Lucas-Lehmer test

There’s a really good test that tells you whether or not Mp is prime for agiven prime p. It is mainly because of this test that the largest known primeat any given time has always been a Mersenne prime. Lucas himself usedit to show that M127 was prime in 1876. This number is 170 141 183 460469 231 731 687 303 715 884 105 727.Here’s how Lucas’s test, as modified by Lehmer, goes. To see if Mp is

prime, we form a sequence of numbers s0, s1, s2, . . . , sp−1. Set s0 = 4, andthen, for each k > 0, set sk = s2k−1 − 2 until you get up to sp−2. It turns outthat Mp is prime exactly when it divides sp−2. In order to keep the numbersreasonably small, do all the computations sk = s2k−1 − 2 modulo Mp, ratherthan waiting until the end to divide some monstrous number byMp. SoMp isprime, exactly when we end up with sp−2 = 0. Using the Lucas-Lehmer test,you should be able to figure out for which primes p < 1000 the number Mp

is a prime. Do it. That will also tell you what all the even perfect numbersare that are less than . . . what?

5.2 Repunits

A repunit is a number whose digits are all 1’s. That is, they are the numbers1, 11, 111, 1111, 11111, etc. Sometimes these numbers are written as Rn, so

36

R7 = 1111111. It is easy to see that

Rn =10n − 19

because 10n − 1 is an n-digit number consisting of only 9’s. These numberswere named by Albert H. Beiler in his 1964 book, Recreations in the theoryof numbers.What repunits are primes? The first two are R2 = 11 and R19 =

1111111111111111111. The next three repunit primes are R23, R317 andR1031. These are the only repunits that have been proven to be primes, al-though the repunits R49081 and R86453 are almost certainly primes, as areR109297 and R270343. Just as for Mersenne primes, the number Rp can beprime only if p is prime. In fact, the Mersenne primes are just the repunitprimes in base 2, rather than in base 10.Exercise 1. Write a program that finds the prime factorization of all

repunits with fewer than 19 digits. Observe that if m divides n, then Rmdivides Rn.

5.3 Emirps and palindromic primes

An emirp is a prime which forms a different prime when its digits are re-versed. The first four emirps are 13, 17, 31, and 37. A prime which readsthe same backwards and forwards, like 11 and 353, or, for that matter, 2, 3,5, and 7, is called a palindromic prime, not an emirp.Exercise 1. Write a program to find all the emirps and palindromic

primes that are less than 2000.

6 Fermat’s theorem

Fermat’s theorem says that if n is a prime, and a is an integer not divisibleby n, then

an−1 ≡ 1 (modn)This is sometimes referred to as “Fermat’s little theorem” as opposed to“Fermat’s great theorem”better known as “Fermat’s last theorem”becauseit was the last of Fermat’s theorems to be proved (not by Fermat, as far as weknow). Fermat’s last theorem says that if n > 2, then there are no nonzerointeger solutions x, y, z to the equation xn + yn = zn. Fermat’s last theorem

37

is very diffi cult to prove, and remained unproved for over three hundred yearsafter Fermat stated it. Fermat’s little theorem is fairly easy to prove and youcan use Google to find lots of proofs of it on the web.Our first project with Fermat’s theorem will be to check it on lots of

examples. So we want to take some primes n, and some numbers a with1 ≤ a < n, and see if an−1 ≡ 1 (modn). Of course this equation holds fora = 1, so we need only look at numbers a such that 1 < a < n.Just checking the equation on primes n is a little boring. It is also a little

dangerous because the output of the program will just be, “yes, it checks”,so we won’t have any evidence as to whether the program is working right ornot. More interesting would to check the equation not only on primes n butalso on composites. In fact, we will be more interested in what happens withcomposites than with primes because we are going to use Fermat’s theoremto test whether or not n is a prime. The test will be: choose a number afrom {2, 3, . . . , n− 1} and compute an−1 modulo n. If the result is 1, thenn might be a prime, or it might not. But if the result is not 1, then n isdefinitely not a prime.So our first project will be to run through the integers n from 2 to 100,

and for each n run through the integers a from 2 to n − 1 to see whetheror not an−1 ≡ 1 (modn). What do we want the output to be? For each n,we will count the number of integers a from 2 to n− 1 such that an−1 is notequal to 1 modulo n. So if n is prime, this count should be zero accordingto Fermat’s theorem. We want to print out the number n together with thecount. A check on the program will be to see if the numbers n where we geta count of zero are exactly the primes. The first few lines of output shouldbe:

2. 03. 04. 25. 06. 47. 08. 69. 6

We can get a probabilistic test for the primality of a number n by choosing,at random, a number a from 1 to n− 1 and seeing if an−1 ≡ 1 (modn). Tochoose a random number from 1 to n− 1 in Python, put the line

38

from random import randint

at the top of the file. Then we can use the Python function randint(c,d) whichreturns a random integer a such that c ≤ a ≤ d. To set a equal to a randominteger between 1 and n− 1 we writea = randint(1,n-1)

Try running this test 100 times on the number 15906120889 and countingthe number of times you get 1. Then try factoring this number with spf.

6.1 Carmichael numbers

A Carmichael number is a number n so that an−1 ≡ 1 (mod n) whenevergcd(a, n) = 1. So a Carmichael number will pass the Fermat test unlessyou happen to choose a number a that has a common factor with n. Ifthat were easy to do, then you could just choose such a number a, computegcd (a, n), which is a quick computation, and you would have a factor ofn. Carmichael numbers are sometimes called pseudoprimes. The first fewCarmichael numbers are 561, 1105, 1729, 2465, 2821, 6601, 8911, 10585,15841, 29341. Two bigger ones are 294409 = 37 · 73 · 109 and 56052361 =211 · 421 · 631. Also interesting are 6733693 = 109 · 163 · 379 and 17236801 =151 ·211 ·541. The probability that a number less than 56052361 is relativelyprime to 56052361 is 210 · 420 · 630/56052361 = 0.99132. So this is theprobability that 56052361 passes the Fermat test. The probability that itwill pass ten Fermat tests is 0.9913210 = 0.91651, pretty good odds.For all Carmichael numbers less than 1012, see http://www.kobepharma-

u.ac.jp/~math/notes/note02.htmlSee also http://math.fau.edu/richman/carm.htmSome other big Carmichael numbers are 492559141 = 367 · 733 · 1831,

413138881 = 617 ·661 ·1013, 16157879263 = 1667 ·2143 ·4523, 25749237001 =1901× 2851× 4751, 58094662081 = 2633× 4513× 4889.What do all these numbers have in common? They are all products of

three primes, n = pqr, and n− 1 is divisible by p− 1, q − 1, and r − 1. Forexample, 29341 = 13 · 37 · 61 and 29340 = 22325 · 163 which is divisible by12, 36, and 60. This reflects Korselt’s criterion which says that a numbern > 1 is a Carmichael number exactly when n is square free (is not divisibleby the square of a prime) and if p is any prime divisor of n, then p−1 dividesn− 1.

39

6.2 The Miller-Rabin test

The most commonly used probabilistic primality test is the Miller-Rabintest. This test, which is a variant of Fermat’s test, cannot be fooled byCarmichael numbers. If the numbers a that we use to test are chosen atrandom, then the probability that a composite n will pass the test is lessthan 1/2. So if we test 20 times in succession, choosing the numbers aindependently, then the probability of a composite passing these 20 tests isless than 1/220, that is, less than 1 in a million.There is one new idea in the test: If the square of a number is 1 modulo

n, and n is a prime, then the number has to be either 1 or −1 modulo n.That’s because z2− 1 = (z − 1) (z + 1), so if z2− 1 is divisible by a prime n,then n has to divide either z − 1 or z + 1.How do we run across a number whose square is equal to 1 modulo n?

When the number n passes Fermat’s test. In that case, an−1 is equal to 1modulo n, and an−1 is the square of a(n−1)/2. We know that n − 1 is even,because n were even, we would know that it wasn’t a prime. So we can checkto see if a(n−1)/2 is equal to 1 or −1 modulo n. That already is a better testthan just Fermat’s test.Here is the Miller-Rabin test. You are given a number n that wish to test

for primality. Write n − 1 = 2sd where d is odd. This is always possible:you just keep dividing n− 1 by 2 until you get an odd number. For the test,you choose a number a at random so that 0 < a < n. Then you computex = ad (mod n). The test is to consider, modulo n, the sequence

x, x2, x4, x8, . . . , x2s

There are s + 1 terms in this sequence (because the exponents of x are20, 21, 22, 23, . . . , 2s), and the last is x2

s= ad2

s= an−1. Of course the last

term should be 1– that’s Fermat’s test.Now each term in our sequence is the square of the previous term. So if

a term is 1, and the last term must be 1 or we would know that n was not aprime by Fermat’s test, then the previous term must be ±1. If that doesn’thappen, we know that n is not a prime. So the good sequences look like

1, 1, 1, 1, 1, 1, 1, 1

−1, 1, 1, 1, 1, 1, 1∗, ∗, ∗,−1, 1, 1, 1

40

where ∗ is a number different from ±1. The bad sequences look like

∗, ∗, ∗, 1, 1, 1, 1∗, ∗, ∗, ∗, ∗, ∗,−1∗, ∗, ∗, ∗, ∗, ∗, ∗

The bad sequences either don’t end in 1, so the Fermat test fails, or theycontain a 1 immediately following a ∗.If we denote the sequence by t0, t1, t2, . . . , ts, then for the sequence to be

good we must have ts = 1 and there must not be an index i such that ti 6= ±1and ti+1 = 1. You don’t need a list to perform this test, but you may findit convenient. Just compute x, keep squaring it, looking for the forbiddenz 6= ±1 and z2 = 1, and make sure that x2

s= 1. While developing this

program you might want to print out the sequence t0, t1, t2, . . . , ts.Try this test out on the largest Carmichael numbers above.If you find that a number passes the Fermat test, but fails the Miller-

Rabin test, then you will have computed a number z so that z 6= ±1 (modn)but z2 = 1 (modn). So n divides (z − 1) (z + 1), but n does not divideeither z − 1 or z + 1. In that case, gcd (z − 1, n) has to be a proper fac-tor of n, showing directly that n is not prime. This gives a quick way offactoring because the Euclidean algorithm is very fast. For example, forthe number 56052361, and the random number 40202214, the sequence is55252883, 1, 1, 1, so gcd (55252882, 56052361) = 88831 is a factor of 56052361.

7 The sum of the squares of the digits of anumber

Consider the function f that takes a number to the sum of the squares of itsdigits. So

f (340779) = 32 + 42 + 02 + 72 + 72 + 92 = 9 + 16 + 0 + 49 + 49 + 81 = 204

After we figure out how to compute this function, we will want to iterate itand see what happens. That is, after computing f (340779) = 204, we willcompute f (204) = 20, then f (20) = 4, then f (4) = 16 and so on. Thesequence we get starting with 340779 is

340779, 204, 20, 4, 16, 37, 58, 89, 145, 42, 20

41

and now, of course, the sequence starts repeating. We have found a periodicpoint, 20, of the function f . That is,

f 8 (20) = 20

where f 8 indicates the function f applied 8 times, that is

f 8 (m) = f (f (f (f (f (f (f (f (m))))))))

We call f 8 the 8-th iterate of f , and we say that 20 has period 8. We wantto investigate the sequence m, f (m), f 2 (m), f 3 (m), . . . for various valuesof m. We just did it for m = 340779. Notice that not only is 20 a periodicpoint of f , but so are 4, 16, 37, 58, 89, 145, and 42. They each have period 8.We say that the set {20, 4, 16, 37, 59, 89, 145, 42} is an orbit of the functionf . The set {1} is another orbit. It turns out that these are the only orbitsof the function f .

7.1 Happy numbers

A happy number is a number m so that fk (m) = 1 for some k. Notethat f (1) = 1, so the sequence of iterates is 1 from k on. The number 1is called a fixed point of f ; it is a periodic point of period 1 Of course 1is a happy number. The next happy number is 7, which gives the sequence7, 49, 97, 130, 10, 1. The number 2 is not a happy number because f (2) = 4which is a periodic point of period 8, so the number 1 will not appear in thesequence.If we want to use a program to study these sequences, we will have to

write a function that computes f (m). How do we get hold of the digits of mso that we can square them and add up the results? Consider m = 340779.The easiest digit of m to get hold of is the last one, 9, because 9 = m%10.To get at the next-to-the-last digit, we arrange for it to be the last digit ofanother number. To do this, we subtract 9, the last digit, from m to get340770. Now, dividing by 10, we get 34077, and the next digit we want is thelast digit of this number. We continue this computation as in the following

42

table

m m%10 m−m%10 m−m%1010

340779 9 340770 3407734077 7 34070 34073407 7 3400 340340 0 340 3434 4 30 33 3 0 0

Notice that we generate the digits in reverse order, the last one first. Thismakes no difference for the computation of f because we are just going tosquare the digits and add up the results, and it doesn’t matter in which orderwe add.There is a recursion for f , which you can pretty much see from our com-

putations, namely

f (m) = (m%10)2 + f

(m−m%10

10

)This tells us what to do with any nonzero m, reducing the computation off (m) to computing f of a number smaller than m. What about f (0)? Youshould now be able to write a recursive Python function that computes f .

There is a Python trick that computes the sum of the squares ofthe digits of a number written in base 10. It is sum(int(i)**2 fori in str(n)). The number n is converted to a string of charactersstr(n). So 123 would be converted to the string "123". Then int(i)converts each character in i in str(n) into an integer, so we get theintegers 1 2 3. Each one of those is squared by **2, resulting in1 4 9, and then sum adds them up. This only works in base 10.Try it.

But, of course, what we want to see are not the sequences f (m), wherem goes from 1 to n, but the sequences fk (m) where m is fixed and k goesfrom 1 to n.Exercise 1. Write a recursive Python function that computes f and test

it out on the numbers from 0 to 100. Is it correct?Exercise 2. Write a function g (m,n) that prints out the valuesm, f (m) , f 2 (m) , . . . , fn (m)

on a single line.

43

7.2 Numbers whose digits increase

The function f that sums the squares of the digits of a number n, doesn’t carein what order the digits of n appear. For example, f (512) = f (215) = 30.So we can always write f (n) as f (m) where m is a number whose digitsappear in increasing order. To construct m, we simply rearrange the digitsof n. So we can write f (9717) as f (1779). Notice that we don’t demand thatthe digits appear in strictly increasing order– we allow consecutive digits tobe equal. Notice also that if the digits of a number appear in increasingorder, then the digit 0 does not appear.How many numbers less than a million have their digits in increasing

order? For 100, we can count them by hand:

0 1 2 3 4 5 6 7 8 911 12 13 14 15 16 17 18 1922 23 24 25 26 27 28 2933 34 35 36 37 38 3944 45 46 47 48 4955 56 57 58 5966 67 68 6977 78 7988 8999

We can see that the numbers fill up a little more than half of a ten-by-tensquare, which contains 100 little squares. It’s a little more, because if wecut the square exactly in half, from the upper right to the lower left, theten little squares on the diagonal would be cut in half, so 100/2 = 50 wouldundercount by 10/2 = 5. So, of the numbers with at most two digits, thereare 55 of them whose digits appear in increasing order.What about the numbers with at most six digits, that is, the numbers

less than a million? In fact, we can develop a simple formula for how manyof those have their digits appearing in increasing order, namely(

9 + 6

6

)=15 · 14 · 13 · 12 · 11 · 106 · 5 · 4 · 3 · 2 · 1 = 7 · 13 · 11 · 5 = 5005

The symbol on the left is a binomial coeffi cient. It counts the number ofways of choosing 6 things from 15 things. What does this have to do with

44

the number of numbers less than a million whose digits appear in increasingorder?What we are really counting is the number of strings of digits of length

6 where the digits appear in increasing order. We can identify a four-digitnumber with a string starting with two zeros, so the number 1779 correspondsto the string of digits 001779. Now we come to a truly delightful move. Weare going to represent the string 001779 by 9 cuts in a line of 16 dots. Hereit is

· · ·| · ·| · | · | · | · | · | · · · | · | · ·We cut only once between any pair of consecutive dots, so the 9 cuts dividethe 16 dots into 10 groups containing at least one dot each. Those 10 groupsrepresent the 10 digits, in order. The number of dots in the groups are3, 2, 1, 1, 1, 1, 3, 1, 2. If we substract 1 from each of these numbers, we get2, 1, 0, 0, 0, 0, 0, 2, 0, 1 which we interpret as 2 zeros, 1 one, 0 twos, threes,fours, fives, sixes, and nines, 2 sevens, and 1 nine. But that is exactly thestructure of the string 001779.How do you cut the line of 16 dots to represent the string 133356?So constructing an increasing string of six digits corresponds to making 9

cuts in a line of 16 dots, that is, choosing 9 of the 15 possible places to cut.But choosing 9 things out of 15 things is the same as choosing 6 things outof 15 things: you can choose either which things to keep, or which things toleave out. In general, if we have b digits, then there are(

b− 1 + dd

)increasing strings of digits of length d.Here is a short table of how many numbers (including 0) have their digits

45

appearing in increasing order:

One digit :(10

1

)= 10

Two or fewer digits :(11

2

)= 55

Three or fewer digits :(12

3

)= 220

Four or fewer digits :(13

4

)= 715

Five or fewer digits :(14

5

)= 2002

Six or fewer digits :(15

6

)= 5005

Seven or fewer digits :(16

7

)= 11440

Exercise 1. Define a Python function inc(n) that returns True if the(decimal) digits in n appear in increasing order, and False otherwise.Exercise 2. For k = 1, . . . , 8, use your function from Exercise 1 to count

how many numbers less than 10k have their digits appearing in increasingorder.

7.3 Unhappy numbers

It turns out that a number n is unhappy exactly when fk (n) = 4 for somek. Certainly if fk (n) = 4, then n cannot be happy because, as we have seen,4 is a periodic point. Starting at 4, the sequence of iterates is 4, 16, 37, 58,89, 145, 42, 20, 4, 16, and so on– you can never get to 1. Why does everynumber end up at 1 or trapped in the set {4, 16, 37, 58, 89, 145, 42, 20}?How big can f (n) be if n is a four-digit number? The sum of the squares

of the digits of a four-digit number is at most 4 · 92, which happens whenall the digits are 9. This number is 324, a three-digit number, so if n is afour-digit number, then f (n) has fewer than four digits. Similarly, if n isa five-digit number, then f (n) is at most 5 · 92 = 405, another three-digitnumber. In general if n is a k-digit number, that is, 10k−1 ≤ n < 10k, then

46

f (n) ≤ k · 81. In fact, k · 81 < 10k−1 whenever k ≥ 4. We have checked thatfor k = 4 and k = 5. How do we verify it for other values of k?This is a job for induction man. Suppose we have a number k for which

we know that k · 81 < 10k−1. We want to show that the same is true fork + 1, that is, that (k + 1) · 81 < 10k. Now we know that

(k + 1) · 81 = k · 81 + 81 < 10k−1 + 81Can we say that 10k−1 + 81 < 10k? That would verify our induction step.But 10k = 10 · 10k−1 so we are asking whether 81 < 9 · 10k−1. Well, 81 <9 · 10 = 9 · 102−1, so 10k−1 + 81 is certainly less than 10k if k ≥ 2. Bingo!So if n is a number with four or more digits, then f (n) < n. Thus,

starting anywhere, and iterating f , we eventually hit a three-digit number.Notice that unhappy numbers come in eight varieties depending on which

of the eight numbers in {4, 16, 37, 58, 89, 145, 42, 20} they first run into. “Happyfamilies are all alike; every unhappy family is unhappy in its own way.”LeoTolstoy, Anna Karenina.Exercise 1. To check that every number ends up either at 1 or trapped

in the set {4, 16, 37, 58, 89, 145, 42, 20}, it suffi ces to check every number withthree or fewer digits. That’s a pain to do by hand, but it’s easy to get Pythonto do. Do it.

7.4 Changing exponents and bases

There are two numbers we can change in the definition of f (m): the sumof the squares of the digits of m. One is the number 2 that we use becausewe are summing the squares of the digits. We could just as well sum thecubes of the digits, or the fourth powers of the digits. Call that number e, forexponent. For the original f , we have e = 2. It’s easy to change the recursionfor f (m) so that it now computes the sum of the cubes of the digits of m.How do you do that?The other number we can change is the number 10. That is the base b

for our system of representing numbers by strings of digits. If we change thenumber b = 10 to, say, b = 8, then the digits we get are the digits in thebase-8 representation of m, that is, we are thinking of writing m in octal.The octal representation of the number 340779 is “1231453”, or 12314538 ifwe want to indicate that the number is written in base 8. The sum of thesquares of its digits is

1 + 4 + 9 + 1 + 16 + 25 + 9 = 65 = 1018

47

and if we continue summing the squares of the digits we get 2, 4, 16 = 208,4 and we have run into a periodic point, 4, with period 2.Let’s examine in some detail what happens when we repeatedly sum the

squares of the digits of a number in base 5. Here is the beginning of a table:

1 → 1

2 → 4→ 16 = 315 → 10 = 205 → 4

Let f (n) denote the sum of the squares of the digits of n when we writen in base 5. Then f (1) = 1 because 1 = 15. The number 2 is equal to25 so f (2) = 4. The number 4 is equal to 45, so f (4) = 16 = 315. Nowf (315) = 10 = 205 and f (205) = 4, so we are back at 4, and we haveconstructed the orbit 4 16 10. The next entry in our table is

3→ 9 = 145 → 17 = 325 → 13 = 235 → 13

so we have discovered another fixed point: f (13) = 13, an orbit of size 1.Continue this table up to n = 18. How many orbits do you find?You can easily change your program for computing f (m) to one that

computes f (m, e, b), the sum of the e-th powers of the digits of m, where mis written in base b. Your first function f (m) was f (m, 2, 10).Exercise 1. Find the smallest number n > 1 such that n is happy in all

bases 2 through 8.Exercise 2. Show that there is no number greater than 1 that is happy

in all bases.Exercise 3. Show that every number is happy in bases 2 and 4. These

numbers are called “happy bases”. It is claimed (http://oeis.org/A161872)that 2 and 4 are the only happy bases less than 500, 000, 000.Exercise 4. It is claimed that the greatest happy number (base 10) that

has no repeated digits is 986543210. Verify that claim.Exercise 5. Find all the orbits of the functions f (m, 2, 7) and f (m, 2, 13).

8 Finding orbits

We are interested in the function f (m, e, b) that takes a number m to thesum of the e-th powers its digits when it is written in base b. We examinedf (m, 2, b) in the previous section. The function f (m, e, 10) maps a positive

48

integerm to a positive integers. Such a function f gives us a discrete dynami-cal system. We are particularly interested in the fixed points of such a system:numbers m such that f (m) = m. The fixed points m of f (m, 3, 10) are 1,153, 370, 371, and 407. We are also interested in periodic points which comein groups called orbits. An orbit is a finite set S of distinct positive integers{s1, s2, . . . , sk} so that f (si) = si+1, for i < k, and f (sk) = s1. If k = 1,then the orbit S contains exactly one number, and that number is a fixedpoint of f . An orbit of size 3 of the function f (m, e, 10) is {55, 250, 133}, asyou can easily check by hand.It turns out that if we choose any positive integer m whatsoever, and

keep applying f (m, e, b) to it, then eventually we end up in an orbit. Toverify that claim, we proceed as we did for the unhappy numbers: show thatf (m) < m for all suffi ciently large values of m. If m is has k-digits whenwritten in base b, then f (m, e, b) is at most k · (b− 1)e which happens whenall k of the digits of m are equal to b− 1, the largest digit. How many digitscan the number k · (b− 1)e have when written in base b? If a number is lessthan bd, then it has at most d digits, so we would like know how large k mustbe to guarantee that k · (b− 1)e < bk−1. However, for theoretical purposes,it is enough to know that bk−1/k gets arbitrarly large for large values of k.That’s because all we need is for bk−1/k eventually to be bigger than thefixed number (b− 1)e. Here is a graph of the function y = 2x−1/x

2 4 6 80

1

2

3

4

5

6

7

8

9

10

x

y

49

Looks like it is going off to infinity! We can use l’Hôpital’s rule to show that.Taking the derivative of the top and the bottom of 2x−1/x we get

2x−1 ln 2

which clearly goes to infinity.How can we find orbits of f? The simplest thing to do is to choose some

number n, either systematically or at random, and form the sequence n,f (n) , f (f (n)) , f (f (f (n))) , . . .. There are really only two things that canhappen, one of which we can detect. Either the sequence never repeats, orat some point we will generate a number that we have seen before. For allof the functions f (m, e, b), no matter what e and b are, this sequence willeventually repeat. How do we figure out where that happens?Given a function f , we want to write a program that finds the first place

k such that fk (m) = f i (m) for some i < k. More precisely, we want towrite a program that returns fk (m), where k is the first place such thatfk (m) = f i (m) for some i < k. For the function f (m, 2, 10), if we start atm = 11, and repeatedly apply f , we get the sequence

11, 2, 4, 16, 37, 58, 89, 145, 42, 20, 4

so we want to return 4. To do that, we have to keep track of where we havebeen. We can do that using a list or using a set. We’ll do it with a set Shere. At the start, we haven’t been anywhere, so S is empty. To set S equalto the empty set, we write S = set(). The standard way to generate thesequence that we want is to repeatedly set n equal to f (n). Of course wedon’t want to do that forever, so we want to stop when we’ve seen n before,that is, when n is in S. The easiest way to do that is to write a while-loop:while not n in S:. We also want to update S each time we look at anothervalue of n by putting n in S. That’s done by writing S.add(n). Those are allthe ingredients– write the function.If we use a list instead of a set, we can easily get our function to return

the orbit that n eventually ends up in. So now we have a list L that keepstrack of where we have been. Start out by setting L = [], and write L = L +[n] instead of S.add(n). Instead of returning n when we leave the while-loop,return the slice L[ L.index(n) : ]. The function L.index(n) returns the positionof the number n in the list L. The list L[ a : b ] is the slice of L that goesfrom position a up to, but not including, position b. The list L[ a : ] is theslice of L that goes from position a to the end of L. So L[ L.index(n) : ] is the

50

slice of the list L starting at the number n and going to the end of L. Thisis exactly the orbit that we end up in because n, at this point, is the firstnumber we have seen twice on our journey.

9 Aliquot sequences

One very much studied discrete dynamical system is given by the functions (n) which returns the sum of the proper divisors of n. Here we include thedivisor 1, even though it is rather uninteresting, but we don’t include n itself.So s (2) = 1, s (3) = 1, s (4) = 1+2 = 3, s (5) = 1, and s (6) = 1+2+3 = 6.Notice n is prime exactly when s (n) = 1. The number 6 is called perfectbecause s (6) = 6. It is a fixed point s.Technically, s (1) = 0 because 1 doesn’t have any proper divisors. I guess

we could say that s (n) is the sum of the positive divisors of n that are lessthan n.The study of perfect numbers goes back to antiquity. A related concept

is that of a pair of amicable numbers. These are distinct numbers mand n such that s (m) = n and s (n) = m. That is, the pair {m,n} isan orbit of size 2. Actually, we say that it is an orbit of period 2. Thesmallest amicable pair is {220, 284}. Bigger orbits are called sets of sociablenumbers. There is no orbit of period 3. An example of an orbit of period 4is {1264460, 1547860, 1727636, 1305184}.Unlike the other functions we have looked at, there is no guarantee that

if we keep applying the function s, we will eventually reach a finite orbit. Infact, this is a major unsolved problem. The first problematic number is 276.

10 The Collatz function

Another much studied dynamical system is given by the function

f (n) =

{n/2 if n is even3n+ 1 if n is odd

If you start at 1 you get the sequence 1, 4, 2, 1, an orbit of size 3. If youstart at 3 you get the sequence 3, 10, 5, 16, 8, 4 ending up in the same orbit ofsize 3. The sequence starting at 27 is quite interesting, but also ends up inthat same orbit. The Collatz conjecture is that no matter where you start,

51

you always end up in this orbit. So the conjecture is that there are no otherorbits, and no sequence can wander off to infinity.It’s unlikely that we will be able to find any other orbits, but we can ask

the question: if you start at a number n, what is the biggest number youwill see if you keep applying the function f? If you start at the number 1,the biggest number you see is 4. If you start at the number 2, the biggestnumber you see is 4– nothing new. If you start at the number 3, the biggestnumber you see is 16. A small table is

start 1 2 3 4 5 6 7 8 9biggest number encountered 4 4 16 16 16 16 52 4 52

The interesting numbers here are the ones that set new records; those arethe numbers 1, 3, and 7 which set the new records 4, 16, and 52. (Trycalculating by hand the largest number you get when you start with 7.) Thenext number to set a new record is 27 from which you eventually get to therecord high of 9232. So we get a smaller table

start 1 3 7 27new record 4 16 52 9232

Each number in the first row reaches a value greater than that reached by anyprevious number (a new record). The second row shows what those valuesare.Project: Extend this table to include, in addition to the numbers,

1, 3, 7, 27, all record holders less than 10000. You probably don’t want todo this by hand– write a Python program instead.

11 Bulgarian solitaire

Bulgarian solitaire, a game popularized by Martin Gardner, is played withstacks of a fixed number of coins. For example, suppose you start with 10coins divided into two stacks of 4 coins each and one stack of 2 coins. Wedenote this configuration by 442. A move in the game consists of taking onecoin from each stack to form a new stack. That’s it! What happens if youstart with 442? You take one coin from each stack, leaving two stacks of 3coins each and one stack of 2 coins, and you form a new stack with those3 coins you skimmed off. We denote this move by 442 → 3331. The game

52

continues 3331→ 4222→ 43111→ 532→ 4321→ 4321 and we are stuck– afixed point.If we start with a single stack of 9 chips, the game goes 9→ 81→ 72→

621 → 531 → 432 → 3321 → 4221 → 4311 → 432 and we are stuck in anorbit of size four.See http://mancala.wikia.com/wiki/Bulgarian_Solitaire

Project: Write a program that plays this game. I represented a config-uration by a list L so that L [i] is the number of stacks of size i, but maybethere’s a better way to do it. Perhaps the configuration 4311 should be rep-resented by the list [4, 3, 1, 1] rather than the list [0, 2, 0, 1, 1] which is how Idid it.Exercise 1. Show that the fixed points of Bulgarian solitaire are the

configurations 1, 21, 321, 4321, 54321, etc. Note that there are two parts tothis exercise: showing that those configurations are fixed points, and showingthat any fixed point is one of those configurations.Exercise 2. Find some other orbits of size greater than one. Can you

guess what the general form is?

12 The digits of n-factorial

Here are the first few values of n-factorial

0! 11! 12! 23! 64! 245! 1206! 7207! 50408! 40 3209! 362 88010! 3628 80011! 39 916 800

Our first project is to compute how many zeros appear at the end of n!. Oursecond project is to compute how many zeros as digits anywhere in n!, howmany ones, how many twos, and so on, up to how many nines. In the number

53

11!, the digit 0 appears twice (both at the end), the digit 1 appears once, thedigit 2 never appears, and so on. Here is the number 200!788 657 867 364 790 503 552 363 213 932 185 062 295 135 977 687 173 263 294 742

533 244 359 449 963 403 342 920 304 284 011 984 623 904 177 212 138 919 638 830 257642 790 242 637 105 061 926 624 952 829 931 113 462 857 270 763 317 237 396 988 943922 445 621 451 664 240 254 033 291 864 131 227 428 294 853 277 524 242 407 573 903240 321 257 405 579 568 660 226 031 904 170 324 062 351 700 858 796 178 922 222 789623 703 897 374 720 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

Notice that there are a whole bunch of zeros at the end. I count forty-nineof them. That means that 200! is divisible by 1049 but not by 1050.Exercise 1. Write a program that uses that fact to calculate how many

zeros there are at the end of n!. Compute the number t = n!, then keepdividing t by 10 until you can’t anymore. If you keep track of how manytimes you divided by 10, you will know how many zeros n! ends in.Another approach is to count how many factors of five there are in n!.

There is one zero at the end of n! for each factor of 5. That’s because n!contains many more twos than fives, so the number of factors of five will beequal to the number of factors of ten. Question: Why not use tens here?Of the numbers 1, 2, 3, . . . , n, the number that are divisible by 5 is equal

to bn/5c the floor of n/5, and each of them will contribute (at least) one 5to the product of them all, n!. The number that are divisible by 52 is equalto bn/52c, and these will each contribute (at least) one additional 5 to theproduct. Continuing in this way we see that the number of 5’s in n! is equalto ⌊n

5

⌋+⌊ n52

⌋+⌊ n53

⌋+ · · ·

where we continue the series as long as n ≥ 5k, after which all the terms arezero. Notice that this sum is approximately

n

(1

5+1

52+1

53+ · · ·

)=n

4

where we sum the infinite geometric series to get 1/4. When n is 200, thisestimate gives 200/4 = 50, pretty close to the actual number which is 49 aswe have seen. The exact computation in this case is⌊

200

5

⌋+

⌊200

25

⌋+

⌊200

125

⌋= 40 + 8 + 1 = 49

54

In Python 2, we can realize⌊n/5k

⌋by n/pow(5,k).

Exercise 2. Write the program!A third approach in Python is to compute n! and then convert it into a

string. We wouldn’t even consider this approach, except that that is the bestway to do the next problem. Once we have a string s that holds the digitsof n!, we can work our way from the right, starting at s [−1], until we hit anonzero digit. If that digit is at position −m in the string, then the stringhas m− 1 zeros at the end.Exercise 3. Write the program!The web site

http://2000clicks.com/MathHelp/BasicFactorialDigitFrequency.aspx

gives the digit frequencies of n! for n ≤ 500.The zeros at the end cause factorials to have more zeros than expected.

Call the other zeros and digits, "inside zeros", and "inside digits". Is it truethat the ratio of the inside zeros to the inside digits is approximately 1/10,and approaches this ratio in the limit as n gets large? Probably one of thoseimpossible-to-answer questions, although we can calculate that ratio for alln less than, say, 100, 000.Zero-perfect factorials: inside zeros appear with frequency exactly

1/10. Looks like the zero-perfect factorials with n < 2000 are 15!, 24!, 54!,146!, 326!, 643!, 732!, 1097!, 1211!, 1386!. We can also ask what are theone-perfect factorials, the two-perfect factorials, and so on. The number 15!is d-perfect for d = 0, 1, 4, 8. The numbers 146! and 732! are d-perfect ford = 0, 1, and possibly other digits. It’s not likely that we will encounter anumber n so that n! is d-perfect for every digit d.If s is a Python string, then s.count(i) will return the number of occur-

rences of i in s. So if m = n! and s is str(m), then s.count(’0’) returns thenumber of occurrences of zero in n!, both inside and at the end.

12.1 Benford’s law

States that the probability that the first digit of a number is d is equal tolog10 (1 + 1/d) = log10(1 + d) − log10(d). So the probability that the firstdigit is 1 is log10 (2), about 30%. Test on n! and b

n. See Julian Havil’sbook, “Impossible?”. Here are the actual and predicted results for 2n where

55

n = 1, 2, . . . , 2000

1 2 3 4 5 6 7 8 9602 354 248 194 160 134 114 105 89602 352 250 194 158 134 116 102 92

Here are the results for n!

1 2 3 4 5 6 7 8 9591 335 250 204 161 156 107 102 94602 352 250 194 158 134 116 102 92

13 Sequences of zeros in 2n

The first power of two that contains the digit 0 (in decimal notation) is210 = 1024. Is there a power of 2 that contains two consecutive 0’s? Well,253 = 9007 199 254 740 992 does, and it is the first one that does. How aboutthree consecutive 0’s? Consider 2242 = 7067 388 259 113 537 318 333 190 002971 674 063 309 935 587 502 475 832 486 424 805 170 479 104. Do you see thethree consecutive zeros? Drawing on the work of Edgar Karst and U. Karst,Mathematics of Computation, July 1964, Julian Havil gives the followingtable of the first appearances of consecutive zeros in powers of 2:

2 3 4 5 6 7 853 242 377 1491 1492 6801 14007

Here is 2377 = 307 828 173 409 331 868 845 930 000 782 371 982 852 185 463 050 511302 093 346 042 220 669 701 339 821 957 901 673 955 116 288 403 443 801 781 174 272.Finally, here is 21491 = 68 505 199 434 441 481 928 960 132 734 923 550 768 601 593

516 271 150 047 023 043 017 169 851 270 631 488 679 017 736 106 611 268 089 166 309388 272 338 901 170 497 165 901 308 515 144 865 310 386 727 931 343 535 071 260 408393 094 700 786 546 061 451 067 454 457 391 289 333 260 647 178 629 423 723 325 244889 881 619 755 782 509 111 430 765 139 535 811 541 502 291 720 957 726 164 276 777120 274 754 519 441 816 831 362 983 266 849 142 056 649 908 740 853 890 886 083 405397 212 467 377 035 143 021 587 233 073 571 308 500 000 341 901 085 017 693 125 848012 770 286 553 757 194 752 360 448. You can see where the five consecutivezeros are, and why 21492 contains six consecutive zeros.There is a remarkable theorem to the effect that there is a power of 2

containing any given number of consecutive zeros.

56

Cliffor A. Pickover, in A passion for mathematics, page 247, says that ac-cording to Michael Beeler and William Gosper, there is at least one zeroin each power of 2 between 286 = 77 371 252 455 336 267 181 195 264, and230749014. See item 57 of www.inwap.com/pdp10/hbaker/hakmen/hakmem.html.There is also a proof there, by Rich Schroeppel, that you can get arbitrarilymany nonzero final digits (in fact, 1’s and 2’s).To look for patterns in the digits of a number, you can convert it to a

string, and then use the Python function find. If s and t are strings, thens.find(t) will return the first index in the string s where the pattern t starts. Soif s is the string ’23050007900’, then s.find(’00’) will return 4. If the patternt does not appear in the string s, then s.find(t) returns −1. So s.find(’1’)will return −1 for this string s. To convert a number into a string, use thePython function str. For example, str(1024) returns the string ’1024’.Exercise 1. Verify that 2377 is the smallest power of 2 containing four

consecutive zeros.Exercise 2. Verify that the other numbers in the table are correct. The

number 14007 might take some time.Exercise 2. Explain why 21492 contains six consecutive zeros. Remember

this on Columbus Day!Exercise 3. Find all powers of 2 less than 2200 that contain no zeros.

14 Ciphers

A standard method for enciphering a piece of text is to replace the letters byother letters according to a fixed scheme. One famous example is attributedto Julius Caesar. The idea was to replace the letter a by the letter d, theletter b by the letter e, the letter c by the letter f , and so on until the letterz is replaced by the letter c. The scheme can be summarized in the followingtable

a b c d e f g h i j k l m n o p q r s t u v w x y zd e f g h i j k l m n o p q r s t u v w x y z a b c

where the letters in the second row are substituted for the letters in the firstrow. So the word “caesar”would become “fdhvu”. If we think of the lettersof the alphabet as being the numbers 0, 1, 2, . . . , 25, this amounts to replacingthe number n by the number n+ 3 (mod 26).

57

More briefly, we can think of the plain alphabet as being the string"abcdefghijklmnopqrstuvwxyz" and what we need to do is to specify a cipheralphabet which is some permutation of these 26 letters. In the Caesar ciphercase, we choose the cipher alphabet to be the string "defghijklmnopqrstu-vwxyzabc".Suppose p is the plain alphabet and c is the cipher alphabet. How do we

encrypt a message t? We want to form a new string r which is the encryptedmessage. The i-th character in the message t is t [i].We need to know the position j of t [i] in the plain alphabet p. (Remember

that positions start at 0.) Then we can set r [i] equal to c [j]. There is aPython function associated with the string p that does just that. It is calledp.find(). If we write p.find(’u’), we will get the position of the first occurrenceof the letter u in the string p. If the letter u does not appear in the string p,then we get the number −1. So we want to set r[i] = c[j] where j = p.find(t[i]).To decipher a message, we interchange the roles of p and c.There is a quick way to generate a cipher alphabet from a word, called

a keyword. It’s much easier to remember a keyword than to remember awhole cipher alphabet. Here is how you generate a cipher alphabet from thephrase “boca raton”. First you eliminate the space and all the duplicateletters, so you are left with “bocartn”. Then you form the following table,with the letters bocartn at the top, and the rest of the alphabet written inrows underneath:

b o c a r t nd e f g h i jk l m p q s uv w x y z

Finally, you read off the cipher alphabet by going down each column:

bdkvoelwcfmxagpyrhqztisnju

Exercise 1. What happens when you take the keyword to be the one-letter word “a”? The one-letter word “b”? The one-letter word “z”?Exercise 2. Develop a formula, like n+3 (mod 26) for the Caesar cipher,

for how to encipher using the two-letter keyword “ab”?

58

15 Stuff

What are the possible last two digits of a power of 2? Here are the first fewpowers of 2 modulo 100:

2, 4, 8, 16, 32, 64, 28, 56, 12, 24, 48, 96, 92, 84, 68, 36, 72, 44, 88, 76, 52, 4

Multiplying by 2 modulo 100 is a discrete dynamical system. We have justfound one of the orbits, namely:

4, 8, 16, 32, 64, 28, 56, 12, 24, 48, 96, 92, 84, 68, 36, 72, 44, 88, 76, 52

This orbit has size 20. The numbers in the orbit are all periodic points ofperiod 20. Notice that these numbers are all divisible by 4– it is not diffi cultto show that this must be the case. However not all two-digit numbers thatare divisible by 4 appear in this list. For example, the number 40 doesn’tappear in this list. Does that mean that a power of two cannot end in thedigits 40?

59