Book Python1
Book Python1
ARNAUD BODIN
A L G O R I T H M S A N D M AT H E M AT I C S
Exo7
Python in high school
Let’s go!
Everyone uses a computer, but it’s another thing to drive it! Here you will learn the basics of programming.
The objective of this book is twofold: to deepen mathematics through computer science and to master
programming with the help of mathematics.
Python
Choosing a programming language to start with is tricky. You need a language with an easy handling,
well documented, with a large community of users. Python has all these qualities and more. It is modern,
powerful and widely used, including by professional programmers.
Despite all these qualities, starting programming (with Python or another language) is difficult. The best
thing is to already have experience with the code, using Scratch for example. There is still a big walk to
climb and this book is there to accompany you.
Objective
Mastering Python will allow you to easily learn other languages. Especially the language is not the most
important, the most important thing is the algorithms. Algorithms are like cooking recipes, you have to
follow the instructions step by step and what counts is the final result and not the language with which the
recipe was written. This book is therefore neither a complete Python manual nor a computer course, nor is
it about using Python as a super-calculator.
The aim is to discover algorithms, to learn step-by-step programming through mathematical/computer
activities. This will allow you to put mathematics into practice with the willingness to limit yourself to the
knowledge acquired during the first years.
You can retrieve all the activity Python codes and all the source files on the Exo7 GitHub page:
GitHub: Python in high school
Contents
I Getting started 1
1 Hello world! 2
II Basics 17
4 Functions 24
7 Lists I 50
9 Files 68
11 Binary I 82
12 Lists II 89
13 Binary II 95
IV Projects 98
18 L-systems 126
22 Bitcoin 155
V Guides 171
Index
Summary of the activities
Hello world!
Get into programming! In this very first activity, you will learn to manipulate numbers, variables and code your
first loops with Python.
Functions
Writing a function is the easiest way to group code for a particular task, in order to execute it once or several
times later.
Arithmetic – While loop – I
The activities in this sheet focus on arithmetic: Euclidean division, prime numbers . . . This is an opportunity to
use the loop “while” intensively.
Lists I
A list is a way to group elements into a single object. After defining a list, you can retrieve each item of the list
one by one, but also add new ones. . .
Files
You will learn to read and write data with files.
Lists II
The lists are so useful that you have to know how to handle them in a simple and efficient way. That’s the
purpose of this chapter!
Binary II
We continue our exploration of the world of 0 and 1.
Dynamic images
We will distort images. By repeating these distortions, the images become blurred. But by a miracle after a
certain number of repetitions the original image reappears!
Game of life
The game of life is a simple model of the evolution of a population of cells that born and die over time. The
“game” consists in finding initial configurations that give interesting evolution: some groups of cells disappear,
others stabilize, some move. . .
Random blocks
You will program two methods to build figures that look like algae or corals. Each figure is made up of small
randomly thrown blocks that stick together.
PA R T I
G E T T I N G S TA R T E D
1
Chapter
1
Hello world!
Get into programming! In this very first activity, you will learn to manipulate numbers, variables
and code your first loops with Python.
1. How many seconds are there in a century? (Do not take leap years into account.)
2. How far do you have to complete the dotted formula to obtain a number greater than one billion?
(1 + 2) × (3 + 4) × (5 + 6) × (7 + 8) × · · ·
3. What are the last three digits of
123456789 × 123456789 × · · · ?
| {z }
7 instance of 123456789
4. 7 is the first integer such that its inverse has a repeating decimal representation of period 6:
1
= 0. |
142857
{z } 142857
| {z } 142857
| {z } . . .
7
Find the first integer whose inverse has a repeating decimal representation of period 7:
1
= 0.00 a bcd e f g a bcd e f g . . .
??? | {z } | {z }
HELLO WORLD! 3
Lesson 3 (Variables).
Variable. A variable is a name associated with a memory location. It is like a box that is identified by a
label. The command “a = 3” means that I have a variable “a” associated with the value 3.
Here is a first example:
a = 3 # One variable
b = 5 # Another variable
Comments. Any text following the sharp character “#” is not executed by Python but is used to explain
the program. It is a good habit to comment extensively on your code.
Names. It is very important to give a clear and precise name to the variables. For example, with the right
names you should know what the following code calculates:
base = 8
height = 3
area = base * height / 2
print(area)
# print(Area) # !! Error !!
Attention! Python is case sensitive. So myvariable, Myvariable and MYVARIABLE are different vari-
ables.
Re-assignment. Imagine you want to keep your daily accounts. You start with S0 = 1000, the next day
you earn 100, so now S1 = S0 + 100; the next day you add 200, so S2 = S1 + 200; then you lose 50, so on
the third day S3 = S2 − 50. With Python you can use only one variable S for all these operations.
S = 1000
S = S + 100
HELLO WORLD! 4
S = S + 200
S = S - 50
print(S)
You have to understand the instruction “S = S + 100” like this: “I take the contents of the box S, I add
100, I put everything back in the same box”.
Activity 2 (Variables).
1. (a) Define variables, then calculate the area of a trapezoid. Your program should display "The
value of the area is ..." using print("The value of the area is",area).
b=4
h=3
B=7
(b) Define variables to calculate the volume of a box (a rectangular parallelepiped) whose
dimensions are 10, 8, 3.
(c) Define a variable PI equals to 3.14. Define a radius R = 10. Write the formula for the area of
a disc of radius R.
2. Put the lines back in order so that, at the end, x has the value 46.
(1) y = y - 1
(2) y = 2*x
(3) x = x + 3*y
(4) x = 7
3. You place the sum of 1000 dollars in a savings account. Each year the interest on the money
invested brings in 10% (the capital is multiplied by 1.10). Write the code to calculate the capital
for the first three years.
4. I define two variables by a = 9 and b = 11. I would like to exchange the content of a and b.
Which instructions agree so that at the end a equals 11 and b equals 9?
c = a
c = b c = a
a = b a = c
a = b a = b
b = a c = b
b = c b = c
b = c
There are many other functions. For example, the function abs() calculates the absolute value:
abs(-3) returns 3, abs(5) returns 5.
• The module math.
Not all functions are directly accessible. They are often grouped in modules. For example, the
module math contains the mathematical functions. For instance, you will find the square root
function sqrt(). Here’s how to use it:
x = sqrt(2)
print(x)
print(x**2)
p
The first line imports all the functions of the module named math, the second line calculates x = 2
(in approximate value) and then displays x and x 2 .
• Sine and cosine.
The module math contains the trigonometric functions sine and cosine and even the constant pi
which is an approximate value of π. Be careful, the angles are expressed in radians.
Here is the calculation of sin( π2 ).
angle = pi/2
print(angle)
print(sin(angle))
• Decimal to integer.
In the module math there are also functions to round a decimal number:
– round() rounds to the nearest integer: round(5.6) returns 6, round(1.5) returns 2.
– floor() returns the integer less than or equal to: floor(5.6) returns 5.
– ceil() returns the integer greater than or equal to: ceil(5.6) returns 6.
• floor(3*x) returns 11
• ceil(4*x) returns 16
Hint. abs() refers to the absolute value function.
3. You know the trigonometric formula
cos2 θ + sin2 θ = 1.
Check that for θ = π7 (or other values) this formula is numerically true (this is not a proof of the
formula, because Python only makes approximate computations of the sine and cosine).
Note that what delimits the block of instructions to be repeated is indentation, i.e. the spaces at the
beginning of each line that shift the lines to the right. All lines in a block must have exactly the same
indentation. In this book, we choose an indentation of 4 spaces.
Don’t forget the colon “:” at the end of the line of the for declaration!
• Example of a “for” loop.
Here is a loop that displays the squares of the first integers.
for i in range(10):
print(i*i)
The second line is shifted and constitutes the block to be repeated. The variable i takes the value 0
and the instruction displays 02 ; then i takes the value 1, and the instruction displays 12 ; then 22 ,
32 . . .
In the end this program displays:
0, 1, 4, 9, 16, 25, 36, 49, 64, 81.
Warning: the last value taken by i is 9 (and not 10).
• Browse any list.
The loop “for” allows you to browse any list. Here is a loop that displays the cube of the first prime
numbers.
HELLO WORLD! 7
for p in [2,3,5,7,11,13]:
print(p**3)
• Sum all.
Here is a program that calculates
0 + 1 + 2 + 3 + · · · + 18 + 19.
mysum = 0
for i in range(20):
mysum = mysum + i
print(mysum)
Understand this code well: a variable mysum is initialized at 0. We will add 0, then 1, then 2. . . This
loop can be better understood by filling a table:
Initialisation: mysum= 0
i mysum
0 0
1 1
2 3
3 6
4 10
... ...
18 171
19 190
Display: 190
• range().
– With range(n) we run the entire range from 0 to n − 1. For example range(10)
corresponds to the list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
Attention! the list stops at n − 1 and not at n. What to remember is that the list contains
n items (because it starts at 0).
– If you want to display the list of items browsed, you must use the command:
list(range(10))
– With range(a,b) we go through the elements from a to b − 1. For example
range(10,20) corresponds to the list [10, 11, 12, 13, 14, 15, 16, 17,
18, 19].
– With range(a,b,step) you can browse the items a, a + step, a + 2step. . . For example
range(10,20,2) corresponds to the list [10, 12, 14, 16, 18].
• Nested loops.
It is possible to nest loops, i.e. inside the block of a loop, a new loop is used.
for x in [10,20,30,40,50]:
for y in [3,7]:
print(x+y)
HELLO WORLD! 8
In this small program x is first equal to 10, y takes the value 3 then the value 7 (so the program
displays 13, then 17). Then x = 20, and y again equals 3, then 7 again (so the program displays
23, then 27). Finally the program displays:
13, 17, 23, 27, 33, 37, 43, 47, 53, 57.
The module turtle allows you to easily make drawings in Python. It’s about ordering a turtle
with simple instructions like “go ahead”, “turn”. . . It’s the same principle as with Scratch, but with
one difference: you no longer move blocks, but you write the instructions.
exitonclick()
300
200
100
(0, 0)
−100
−200
−300
Activity 2 (Figures).
1. Pentagon. Draw a first pentagon (in blue). You have to repeat 5 times: advance 100 steps, turn 72
degrees.
Hint. To build a loop, use
for i in range(5):
(even if you do not use the variable i).
2. Pentagon (bis). Define a variable length which is equal to 200 and a variable angle which is
equal to 72 degrees. Draw a second pentagon (in red), this time advancing by length and turning
by angle.
3. Dodecagon. Draw a polygon having 12 sides (in purple).
Hint. To draw a polygon with n sides, it is necessary to turn an angle of 360/n degrees.
4. Spiral. Draw a spiral (in green).
Hint. Build a loop, in which you always turn at the same angle, but on the other hand you move
forward by a length that increases with each step.
Plot the graph of the square function and the sine function.
In order to get a curve in the turtle window, repeat for x varying from −200 to +200 :
1
• set y = 100 x 2,
• go to (x, y).
For the sinusoid, you can use the formula
1
y = 100 sin x .
20
By default Python does not know the sine function, to use sin() you must first import the module
math:
from math import *
To make the turtle move faster, you can use the command speed("fastest").
Here is how to picture the second drawing. Analyze the nesting of the loops and draw the next pictures.
for i in range(3):
color("blue")
forward(256)
left(120)
for i in range(3):
color("red")
forward(128)
left(120)
TURTLE (SCRATCH WITH PYTHON) 13
3 2
4 1
5 0
6 9
7 8
For example:
• the 3 point is linked to the 6 point, because 2 × 3 = 6 ;
• the 4 point is linked to the 8 point, because 2 × 4 = 8 ;
• the 7 point is linked to the 4 point, because 2 × 7 = 14 = 4 (mod 10).
(x 1 , y1 )
(x i , yi ) 2iπ
yi = r sin n
(x 0 , y0 )
2iπ (0, 0) x
x i = r cos n
(x n−1 , yn−1 )
turtle1.color('red')
turtle2.color('blue')
turtle1.forward(100)
turtle2.left(90)
turtle2.forward(100)
turtle 1 turtle 2
TURTLE (SCRATCH WITH PYTHON) 16
position1 = turtle1.position()
position2 = turtle2.position()
angle1 = turtle1.towards(position2)
turtle1.setheading(angle1)
• You place turtles at the four corners of a square, for example in (−200, −200), (200, −200),
(200, 200) and (−200, 200).
• You get the position of the first turtle by position1 = turtle1.position(). Same for the
other turtles.
• You calculate the angle between turtle 1 and turtle 2 by the command angle1 =
turtle1.towards(position2).
• You orient the first turtle according to this angle: turtle1.setheading(angle1).
• You advance the first turtle by 10 steps.
Improve your program by drawing a segment between the chasing turtle and the chased turtle each time.
PA R T I I
BASICS
17
Chapter
3
If ... then ...
The computer can react according to a situation. If a condition is met, it acts in a certain way,
otherwise it does something else.
keyword "if"
a condition
colon
if condition :
instruction_1 indented block
instruction_2 will be executed only
... if the condition is true
other instructions
program continuation
Instructions can also be executed if the condition is not met using the keyword “else”.
if condition :
instruction this block will be executed
instruction if the condition is true
...
else:
instruction this block will be executed
...
if the condition is not true
other instructions
Once again, it is the indentation that delimits the different blocks of instructions. Here is an example that
displays the sign of a number x.
IF ... THEN ... 19
if x >= 0:
print("The number is positive (or zero).")
else:
print("The number is negative.")
Explanations.
• The command input() pauses the execution of the program and waits for the user to send a text
(ended by pressing the “Enter” key).
• This command returns a string.
• If you want an integer, you have to convert the string. For example, here age_str can be equal to
"17" (it is not a number but a sequence of characters), while int(age_str) is now the integer
17.
• The reverse operation is also possible, str() converts a number into a string. For example str(17)
returns the string "17"; if you set age = 17, then str(age) also returns "17".
• Define a variable a, to which you assign a random value between 1 and 12.
• Same thing for a variable b.
• Display the question on the screen: “How much is the product a × b?”. (Replace a and b by their
value!)
• Retrieve the user’s answer and transform it into an integer.
• If the answer is correct, display “Well done!”, otherwise display “Lost! The correct answer was . . . ”.
Test of equality. To test if two numbers x and y are equal, the instruction is:
if x == y:
The equality test is written with the double symbol equal “==”. For example “x == 3” returns “True”
if x is equal to 3 and “False” otherwise.
Attention! The instruction “x = 3” has nothing to do with it, this instruction stores 3 in the variable
x.
Hints. Here’s how to scan the letters of a word and test if a letter is the character F:
for c in word:
if c == "F":
instructions...
IF ... THEN ... 21
Lesson 4 (Booleans).
• A bolean is a data that is either equal to the value “True” or the value “False”. In Python the values
are True and False (with a capital letter).
• We obtain a boolean for example as a result of the comparison of two numbers. For example 7 < 4
is equal to False (because 7 is not smaller than 4). Check that print(7 < 4) displays False.
Here are the main comparisons:
– Test of equality: a == b
– Strict lower test: a < b
– Large lower test: a <= b
– Higher test: a > b a >= b
or
– Test of non equality: a != b
For example 6*7 == 42 is equal to True.
•
• We can compare something other than numbers. For example, “char == "A"” tests if the variable
char is equal to "A"; “its_raining == True” tests if the variable its_raining is true. . .
• Booleans are useful in the test “if . . . then . . . ” and in the loops “while . . . then . . . ”.
• Operations between booleans. If P and Q are two booleans, new booleans can be defined.
– Logical and. “P and Q” is true if and only if P and Q are true.
– Logical or. “P or Q” is true if and only if P or Q is true.
– Negation. “not P” is true if and only if P is false.
For example “(2+2 == 2*2) and (5 < 3)” returns False, because even if we have 2+2 = 2×2,
the other condition is not satisfied because 5 < 3 is wrong.
for t in range(10):
for u in range(10):
n = 10*t + u
print(n)
2. Find all integers between 0 and 999 that check all the following properties:
• the integer ends with 3,
• the sum of the digits is greater than or equal to 15,
• the tens digit is even.
3. Modify your previous program to count and display the number of integers checking these proper-
ties.
IF ... THEN ... 22
Activity 4 (Triangles).
Goal: determine the properties of a triangle from the three lengths of the sides.
We give ourselves three lengths a, b and c. You will determine the properties of the triangle whose
lengths would be a, b, c.
a
b
Define three variables a, b and c with integer values and a 6 b 6 c (or ask the user for three values).
1. Order. Ask Python to test if the lengths check a 6 b 6 c. Display a sentence for the answer.
2. Existence. There is a triangle corresponding to these lengths if and only if:
a + b > c.
Ask Python to test if this is the case and display the answer.
3. Rectangle triangle. Ask Python to test if the triangle is a rectangular triangle. (Think of Pythagoras’
theorem.)
4. Equilateral triangle. Test if the triangle is equilateral.
5. Isosceles triangle. Test if the triangle is isosceles.
6. Acute triangle. Tests if all angles are acute (i.e. less than or equal to 90 degrees).
Hints.
• The cosine law allows to calculate an angle according to the lengths:
a
b
γ
β
α c
−a2 + b2 + c 2 a2 − b2 + c 2 a2 + b2 − c 2
cos α = , cos β = , cos γ = .
2bc 2ac 2a b
• To test if the angle α is acute just check cos α > 0 (in the end we never calculate α, but only
cos α).
4
Functions
Writing a function is the easiest way to group code for a particular task, in order to execute it once
or several times later.
def print_squares():
def say_hello():
for i in range(20):
print("Hello world!")
print(i**2)
return
return
The instructions are grouped into an indented block. The word return (optional) indicates the end of
the function. These instructions are executed only if I call the function. For example, each time I execute
the command say_hello(), Python displays the sentence “Hello world!”. Each time I execute the
command print_squares(), Python displays 0, 1, 4, 9, 16, . . ., i.e. the numbers i 2 for i = 0, . . . , 19.
keyword "def"
well-chosen name
parentheses
colon
def my_function () :
instruction_1
instruction_2 instructions
...
return
end of the function
def display_month(number):
if number == 1:
print("We are in January.")
if number == 2:
print("We are in February.")
if number == 3:
print("We are in March.")
# etc.
return
When called this function displays the name of the month based on the number provided as input. For
example display_month(3) will display "We are in March.".
def compute_cube(a):
cube = a * a * a # or a**3
return cube
This function calculates the cube of a number, for example compute_cube(2) does not display anything
but returns the value 8. This value can be used elsewhere in the program. For example, what do the
following instructions do?
x = 3
y = 4
z = compute_cube(x) + compute_cube(y)
print(z)
In mathematical terms, we put x = 3, y = 4, then we calculate the cube of x, the cube of y and add them
up:
z = x 3 + y 3 = 33 + 43 = 27 + 64 = 91
Thus the program displays 91.
returned result
• you write the code of a function only once, but you can call the function several times;
• by dividing our program into small blocks, each with its own use, the program is easier to write,
read, correct and modify;
• you can use a function written by someone else (such as the sqrt() function) without knowing
all the internal details of its programming.
def sum_product(a,b):
""" Computes the sum and product of two numbers. """
s = a + b
p = a * b
return s, p
FUNCTIONS 27
The last line calls the function with arguments 6 (for parameter a) and 7 (for parameter b). This function
returns two values, the first one is assigned to mysum (which is therefore equal to 13) and the second
one to myprod (which is equal to 42).
So let’s remember:
• There can be several input parameters.
• There can be several results at the output.
• Very important! Do not confuse displaying and returning a value. The display (by the command
print()) just displays something on the screen. Most functions do not display anything, but return
one (or more) value. This is much more useful because this value can be used elsewhere in the
program.
• As soon as the program encounters the instruction return, the function stops and returns the result.
There may be several times the instruction return in a function but only one will be executed. It
is also possible not to put an instruction return if the function returns nothing.
• In the instructions of a function, you can of course use other functions!
• It is important to comment well on your programs. To document a function, you can describe what
it does starting with a docstring, i.e. a description (in English) surrounded by three quotation marks:
""" My function does this and that. """
to be placed just after the header.
• When defining a function, the variables that appear between the parentheses are called the pa-
rameters; when calling the function, however, the values between the parentheses are called the
arguments. There is of course a correspondence between the two.
Activity 3 (Turtle).
Goal: define some functions that draw geometric shapes. Creating a function is similar to creating
a block with Scratch.
1. Program a function triangle() that draws a triangle (in red, each side measuring 200).
FUNCTIONS 29
2. Program a function square() that draws a square (in green, each side measuring 200). Use a
loop “for” so you don’t have to rewrite the same instructions several times.
3. Program a hexagon(length) function that draws a hexagon (in blue) of a given side length (the
angle to turn is 60 degrees).
4. Program a function polygon(n,length) that draws a regular polygon of n sides and a given
side length (the angle to rotate is 360/n degrees).
1. (a) Here is the discount for the price of a train ticket based on the age of the passenger:
• reduction of 50% for those under 10 years old;
• reduction of 30% for 10 to 18 years old;
• reduction of 20% for 60 years old and over.
Write a function reduction() that returns the reduction according to age and whose
properties are recalled in the box below:
reduction()
Use: reduction(age)
Input: an integer corresponding to age
Output: an integer corresponding to the reduction
Examples:
• reduction(17) returns 30.
• reduction(23) returns 0.
Deduce a amount() function that calculates the amount to be paid based on the normal fare
and the traveler’s age.
amount()
Use: amount(normal_rate,age)
Input: a number normal_rate corresponding to the price without discount
and age (an integer)
Output: a number corresponding to the amount to be paid after reduction
Note: uses the function reduction()
Example: amount(100,17) returns 70.
A family buys tickets for different trips, here is the normal fare for each trip and the ages of
the passengers:
• normal price 30 dollars, child of 9 years old;
• normal price 20 dollars, for each of the twins of 16 years old;
• normal price 35 dollars, for each parent of 40 years old.
What is the total amount paid by the family?
2. We want to program a small quiz on the multiplication tables.
(a) Program a function is_calculation_correct() that decides if the answer given to a
multiplication is right or not.
FUNCTIONS 30
is_calculation_correct()
Use: is_calculation_correct(a,b,answer)
Input: three integers, answer being the proposed answer to the calculation
of a × b.
Output: “True” or “False”, depending on whether the answer is correct or not
Examples:
• is_calculation_correct(6,7,35) returns False.
• is_calculation_correct(6,7,42) returns True.
(b) Program a function that displays a multiplication, asks for an answer and displays a short
concluding sentence. All this in English or a foreign language!
test_multiplication()
Use: test_multiplication(a,b,lang)
Input: two integers, the chosen language (for example "english" or
"french")
Output: nothing (but display a sentence)
Note: uses the function is_calculation_correct()
Example: test_multiplication(6,7,"french") asks, in French, for the
answer to the calculation 6 × 7 and answers if it is correct or not.
Bonus. Improve your program so that the computer offers random operations to the player. (Use
the randint() function of the module random.)
1. (a) Build a function absolute_value(x) that returns the absolute value of a number (without
using the function abs() of Python).
p
(b) Build a function root_of_square(x) which corresponds to the calculation of x 2 .
(c) Two functions (of one variable) f and g are said to be experimentally equal if f (i) = g(i)
for i = −100, −99, . . . , 0, 1, 2, . . . , 100. Check by computer that the two functions defined by
p
|x| and x2
are experimentally equal.
2. (a) Build a two-parameter function F1(a,b) that returns (a + b)2 . Same thing with F2(a,b)
that returns a2 + 2a b + b2 .
(b) Two functions of two variables F and G are said to be experimentally equal if F (i, j) = G(i, j)
for all i = −100, −99, . . . , 100 and for all j = −100, −99, . . . , 100. Check by computer that
the functions defined by (a + b)2 and a2 + 2a b + b2 are experimentally equal.
(c) I know that one of the following two identities is true:
(a − b)3 = a3 − 3a2 b − 3a b2 + b3 or (a − b)3 = a3 − 3a2 b + 3a b2 − b3 .
Help yourself from the computer to decide which one it is!
3. (a) Build a function sincos(x) that returns (sin(x))2 + (cos(x))2 and another one(x) that
always returns 1. Are these two functions experimentally equal (in the sense of the first
question)? Find out what could be the cause of this answer.
FUNCTIONS 31
(b) Fix ε = 0.00001. It is said that two functions (of one variable) f and g are experimentally
approximately equal if | f (i) − g(i)| 6 ε for i = −100, −99, . . . , 100. Do the two functions
defined by sincos(x) and one(x) now check this criterion?
(c) Experimentally check and experimentally approximately check the identities:
π
sin(2x) = 2 sin(x) cos(x), cos − x = sin(x).
2
(d) Bonus. A counter-example. Show that the functions defined by g1 (x) = sin(πx) and g2 (x) =
0 are experimentally equal (with our definition given above). But also show that you don’t
get g1 (x) = g2 (x) for every x ∈ R.
def my_function(x):
x = x + 1
return x
x = 7
print(my_function(x))
print(x)
• Variables defined within a function are called local variables. They do not exist outside the function.
• If there is a variable in a function that has the same name as a variable in the program (like the x
in the example above), it is as if there were two distinct variables; the local variable only exists
inside the function.
To understand the scope of the variables, you can color the global variables of a function in red, and the
local variables with one color per function. The following small program defines a function that adds one
and another that calculates the double.
FUNCTIONS 32
global variable
x = 7
def add_one( x ):
x = x +1
local variable
return x
def double( x ):
x = 2 * x
another local variable
return x
print( x )
print(add_one( x ))
print(double( x ))
print( x )
The program first displays the value of x, so 7, then it increases it by 1, so it displays 8, then it displays
twice as much as x, so 14. The global variable x has never changed, so the last display of x is still 7.
It is still possible to force the hand to Python and modify a global variable in a function using the keyword
global. See the chapter “Polish calculator – Stacks”.
Chapter
The activities in this sheet focus on arithmetic: Euclidean division, prime numbers . . . This is an
opportunity to use the loop “while” intensively.
Lesson 1 (Arithmetic).
We recall what Euclidean division is. Here is the division of a by b, a is a positive integer, b is a strictly
positive integer (with an example of 100 divided by 7) :
quotient
q 14
b a 7 100
remainder
r 2
With Python :
• a // b returns the quotient,
• a % b returns the remainder.
1. Program a function quotient_remainder(a,b) that does the following tasks for two integers
a > 0 and b > 0 :
• It displays the quotient q of the Euclidean division of a per b,
• it displays the remainder r of this division,
ARITHMETIC – WHILE LOOP – I 34
• it displays True if the remainder r is positive or zero and strictly less than b, and False
otherwise,
• it displays True if you have equality a = bq + r, and False if not.
Here is for example what the call should display quotient_remainder(100,7):
Division of a = 100 per b = 7
The quotient is q = 14
The remainder is r = 2
Check remainder: 0 <= r < b? True
Check equality: a = bq + r? True
Note. You have to check without cheating that we have 0 6 r < b and a = bq + r, but of course it
must always be true!
2. Program a function is_even(n) that tests if the integer n is even or not. The function returns
True or False.
Hints.
• First possibility: calculate n % 2 and discuss as appropriate.
• Second possibility: calculate n % 10 (which returns the digit of units) and discuss.
• The smartest people will be able to write the function with only two lines (one for def...
and the other for return...).
3. Program a function is_divisible(a,b) that tests if b divides a. The function returns True or
False.
keyword "while"
a condition
colon
while condition :
instruction_1 indented block will
instruction_2 be executed as long as
... the condition is true
other instructions
program continuation
ARITHMETIC – WHILE LOOP – I 35
Example.
Here is a program that displays the countdown
n = 10
10, 9, 8, . . . 3, 2, 1, 0. As long as the condition n > 0 is
while n >= 0:
true, we reduce n by 1. The last value displayed is n = 0,
print(n)
because then n = −1 and the condition “n > 0” becomes
n = n - 1
false so the loop stops.
This is summarized in the form of a table:
Input: n = 10
n “n > 0” ? new value of n
10 yes 9
9 yes 8
... ... ...
1 yes 0
0 yes −1
−1 no
Display: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
Example.
n = 100
This piece of code looks for the first power of 2 greater
p = 1
than a given integer n. The loop prints the values 2, 4,
while p < n:
8, 16,. . . It stops as soon as the power of 2 is higher or
p = 2 * p
equal to n, so here this program displays 128.
print(p)
Inputs: n = 100, p = 1
p “p < n” ? new value of p
1 yes 2
2 yes 4
4 yes 8
8 yes 16
16 yes 32
32 yes 64
64 yes 128
128 no
Display: 128
ARITHMETIC – WHILE LOOP – I 36
Example.
For this last loop we have already prepared a function
is_even(n) which returns True if the integer n is even n = 56
and False otherwise. The loop does this: as long as while is_even(n) == True:
the integer n is even, n becomes n/2. This amounts to n = n // 2
removing all factors 2 from the integer n. As here n = print(n)
56 = 2 × 2 × 2 × 7, this program displays 7.
Input: n = 56
n “is n even” ? new value of n
56 yes 28
28 yes 14
14 yes 7
7 no
Display: 7
For the latter example, it is much more natural to start the loop with
while is_even(n):
Indeed is_even(n) is already a value “True” or “False”. We’re getting closer to the English sentence
“while n is even...”
Operation “+=”. To increment a number you can use these two methods:
nb = nb + 1 or nb += 1
The second writing is shorter but makes the program less readable.
We will improve our function which tests if a number is prime or not, it will allow us to test more
quickly lots of numbers or very large numbers.
4. Prime numbers (2).
Enhance your previous function to a is_prime_2(n) that does not test all divisors d from 2 to n,
p
but only up to n.
Explanations.
• For example, to test if 101 is a prime number, just see if it admits divisors among 2, 3, . . . , 10.
The gain is significant!
• This improvement is due to the following proposal: if an integer is not prime then it admits a
p
divisor d that verifies 2 6 d 6 n.
p
• Instead of testing if d 6 n, it is easier to test if d 2 6 n.
5. Prime numbers (3).
Improve your function into a function is_prime_3(n) using the following idea. We test if d = 2
divides n, but from d = 3, we just test the odd divisors (we test d, then d + 2. . . ).
• For example to test if n = 419 is a prime number, we first test if d = 2 divides n, then d = 3
and then d = 5, d = 7. . .
• This allows you to do about half less tests!
• Explanations: if an even number d divides n, then we already know that 2 divides n.
6. Calculation time.
Compare the calculation times of your different functions is_prime() by repeating for example
a million times the call is_prime(97). See the course below for more information on how to do
this.
print(timeit.timeit("my_function_1(1000)",
setup="from __main__ import my_function_1",
number=100000))
print(timeit.timeit("my_function_2(1000)",
setup="from __main__ import my_function_2",
number=100000))
Results.
The result depends on the computer, but allows the comparison of the execution times of the two functions.
• The measurement for the first function (called 100 000 times) returns 5 seconds. The algorithm is
not very clever. We’re testing if 7 × 1 = n, then test 7 × 2 = n, 7 × 3 = n. . .
• The measurement for the second function returns 0.01 second! We test if the remainder of n divided
by 7 is 0. The second method is therefore 500 times faster than the first.
Explanations.
• The module is named timeit.
• The function timeit.timeit() returns the execution time in seconds. It takes as parameters:
– a string for the call of the function to be tested (here we ask if 1000 is divisible by 7),
– an argument setup="..." which indicates where to find this function,
– the number of times you have to repeat the call to the function (here number=100000).
• The number of repetitions must be large enough to avoid uncertainties.
For example, the first Germain prime number after n = 60 is p = 83, with 2p + 1 = 167. What is
the first Germain prime number after n = 100 000?
Chapter
Letter p l a n e
Rank 0 1 2 3 4
Note that there are 5 letters in the word "plane" and that you access it through the ranks starting with
0. The indices are therefore here 0, 1, 2, 3, and 4 for the last letter. More generally, if word is a string,
characters are obtained by word[i] for i varying from 0 to len(word)-1.
Lesson 3 (Substrings).
You can extract several characters from a string using the syntax word[i:j] which returns a string
STRINGS – ANALYSIS OF A TEXT 41
Letter w e d n e s d a y
Rank 0 1 2 3 4 5 6 7 8
Another example: word[1:len(word)-1] returns the word but with its first and last letter cut off.
Goal: write step by step a program that returns the plural of a given word.
1. For a string word, for example "cat", displays the plural of this word by adding a "s".
2. For a word, for example "bus", display the last letter of this string (here "s"). Improve your
program of the first question, by testing if the last letter is already a "s":
• if this is the case, then add "es" to form the plural ("bus" becomes "buses"),
• otherwise you have to add "s".
3. Test if a word ends with "y". If so, display the plural in "ies" (the plural of "city" is "cities").
(Exceptions are not taken into account.)
4. Collect all your work from the first three questions in a function plural(). The function displays
nothing, but returns the word in the plural.
plural()
Use: plural(word)
Input: a word (a string)
Output: the plural of the word
Examples:
• plural("cat") returns "cats"
• plural("bus") returns "buses"
• plural("city") returns "cities"
5. Write a function conjugation() that conjugates a verb to the present continuous tense.
conjugation()
Use: conjugation(verb)
Input: a verb (a string, exceptions are not taken into account)
Output: no result but displays conjugation in the present continuous tense
hamming_distance()
Use: hamming_distance(word1,word2)
Input: two words (strings)
Output: the Hamming distance (an integer)
Example: hamming_distance("SHORT","SKIRT") returns 2
2. Upside down.
Write a function upsidedown() that returns a word backwards: HELLO becomes OLLEH.
upsidedown()
Use: upsidedown(word)
Input: a word (a string)
Output: the word backwards
Example: upsidedown("PYTHON") returns "NOHTYP"
3. Palindrome.
Deduce a function that tests whether a word is a palindrome or not. A palindrome is a word that
can be written from left to right or right to left; for example RADAR is a palindrome.
STRINGS – ANALYSIS OF A TEXT 43
is_palindrome()
Use: is_palindrome(word)
Input: a word (a string)
Output: “True” if the word is a palindrome, “False” otherwise.
Example: is_palindrome("KAYAK") returns True
4. Pig latin. Pig latin is word play, here are the rules according to Wikipedia:
• For words that begin with vowel sounds, one just adds "way" to the end. Examples are:
– EAT becomes EATWAY
– OMELET becomes OMELETWAY
– EGG becomes EGGWAY
• For words that begin with consonant sounds, all letters before the initial vowel are placed at
the end of the word sequence. Then, "ay" is added, as in the following examples:
– PIG becomes IGPAY
– LATIN becomes ATINLAY
– BANANA becomes ANANABAY
– STUPID becomes UPIDSTAY
– GLOVE becomes OVEGLAY
Write a function pig_latin() that transforms a word according to this procedure.
pig_latin()
Use: pig_latin(word)
Input: a word (a string)
Output: the word transformed into pig latin.
Examples:
• pig_latin("DUCK") returns "UCKDWAY"
• pig_latin("ALWAYS") returns "ALWAYSWAY"
Activity 3 (DNA).
A DNA molecule is made up of about six billion nucleotides. The computer is therefore an essential
tool for DNA analysis. In a DNA strand there are only four types of nucleotides that are noted A,
C, T or G. A DNA sequence is therefore a long word in the form: TAATTACAGACACCTGAA...
1. Write a function presence_of_A() that tests if a sequence contains the nucleotide A.
presence_of_A()
Use: presence_of_A(sequence)
Input: a DNA sequence (a string whose characters are among A, C, T, G)
Output: “True” if the sequence contains “A”, “False” otherwise.
Example: presence_of_A("CTTGCT") returns False
2. Write a function position_of_AT() that tests if a sequence contains the nucleotide A followed
by the nucleotide T and returns the position of the first occurrence found.
STRINGS – ANALYSIS OF A TEXT 44
position_of_AT()
Use: position_of_AT(sequence)
Input: a DNA sequence (a string whose characters are among A, C, T, G)
Output: the position of the first sequence “AT” found (starting at 0); None if
not found.
Example:
• position_of_AT("CTTATGCT") returns 3
• position_of_AT("GATATAT") returns 1
• position_of_AT("GACCGTA") returns None
4. A crime has been committed in the castle of Adeno. You recovered two strands of DNA, from two
distant positions from the culprit’s DNA. There are four suspects, whose DNA you sequenced. Can
you find out who did it?
First code of the culprit: CATA
Second code of the culprit: ATGC
DNA of Colonel Mustard:
CCTGGAGGGTGGCCCCACCGGCCGAGACAGCGAGCATATGCAGGAAGCGGCAGGAATAAGGAAAAGCAGC
Miss Scarlet’s DNA:
CTCCTGATGCTCCTCGCTTGGTGGTTTGAGTGGACCTCCCAGGCCAGTGCCGGGCCCCTCATAGGAGAGG
Mrs. Peacock’s DNA:
AAGCTCGGGAGGTGGCCAGGCGGCAGGAAGGCGCACCCCCCCAGTACTCCGCGCGCCGGGACAGAATGCC
Pr. Plum’s DNA:
CTGCAGGAACTTCTTCTGGAAGTACTTCTCCTCCTGCAAATAAAACCTCACCCATGAATGCTCACGCAAG
39 ’ 49 1 59 ; 69 E 79 O 89 Y 99 c 109 m 119 w
1. The function chr() is a Python function that returns the character associated to a code.
python : chr()
Use: chr(code)
Input: a code (an integer)
Output: a character
Example:
• chr(65) returns "A"
• chr(123) returns "{"
2. The function ord() is a Python function corresponding to the reverse operation: it returns the
code associated with a character.
python : ord()
Use: ord(charac)
Input: a character (a string of length 1)
Output: an integer
Example:
• ord("A") returns 65
• ord("*") returns 42
1. Decodes by hand the encrypted message hidden under the following codes:
80-121-116-104-111-110 105-115 99-64-64-108
2. Write a loop that displays characters encoded by integers from 33 to 127.
3. What does the command chr(ord("a")-32) return? And chr(ord("B")+32)?
STRINGS – ANALYSIS OF A TEXT 46
4. Write a function upper_letter() that transforms a lowercase letter into its uppercase letter.
upper_letter()
Use: upper_letter(charac)
Input: a lowercase character among "a",...,"z"
Output: the same letter in upper case
Example: upper_letter("t") returns "T"
5. Write a function uppercase() which from a sentence written in lower case returns the same
sentence written in upper case. Characters that are not lowercase letters remain unchanged.
uppercase()
Use: uppercase(sentence)
Input: a sentence
Output: the same sentence in upper case
Example: uppercase("Hello world!") returns "HELLO WORLD!"
format_full_name()
Use: format_full_name(somebody)
Input: a person’s first name and surname (without accent, separated by a
space)
Output: the full name following the format "First name LAST NAME"
Example:
• format_full_name("harry Potter") returns "Harry POTTER"
• format_full_name("LORD Voldemort") returns "Lord
VOLDEMORT"
Activity 5.
Goal: determine the language of a text from the analysis of letter frequencies.
1. Write a function occurrences_letter() that counts the number of times the given letter appears
in a sentence (in upper case).
STRINGS – ANALYSIS OF A TEXT 47
occurrences_letter()
Use: occurrences_letter(letter,sentence)
Input: a letter (a character) and a sentence in capital letters (a string)
Output: the number of occurrences of the letter (an integer)
Example: occurrences_letter("E","IS THERE ANYBODY OUT
THERE") returns 4
2. Write a function number_letters() that counts the total number of letters that appear in a
sentence (in upper case). Do not count spaces or punctuation.
number_letters()
Use: number_letters(sentence)
Input: a sentence in capital letters (a string)
Output: the total number of letters from “A” to “Z” (an integer)
Example: number_letters("IS THERE ANYBODY OUT THERE") re-
turns 22.
3. The frequency of appearance of a letter in a text or sentence is the percentage given according to
the formula :
number of occurrences of the letter
frequency of appearance of a letter = × 100.
total number of letters
For example, the sentence IS THERE ANYBODY OUT THERE contains 22 letters; the letter E
appears there 4 times. The frequency of appearance of E in this sentence is therefore:
number of occurrences of E 4
fE = × 100 = × 100 ' 16.66
total number of letters 22
The frequency is therefore about 17%.
Write a function percentage_letter() that calculates this frequency of appearance.
percentage_letter()
Use: percentage_letter(letter,sentence)
Input: a letter (a character) and a sentence in capital letters (a string)
Output: the frequency of appearance of the letter (a number lower than 100)
Example: percentage_letter("E","IS THERE ANYBODY OUT
THERE") returns 16.66. . .
Use this function to properly display the frequency of appearance of all letters in a sentence.
4. Here is the frequency of appearance of letters according to the language used (source:
en.wikipedia.org/wiki/Letter_frequency). For example, the most common letter in English is
“E” with a frequency of more than 12%. The “W” represents about 2% of letters in English and
German, but almost does not appear in French and Spanish. These frequencies also vary according
to the text analyzed.
STRINGS – ANALYSIS OF A TEXT 48
In your opinion, in which languages were written the following four texts (the letters of each word
were mixed).
TMAIER BERACUO RSU NU REBRA PRCEEH EIANTT NE ONS EBC NU GAOFREM EIMATR RERNAD APR L
RDUOE LAHECLE UIL TTNI A EUP SREP EC LGNGAEA TE RBONUJO ERMNOUSI DU UBRACEO QUE
OVSU EEST LIJO UQE OUVS EM MSZELBE BAEU ASNS MIERNT IS RVETO AGRAME ES PRARPTOE A
OEVTR AMGUPLE VUOS SEET EL PNIHXE DSE OSHET ED CSE BIOS A ESC MSOT LE OUBRCEA NE ES
ESTN ASP DE IEJO TE OUPR ERRNOTM AS BELEL XOVI IL OREVU NU RGLEA ECB ILESSA EBOMTR AS
PIOER EL NRDAER S EN ISIAST TE ITD MNO NOB EUSRMNOI NRPEEAZP QEU UTOT EUTLRFTA IVT XUA
SPNEDE DE UECIL UQI L TECEOU TECET NEOCL VATU BNEI UN GMAEORF SNAS TUOED LE EOABURC
OHENTXU TE NSCOFU UJRA SMIA UN EPU TRDA UQ NO EN L Y ARRPEIDNT ULSP
WRE TREITE SO TSPA CUDHR AHNCT UND WIND SE STI RED AEVRT MTI ESEIMN IDNK RE ATH END
NEABNK WLOH IN EMD AMR ER AFTSS HIN IHSERC RE AHTL HIN MRWA EINM SHNO SAW SRTIBG UD
SO NGBA DNEI EIHSGTC ESISTH RAETV UD DEN LERNIOKG NITHC NDE LOENINKGRE TIM OKRN UDN
CHWFSEI NEIM NSOH ES STI IEN BIFTRLSEEEN DU BILESE IKDN OMKM EHG MIT MIR RAG ECHNOS
EPELSI EIPSL IHC ITM RDI HNCMA BEUTN MBLUNE DINS NA DEM TNDRAS NMIEE UTETMR AHT
CAMHN UDNGEL GDAWEN MIEN EATRV MENI VEART DUN OSTHER DU CINTH SAW KNNOEIREGL RIM
ILEES PRSTVRCIEH ISE IHGRU BEEILB RIGUH MNEI KNDI NI RDNEUR NATBRLET STAESUL EDR WNID
DSNOACAIF ORP ANU DAEDALRI DNAAEIMTI EQU NNCOSETE EL RSTEOUL SMA AACTFAITNS UQE EL
TSVAO OINSRVUE DE US ANIGIICANOM EIORDP TOOD RTEIENS RPO LE ITOABOLRROA ED QIUAMALI
USOP A NSSRCAEAD LA TMREAAI NXTADAUEE ROP GOARLS EMESS DE NNAMICLUIAPO Y LOVOIV A
STRINGS – ANALYSIS OF A TEXT 49
RES LE RHMEOB EOMDNEERPRD DE LOS RSOPMRIE OMTSIPE UEQ CIIDADE LE RTDAAOZ ED LSA
CELSAL Y LA NICOIOPS ED LAS UESVNA SSACA Y ES ITRMNEEOD QEU AERFU EL UEQIN IIIRDEGAR LA
NAIORTREICP DE AL RRTEIA
IMTRUESMME DNA TEH LNGIIV SI EYAS SIFH REA GJPNUIM DNA HET TTNOCO IS GHIH OH OUYR
DDADY SI IRHC DAN ROUY MA SI DOGO GKOILON OS USHH LTLIET BBYA NDOT OUY CYR NEO OF
HESET GNSRONIM YUO RE NANGO SIER PU SNIGING NAD OULLY EPADRS YUOR GINSW DAN LYOLU
KATE OT HET KSY TUB ITLL TATH MGNIRNO EREHT NATI INTGOHN ACN AHMR OYU TWIH DADYD NDA
MYMMA NSTIDGAN YB
Chapter
7
Lists I
A list is a way to group elements into a single object. After defining a list, you can retrieve each item
of the list one by one, but also add new ones. . .
rank : 0 1 2 3 4 5
• Add an element. To add an item at the end of a list, just use the command
mylist.append(element). For example if primes = [2,3,5,7] then primes.append(11)
adds 11 to the list, if you then execute the instruction primes.append(13) then the list primes
is now [2,3,5,7,11,13].
• Example of construction. Here is how to build the list that contains the first squares:
1. Simple interest. We have a sum of S0 . Each year this investment earns interest based on the initial
amount.
For example, with an initial amount of S0 = 1000 and simple interest of p = 10%. The interest is
100. So after one year, I have a sum of S1 = 1100, after two years S2 = 1200. . .
Program a simple_interest(S0,p,n) function that returns the list of amounts for the n first
years. For example simple_interest(1000,10,3) returns [1000, 1100, 1200, 1300].
2. Compound interest. A sum of S0 brings in compound interest. This time the interest is calculated
each year on the basis of the sum of the previous year, i.e. according to the formula:
p
I n+1 = Sn ×
100
Program a function compound_interest(S0,p,n) which returns the list of amounts of the n first
years. For example compound_interest(1000,10,3) returns [1000, 1100, 1210, 1331].
3. I have the choice between a simple interest investment of 10% or a compound interest investment
of 7%. What is the most advantageous solution depending on the duration of the placement?
• Add an item at the end. The operator “+” provides another method to add an item to a list:
mylist = mylist + [element]
For example [1,2,3,4] + [5] is [1,2,3,4,5]. Attention! The element to be added must be
surrounded by square brackets. It is an alternative method to mylist.append(element).
• Add an element at the beginning. With :
mylist = [element] + mylist
the item is added at the beginning of the list. For example [5] + [1,2,3,4] is [5,1,2,3,4].
• Slicing lists. You can extract a whole part of the list at once: mylist[a:b] returns the sublist of
items with ranks a to b − 1.
rank : 0 1 2 3 4 5 6
1. Program a function rotate(mylist) that shifts all the elements of a list by one rank (the last
element becoming the first). The function returns a new list.
For example, rotate([1,2,3,4]) returns the list [4,1,2,3].
2. Program a function inverse(mylist) that inverts the order of the elements in a list.
For example, inverse([1,2,3,4]) returns the list [4,3,2,1].
3. Program a function delete_rank(mylist,rank) that returns a list of all elements, except the
one at the given rank.
For example, delete_rank([8,7,6,5,4],2) returns the list [8,7,5,4] (the item 6 that was
at rank 2 is deleted).
4. Program a function delete_element(mylist,element) returning a list that contains all items
except those equal to the specified element.
For example, delete_element([8,7,4,6,5,4],4) returns the list [8,7,6,5] (all items equal
to 4 have been deleted).
• Delete an item. The command mylist.remove(element) deletes the first occurrence found
(the list is modified). For example with mylist = [2,5,3,8,5] the call mylist.remove(5)
modifies the list which is now [2,3,8,5] (the first 5 has disappeared).
• Delete an element (bis). The command del mylist[i] deletes the element of rank i (the list is
modified).
The bubble sort is a simple way to order a list, here it will be from the smallest to the largest element.
The principle is as follows:
• We go through the list from the beginning. As soon as you encounter two consecutive elements in
the wrong order, you exchange them.
• At the end of the first pass, the largest element is at the end and it will not move anymore.
• We restart from the beginning (until the penultimate element), this time the last two elements are
well placed.
• We continue this way. There is a total of n − 1 passages if the list is of length n.
9 7 before
7 9 after
Algorithm.
• – Input: a list ` of n numbers
– Output: the ordered list from the smallest to the largest
• For i ranging from n − 1 to 0:
For j ranging from 0 to i − 1:
If `[ j + 1] < `[ j] then exchange `[ j] and `[ j + 1].
• Return the list `.
Program the bubble sort algorithm into a bubble_sort(mylist) function that returns the or-
dered list of elements. For example bubble_sort([13,11,7,4,6,8,12,6]) returns the list
[4,6,6,7,8,11,12,13].
Hints.
• Begin by defining new_mylist = list(mylist) and works only with this new list.
• For the index i to run backwards from n − 1 to 0, you can use the command :
for i in range(n-1,-1,-1):
Indeed range(a,b,-1) corresponds to the decreasing list of integers i satisfying a > i > b (as
usual the right bound is not included).
LISTS I 54
Lesson 5 (Sorting).
You can now use the sorted() function from Python which orders lists.
python : sorted()
Use: sorted(mylist)
Input: a list
Output: the ordered list of elements
Example: sorted([13,11,7,4,6,8,12,6]) returns the list
[4,6,6,7,8,11,12,13].
Attention! There is also a mylist.sort() method that works a little differently. This command returns
nothing, but on the other hand the list mylist is now ordered. We are talking about a modification in
place.
Activity 4 (Arithmetic).
Goal: improve some functions of the chapter “Arithmetic – While loop – I”.
1. Prime factors. Program a function prime_factors(n) that returns a list of all the prime factors
of an integer n > 2. For example, for n = 12 936, whose decomposition into prime factors is
n = 23 × 3 × 72 × 11, the function returns [2, 2, 2, 3, 7, 7, 11].
Hints. Consult the chapter “Arithmetic – While loop – I”. The core of the algorithm is as follows:
As long as d 6 n:
If d is a divisor of n, then:
add d to the list,
n becomes n/d.
Otherwise increment d by 1.
2. List of prime numbers. Write a function list_primes(n) that returns the list of all prime
numbers less than n. For example list_primes(100) returns the list:
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
To do this, you will program an algorithm that is a simple version of the sieve of Eratosthenes:
Algorithm.
• – Input: an integer n > 2.
– Ouput: the list of prime numbers < n.
• Initialize mylist by a list that contains all integers from 2 to n − 1.
• For d ranging from 2 to n − 1:
For k in mylist:
If d divides k and d 6= k, then remove the element k from mylist.
• Return mylist.
Hints.
• Start from mylist = list(range(2,n)).
• Use mylist.remove(k).
LISTS I 55
mylist1 = [3,5,9,8,0,3]
mylist2 = [4,7,7,2,8,9]
plt.plot(mylist1,color="red")
plt.plot(mylist2,color="blue")
plt.grid()
plt.show()
Explanations.
• The module is matplotlib.pyplot and is given the new simpler name of plt.
• Attention! The matplotlib module is not always installed by default with Python.
• plt.plot(mylist) traces the points of a list (in the form of (i, `i )) that are linked by segments.
• plt.grid() draws a grid.
LISTS I 56
To display points (x i , yi ) you must provide the list of abscissa then the list of ordinates:
plt.plot(mylist_x,mylist_y,color="red")
Here is an example of a graph obtained by displaying coordinate points of the type (x, y) with y = x 2 .
mylist_x = [2, 3, 5, 7, 9]
mylist_y = [4, 9, 25, 49, 81]
plt.plot(mylist_x,mylist_y,color="red")
plt.grid()
plt.show()
Activity 5 (Ballistics).
A cannonball has been fired from the point (0, 0). The trajectory equation is given by the formula:
1 1
y(x) = − g 2 x 2 + tan(α)x
2 v cos2 (α)
where
• α is the angle of the shot,
• v is the initial speed,
• g is the gravitational constant: we will take g = 9.81.
y(x)
v
α
(0, 0) x x
1. Program a function parabolic_shot(x,v,alpha) which returns the value y(x) given by the
formula.
Hint. Be careful with the units for the angle α. If for example you choose that the unit for the angle
is degrees, then to apply the formula with Python you must first convert the angles to radians :
2π
αradian = αdegree
360
2. Program a function list_trajectory(xmax,n,v,alpha) that calculates the list of ordinates
y of the n + 1 points of the trajectory whose abscissa are regularly spaced between 0 and x max .
Method. For i ranging from 0 to n:
x
• calculate x i = i · max
n ,
• calculate yi = y(x i ) using the trajectory formula,
• add yi to the list.
3. For v = 50, x max = 270 and n = 100, displays different trajectories according to the values of α.
What angle α allows to reach the point (x, 0) at ground level as far away from the shooting point
as possible?
PA R T I I I
A D VA N C E D C O N C E P T S
58
Chapter
8
Statistics – Data visualization
It’s good to know how to calculate the minimum, maximum, average and quartiles of a series. It’s
even better to visualize them all on the same graph!
python : sum()
Use: sum(mylist)
Input: a list of numbers
Output: a number
Example: sum([4,8,3]) returns 15
python : min()
Use: min(mylist) or min(a,b)
Input: a list of numbers or two numbers
Output: a number
Example :
• min(12,7) returns 7
• min([10,5,9,12]) returns 5
You can now use the function min(), and of course also the function max() in your programs!
STATISTICS – DATA VISUALIZATION 60
4. The variance of a data series (x 1 , x 2 , . . . , x n ) is defined as the average of the squares of deviations
from the mean. That is to say:
1
v = (x 1 − m)2 + (x 2 − m)2 + · · · + (x n − m)2
n
where m is the average of (x 1 , x 2 , . . . , x n ).
Write a function variance(mylist) that calculates the variance of the elements in a list.
For example, for the series (6, 8, 2, 10), the average is m = 6.5, the variance is
1
v = (6 − 6.5)2 + (8 − 6.5)2 + (2 − 6.5)2 + (10 − 6.5)2 = 8.75.
4
5. The standard deviation of a series (x 1 , x 2 , . . . , x n ) is the square root of the variance:
p
e= v
where v is the variance. Program a function standard_deviation(mylist). With the example
p p
above we find e = v = 8.75 = 2.95 . . .
6. Here are the average monthly temperatures (in Celsius degrees) in London and Chicago.
temp_london = [4.9,5,7.2,9.7,13.1,16.6,18.7,18.2,15.5,11.6,7.7,5.6]
temp_chicago = [-5,-2.7,2.8,9.2,15.2,20.7,23.5,22.6,18.4,12.1,4.8,-1.9]
Calculate the average temperature over the year in London and then in Chicago. Calculate the
standard deviation of the temperatures in London and then in Chicago. What conclusions do you
draw from this?
# A rectangle
canvas.create_rectangle(50,50,150,100,width=2)
canvas.create_rectangle(350,100,500,150,fill="purple")
# An ellipse
canvas.create_oval(50,110,180,160,width=4)
# Some text
canvas.create_text(400,75,text="Bla bla bla bla",fill="blue")
(0, 0) x
(x 1 , y1 )
(x 2 , y2 )
(x 1 , y1 )
(x 2 , y2 )
y
Activity 2 (Graphics).
1. Bar graphics. Write a function bar_graphics(mylist) that displays the values of a list as
vertical bars.
Hints.
• First of all, don’t worry about drawing the vertical axis of the coordinates with the figures.
• You can define a variable scale that allows you to enlarge your rectangles, so that they have
a size adapted to the screen.
• If you want to test your graph with a random list, here is how to build a random list of 10
integers between 1 and 20 :
from random import *
mylist = [randint(1,20) for i in range(10)]
2. Cumulative graph. Write a function cumulative_graphics(mylist) that displays the values
of a list in the form of rectangles one above the other.
3. Graphics with percentage. Write a function percentage_graphics(mylist) that displays the
values of a list in a horizontal rectangle of fixed size (for example 500 pixels) and is divided into
sub-rectangles representing the values.
4. Sector graphics. Write a function sector_graphics(mylist) that displays the values of a list
as a fixed size disk divided into sectors representing the values.
The create_arc() function, which allows you to draw arcs of circles, is not very intuitive. It is
necessary to think that we draw a circle, by specifying the coordinates of the corners of a square
which surrounds it, then by specifying the starting angle and the angle of the sector (in degrees).
canvas.create_arc(x1,y1,x2,y2,start=start_angle,extent=my_angle)
STATISTICS – DATA VISUALIZATION 63
extent=θ
(x 1 , y1 )
start=θ0
(x 2 , y2 )
root = Tk()
canvas = Canvas(root, width=400, height=200, background="white")
canvas.pack(fill="both", expand=True)
def action_button():
canvas.delete("all") # Clear all
colors = ["red","orange","yellow","green","cyan","blue","violet","purple"]
col = choice(colors) # Random color
canvas.create_rectangle(100,50,300,150,width=5,fill=col)
return
root.mainloop()
Some explanations:
• A button is created by the command Button. The text option customizes the text displayed on
the button. The button created is added to the window by the method pack.
• The most important thing is the action associated with the button! It is the option command that
receives the name of the function to be executed when the button is clicked. For our example
command=action_button, associate the click on the button with a change of color.
• Attention! You have to give the name of the function without brackets: commande=my_function
and not command=my_function().
• To associate the button with “Quit” and close the window, the argument is command=root.quit.
• The instruction canvas.delete("all") deletes all drawings from our graphic window.
1. Program a function median(mylist) which calculates the median value of the items of a given
list. By definition, half of the values are less than or equal to the median, the other half are greater
than or equal to the median.
Background. We note n the length of the list and we assume that the list is ordered (from the
smallest to the largest element).
• Case n odd. The median is the value of the list at the rank n−1 2 . Example with mylist =
[12,12,14,15,19]:
– the length of the list is n = 5 (indices range from 0 to 4),
– the middle index is the rank 2,
STATISTICS – DATA VISUALIZATION 65
A box plot is a diagram that represents the main characteristics of a statistical series: minimum, maximum,
median and quartiles. The schematic diagram is as follows:
Q1 median Q3
minimum maximum
Write a box_plot(grade_count) function that draws the box plot of a class’s grades from a list of a
number of students per grade (see previous activity).
STATISTICS – DATA VISUALIZATION 66
1. Simulates the stock market price of the index NISDUQ over 365 days. At the beginning, the day
j = 0, the index is equal to 1000. Then the index for a day is determined by adding a random
value (positive or negative) to the value of the previous day’s index:
index of the day j = index of the day ( j − 1) + random value.
For this random value, you can try a formula like:
value = randint(-10,12)/3
Write a function index_stock_exchange(), without parameter, which returns a list of 365 index
values using this method.
2. Trace point by point the index curve over a year. (To draw a point, you can display a square with a
size of 1 pixel.)
3. Since the daily index curve is very chaotic, we want to smooth it out in order to make it more readable.
For this we calculate moving averages.
The moving average at 7 days for the day j, is the average of the last 7 indices. For example: the
moving average (at 7 days) for the day j = 7 is the average of the day’s indices j = 1, 2, 3, 4, 5, 6, 7.
You can change the duration: for example the moving average at 30 days is the average of the last
30 indices.
Write a function moving_average(mylist,duration) that returns a list of all moving averages
in a data set with respect to a fixed time.
4. Trace point by point on the same graph: the index curve over a year (in red below), the moving
average curve at 7 days (in blue below) and the moving average curve at 30 days (in brown below).
Note that the longer the duration, the more the curve is “smooth”. (Of course the moving average
curve at 30 days only starts from the thirtieth day.)
STATISTICS – DATA VISUALIZATION 67
Chapter
9
Files
fi = open("my_file.txt","w")
fi.write("Hello world!\n")
fi.close()
Explanations.
• The command open allows you to open a file. The first argument is the name of the file. The second
argument here is "w" to say that you want to write to the file.
• We do not work with the file name, but with the value returned by the function open. Here we
have named this object file fi. It is with this variable fi that we work now.
• We now write in the file almost as we would display a sentence on the screen. The instruction is
fi.write() where the argument is a string of characters.
• To switch to the next line, you must add the line terminator character "\n".
• It is important to close your file when you are finished writing. The instruction is fi.close().
• The data to be written are strings, so to write a number, you must first transform it with
str(number).
fi = open("my_file.txt","r")
Hello world!
for line in fi:
print(line)
Hi there.
fi.close()
Explanations.
• The command open is this time called with the argument "r" (for read), it opens the file in reading.
• We work again with an object file named here fi.
• A loop goes through the entire file line by line. Here we just ask for the display of each line.
• We close the file with fi.close().
• The data read is a string, so if you want a number, you must first transform it with int(string)
(for an integer) or float(string) (for a decimal number).
1. Generates at random a grades file, named grades.txt, which is composed of lines with the
structure:
Firstname Name grade1 grade2 grade3
For example:
Hints.
• Build a list of first names list_firstnames = ["Alice","Tintin","James",...].
Then choose a first name at random by the instruction firstname =
choice(list_firstnames) (you have to import the module random).
• Same thing for names!
• For a grade, you can choose a random number with the command randint(a,b).
• Please note! Don’t forget to convert the numbers into a string to write it to the file:
str(grade).
2. Read the file grades.txt that you produced. Calculate the average of each person’s grades and
write the result to a file averages.txt where each line is of the form:
Firstname Name average
For example:
FILES 70
Hints.
• For each line read from the file grades.txt, you get the data as a list by the command
line.split().
• Please note! The data read is a string. You can convert a string "12.5" to the number 12.5
by the instruction float(string).
• To convert a number to a string with only two decimal places after the dot, you can use the
command '{0:.2f}'.format(number).
• Don’t forget to close all your files.
CURIE,Marie,1867,1.55,2
EINSTEIN,Albert,1879,1.75,1
NOBEL,Alfred,1833,1.70,0
Goal: write a data file, with csv format, then read it for a graphic display.
1. Generates a sales.csv file of sales figures (randomly drawn) from a sports brand.
Here is an example:
,2015,2016,2017,2018,2019,2020
Mountain bike,560,890,500,550,650,970
Surfboard,550,690,750,640,710,790
Running shoes,850,740,790,1000,680,540
Badminton racket,710,640,620,550,790,880
Volley ball,900,550,790,510,930,800
• The produced file respects the format csv and must be readable by LibreOffice Calc for example.
Hints.
• The matplotlib package allows you to easily display graphics, it is often called with the
instruction:
import matplotlib.pyplot as plt
• Here is how to view two data lists mylist1 and mylist2:
plt.plot(mylist1)
plt.plot(mylist2)
plt.grid()
plt.show()
P1
4 5
1 1 1 1
1 0 0 0
1 1 1 0
1 0 0 0
1 1 1 1
P2
4 5
255
0 0 0 0
192 192 192 192
192 255 128 128
192 255 64 64
192 0 0 0
P3
3 2
255
255 0 0 0 255 0 0 0 255
0 128 255 255 128 0 128 255 0
1. Generate a file image_bw.pbm that represents a black and white image (e.g. of size 300 × 200)
according to the following pattern:
Hints. If i designates the line number and j the column number (from the top left), then the pixel
in position (i, j) is white if i + j is between 0 and 9, or between 20 and 29, or between 40 and
49,. . . This is obtained by the formula :
col = (i+j)//10 % 2
which returns 0 or 1 as desired.
2. Generate a file image_gray.pgm that represents a grayscale image (for example of size 200 × 200
with 256 grayscale) according to the following pattern:
5. Write a function colors_to_gray(filename) that reads a color image file in .ppm format and
creates a new file in .pgm format in which the color pixels are transformed into grayscale.
You can use the formula:
g = 0, 21 × R + 0, 72 × G + 0, 07 × B
where
• R, G, B are the red, green and blue levels of the colored pixel,
• g is the grayscale of the transformed pixel.
Example: on the left the starting image in color, on the right the arrival image in grayscale.
The formula for the distance between two points (x 1 , y1 ) and (x 2 , y2 ) of the plan is:
Æ
d = (x 2 − x 1 )2 + ( y2 − y1 )2 .
Example. Here is an example of an input file:
We read on this file that the distance between Lille and Marseille is 1077 kilometers.
Below is the map of France that provided (very approximate) data for the input file. The origin is
at the bottom left, each side of a square represents 100 km. For example, in this reference, Paris
has the coordinates (500, 800).
Lille
Strasbourg
Paris
Nantes
Lyon
Bordeaux
Toulouse
(0, 0) Marseille
100 km
Our study of numbers is further developed with the loop “while”. For this chapter you need your
function is_prime() built in the part “Arithmetic – While loop – I”.
Conjecture: Between 1 and N , there are more integers that have exactly 4 divisors than integers that have
exactly 8 divisors.
ARITHMETIC – WHILE LOOP – II 78
You will see that this conjecture looks true for N rather small, but you will show that this conjecture is
false by finding a large N that contradicts this statement.
1. Number of divisors.
Program a function number_of_divisors(n) that returns the number of integers dividing n.
For example: number_of_divisors(100) returns 9 because there are 9 divisors of n = 100 :
1, 2, 4, 5, 10, 20, 25, 50, 100
Hints.
• Don’t forget 1 and n as divisors.
• Try to optimize your function because you will use it intensively: for example, there are no
divisors strictly larger than 2n (except n).
2. 4 or 8 divisors.
Program a function four_and_eight_divisors(Nmin,Nmax) that returns two numbers: (1)
the number of integers n with Nmin 6 n < Nmax that admit exactly 4 divisors and (2) the number
of integers n with Nmin 6 n < Nmax that admit exactly 8 divisors.
For example four_and_eight_divisors(1,100) returns (32,10) because there are 32 inte-
gers between 1 and 99 that admit 4 divisors, but only 10 integers that admit 8.
3. Proof that the conjecture is false.
Experiment that for “small” values of N (up to N = 10 000 for example) there are more integers
with 4 divisors than 8. But calculate that for N = 300 000 this is no longer the case.
Hints. As there are many calculations, you can split them into slices (the slice of integers 1 6
n < 50 000, then 50 000 6 n < 100 000,...) and then add them up. This allows you to share your
calculations between several computers.
Hint. In the list you must find U136 (which is a prime number) but also U34 which is not prime but
whose smallest divisor is 10 149 217 781.
Let n > 0 be an integer. The integer square root of n is the largest integer r > 0 such as r 2 6 n. Another
p
definition is to say that the integer square root of n is the integer part of n.
Examples:
• n = 21, then the integer square root of n is 4 (because 42 6 21, but 52 > 21). In other words,
p
21 = 4.58 . . ., and we only keep the integer part (the integer to the left of the dot), so it is 4.
• n = 36, then the integer square root of n is 6 (because 62 6 36, but 72 > 36). In other words,
p
36 = 6 and the integer square root is of course also 6.
p
1. Write a first function that calculates the integer square root of an integer n, first calculating n,
then taking the integer part.
Hints.
• For this question only, you can use the module math of Python.
• In this module sqrt() returns the real square root.
• The function floor() of the same module returns the integer part of a number.
2. Write a second function that calculates the integer square root of an integer n, but this time
according to the following method:
• Start with p = 0.
• As long as p2 6 n, increment the value of p by 1.
Test carefully what the returned value should be (beware of the offset!).
3. Write a third function that still calculates the integer square root of an integer n with the algorithm
described below. This algorithm is called the Babylonian method (or Heron’s method or Newton’s
method).
Algorithm.
Input: a positive integer n
Output: its integer square root
• Start with a = 1 and b = n.
• as long as |a − b| > 1:
– a ← (a + b)//2 ;
– b ← n//a
• Return the minimum between a and b: this is the integer square root of n.
We do not explain how this algorithm works, but it is one of the most effective methods to calculate
square roots. The numbers a and b provide, during execution, an increasingly precise interval
p
containing of n.
Here is a table that details an example calculation for the integer square root of n = 1664.
ARITHMETIC – WHILE LOOP – II 80
Step a b
i=0 a=1 b = 1664
i=1 a = 832 b=2
i=2 a = 417 b=3
i=3 a = 210 b=7
i=4 a = 108 b = 15
i=5 a = 61 b = 27
i=6 a = 44 b = 37
i=7 a = 40 b = 41
In the last step, the difference between a and b is less than or equal to 1, so the integer square
root is 40. We can verify that this is correct because: 402 = 1600 6 1664 < 412 = 1681.
Bonus. Compare the execution speeds of the three methods using timeit(). See the chapter “Functions”.
Example.
Here are different codes for a countdown from 10 to 0.
# Better (with a flag)
# Countdown
n = 10 # Even better
n = 10
finished = False # (reformulation)
while True: # Infinite loop
while not finished: n = 10
print(n)
print(n) while n >= 0:
n = n - 1
n = n - 1 print(n)
if n < 0:
if n < 0: n = n - 1
break # Immediate stop
finished = True
Example.
Here are programs that search for the integer square root of 777, i.e. the largest integer i that satisfies
i 2 6 777. In the script on the left, the search is limited to integers i between 0 and 99.
# Integer square root # Better
n = 777 n = 777
for i in range(100): i = 0
if i**2 > n: while i**2 <= n:
break i = i + 1
print(i-1) print(i-1)
ARITHMETIC – WHILE LOOP – II 81
Example.
Here are programs that calculate the real square roots of the elements in a list, unless of course the
number is negative. The code on the left stops before the end of the list, while the code on the right
handles the problem properly.
# Better with try/except
# Square root of the elements
mylist = [3,7,0,10,-1,12]
# of a list
for element in mylist:
mylist = [3,7,0,10,-1,12]
try:
for element in mylist:
print(sqrt(element))
if element < 0:
except:
break
print("Warning, I don't know how to
print(sqrt(element))
compute the square root of",element)
Chapter
Binary I
11
The computers transform all data into numbers and manipulate only those numbers. These numbers
are stored in the form of lists of 0’s and 1’s. It’s the binary numeral system of numbers. To better
understand this binary numeral system, you will first understand the decimal numeral system better.
We calculate the integer corresponding to the digits [d p−1 , d p−2 , . . . , d2 , d1 , d0 ] by the formula :
n = d p−1 × 10 p−1 + d p−2 × 10 p−2 + · · · + di × 10i + · · · + d2 × 102 + d1 × 101 + d0 × 100
decimal_to_integer()
Use: decimal_to_integer(list_decimal)
Input: a list of numbers between 0 and 9
Output: the integer whose decimal notation is the list
Example: if the input is [1,2,3,4], the output is 1234.
where p is the length of the list and di is the digit at rank i counting from the end (i.e. from right to left).
To manage the fact that the index i used for the power of 10 does not correspond to the rank in the list,
there are two solutions:
• understand that di = mylist[p − 1 − i] where mylist is the list of p digits,
• or start by reversing mylist.
Lesson 2 (Binary).
• Power of 2. We note 2k for 2 × 2 × · · · × 2 (with k factors). For example, 23 = 2 × 2 × 2 = 8.
27 26 25 24 23 22 21 20
128 64 32 16 8 4 2 1
We calculate the integer corresponding to the bits [b p−1 , b p−2 , . . . , b2 , b1 , b0 ] as a sum of terms
bi × 2i , by the formula :
n = b p−1 × 2 p−1 + b p−2 × 2 p−2 + · · · + bi × 2i + · · · + b2 × 22 + b1 × 21 + b0 × 20
• Python and the binary. Python accepts that we directly write the integers in binary numeral
system, just use the prefix “0b”. Examples:
– with x = 0b11010, then print(x) displays 26,
– with y = 0b11111, then print(y) displays 31,
– and print(x+y) displays 57.
1. Calculate integers whose binary numeral system is given below. You can do it by hand or help
yourself from Python. For example 1.0.0.1.1 is equal to 24 + 21 + 20 = 19 as confirmed by the
command 0b10011 which returns 19.
• 1.1, 1.0.1, 1.0.0.1, 1.1.1.1
• 1.0.0.0.0, 1.0.1.0.1, 1.1.1.1.1
• 1.0.1.1.0.0, 1.0.0.0.1.1
BINARY I 84
• 1.1.1.0.0.1.0.1
2. Write a function binary_to_integer(list_binary) which from a list representing binary
system calculates the corresponding integer.
binary_to_integer()
Use: binary_to_integer(list_binary)
Input: a list of bits, 0 and 1
Output: the integer whose binary numeral system is the list
Examples:
• input [1,1,0], output 6
• input [1,1,0,1,1,1], output 55
• input [1,1,0,1,0,0,1,1,0,1,1,1], output 3383
Algorithm.
Input: mylist : a list of 0 and 1
Output: the associated binary number
• Initialize a variable n to 0.
• For each element b from mylist :
– if b is 0, then make n ← 2n,
– if b is 1, then make n ← 2n + 1.
• The result is the value of n.
quotient
123
10 1234
remainder
4
integer_to_decimal()
Use: integer_to_decimal(n)
Input: a positive integer
Output: the list of its digits
Example: if the input is 1234, the output is [1,2,3,4].
Algorithm.
Input: an integer n > 0
Output: the list of its digits
• Start from an empty list.
• As long as n is not zero:
– add n%10 at the beginning of the list,
– make n ← n//10.
• The result is the list.
BINARY I 86
python : bin()
Use: bin(n)
Input: an integer
Output: the binary numeral system of n in the form of a string starting with
'0b'
Example:
• bin(37) returns '0b100101'
• bin(139) returns '0b10001011'
Example.
Calculation of the binary notation of 14.
• We divide 14 by 2, the quotient is 7, the remainder is 0.
• We divide 7 (the previous quotient) by 2: the new quotient is 3, the new remainder is 1.
• We divide 3 by 2: quotient 1, remainder 1.
• We divide 1 by 2: quotient 0, remainder 1.
• It’s over (the last quotient is zero).
• The successive remainders are 0, 1, 1, 1. we read the binary numeral system backwards, it is
1.1.1.0.
The divisions are done from left to right, but the remainders are read from right to left.
7 3 1 0
2 14 2 7 2 3 2 1
0 1 1 1
Example.
Binary system of 50.
25 12 6 3 1 0
2 50 2 25 2 12 2 6 2 3 2 1
0 1 0 0 1 1
Activity 4.
1. Calculate by hand the binary numeral system of the following integers. Check your results using
the bin() Python function.
• 13, 18, 29, 31,
• 44, 48, 63, 64,
• 100, 135, 239, 1023.
2. Program the following algorithm into a function integer_to_binary().
BINARY I 88
Algorithm.
Input: an integer n > 0
Output: its binary numeral system in the form of a list
• Start from an empty list.
• As long as n is not zero:
– add n%2 at the beginning of the list,
– make n ← n//2.
• The result is the list.
integer_to_binary()
Use: integer_to_binary(n)
Input: a positive integer
Output: its binary notation in the form of a list
Example: if the input is 204, the output is [1,1,0,0,1,1,0,0].
12
Lists II
The lists are so useful that you have to know how to handle them in a simple and efficient way. That’s
the purpose of this chapter!
– The command mylist_doubles = [ 2*x for x in mylist ] returns a list that con-
tains the double of each item of the mylist list. So this is the list [2,4,6,8,...].
– The command mylist_squares = [ x**2 for x in mylist ] returns the list of
squares of the items in the initial list. So this is the list [1,4,9,16,...].
– The command mylist_partial = [x for x in mylist if x > 2] extracts the list
composed only of elements strictly greater than 2. So this is the list [3,4,5,6,7,6,5,4,3].
• List of lists.
A list can contain other lists, for example:
mylist = [ ["Harry", "Hermione", "Ron"], [101,103] ]
contains two lists. We will be interested in lists that contain lists of integers, which we will call
arrays. For example:
array = [ [2,14,5], [3,5,7], [15,19,4], [8,6,5] ]
Then array[i] returns the sublist of rank i, while array[i][j] returns the integer located at
the rank j in the sublist of rank i. For example:
– array[0] returns the list [2,14,5],
– array[1] returns the list [3,5,7],
– array[0][0] returns the integer 2,
– array[0][1] returns the integer 14,
– array[2][1] returns the integer 19.
Goal: practice list comprehension. In this activity the lists are lists of integers.
1. Program a function multiplication(mylist,k) that multiplies each item in the list by k. For
example, multiplication([1,2,3,4,5],2) returns [2,4,6,8,10].
2. Program a function power(mylist,k) that raises each element of the list to the power k. For
example, power([1,2,3,4,5],3) returns [1,8,27,64,125].
3. Program a function addition(mylist1,mylist2) that adds together the elements of two lists
of the same length. For example, addition([1,2,3],[4,5,6]) returns [5,7,9].
Hint. This one is an example of a task where lists comprehension is not used!
4. Program a function non_zero(mylist) that returns a list of all non-zero elements. For example,
non_zero([1,0,2,3,0,4,5,0]) returns [1,2,3,4,5].
5. Program a function even(mylist) that returns a list of all even elements. For example,
even([1,0,2,3,0,4,5,0]) returns [0,2,0,4,0].
display numbers and their position for verification). For the example given the function returns
False.
2. Program a function sum_two_100(mylist) that tests if there are two items in the list, located at
different positions, whose sum is equal to 100. For the example given the function returns True
and can display the integers 2 and 98 (at ranks 1 and 6 of the list).
3. Program a function sum_seq_100(mylist) that tests if there are consecutive elements in the
list whose sum is equal to 100. For the example given the function returns True and can display
the sequence of integers 25, 26, 49 (at ranks 11, 12 and 13).
4. (Optional.) The larger the size of the list, the more likely it is to get the total of 100. For each of
the three previous situations, determines from which size n of the list, the probability of obtaining
a sum of 100 is greater than 1/2.
Hints. For each case, you get an estimate of this integer n, by writing a function proba(n,N) that
performs a large number N of random draws of lists having n items (with for example N = 10 000).
The probability is approximated by the number of favorable cases (where the function returns
true) divided by the total number of cases (here N ).
Activity 3 (Arrays).
In this activity we work with arrays of size n × n containing integers. The object array is therefore a list
of n lists, each having n elements.
For example (with n = 3):
array = [ [1,2,3], [4,5,6], [7,8,9] ]
represents the array:
1 2 3
4 5 6
7 8 9
1. Write a function sum_diagonal(array) that calculates the sum of the elements located on the
main diagonal of an array. The main diagonal of the example given is 1, 5, 9, so the sum is 15.
2. Write a function sum_antidiagonal(array) that calculates the sum of the elements located on
the other diagonal. The anti-diagonal of the example given is composed of 3, 5, 7, the sum is still
15.
3. Write a function sum_all(array) that calculates the total sum of all elements. For the example
the total sum is 45.
4. Write a function print_array(array) that displays an array properly on the screen. You can
use the command:
print('{:>3d}'.format(array[i][j]), end="")
Explanations.
• The command print(string,end="") allows you to display a string of characters without
going to the next line.
• The command '{:>3d}'.format(k) displays the integer k on three characters (even if
there is only one digit to display).
Goal: build magic squares as big as you want! You must first have done the previous activity.
LISTS II 92
A magic square is a square array of size n × n that contains all integers from 1 to n2 and satisfies that: the
sum of each row, the sum of each column, the sum of the main diagonal and the sum of the anti-diagonal
all have the same value.
Here is an example of a magic square with a size of 3 × 3 and one of size 4 × 4.
1 14 15 4 34
4 9 2 15
7 9 6 12 34
3 5 7 15
10 8 11 5 34
8 1 6 15
16 3 2 13 34
15 15
15 15 15
34 34
34 34 34 34
Algorithm.
• – Inputs: a magic square C1 of size n × n and a magic square C2 of size m × m.
– Output: a magic square C of size (nm) × (nm).
Set the square C3a by subtracting 1 from all elements of C2 . (Use the command
addition_square(square2,-1).)
• Define the square C3b as the homothety of the square C3a of ratio n. (Use the command
homothety(square3a,n).)
• Define the square C3c by multiplying all the terms of the square C3b by n2 . (Use the
command multiplication_square(square3b,n**2).)
• Define the square C3d by adding the square C1 to the square C3c per block. (Use the
command block_addition_square(square3c,square1).)
• Return the square C3d .
Binary II
13
Activity 1 (Palindromes).
In English a palindrome is a word (or a sentence) that can be read in both directions, for example
“RADAR” or “A MAN, A PLAN, A CANAL: PANAMA”. In this activity, a palindrome will be a list, which
has the same elements when browsing from left to right or right to left.
Examples:
• [1,0,1,0,1] is a palindrome (with binary numeral system),
• [2,9,4,4,9,2] is a palindrome (with decimal numeral system).
1. Program a function is_palindrome(mylist) that tests if a list is a palindrome or not.
Hints. You can compare the items at ranks i and p − 1 − i or use list(reversed(liste)).
2. We are looking for integers n such that their binary numeral system is a palindrome. For example,
the binary notation of n = 27 is the palindrome [1,1,0,1,1]. This is the tenth integer n having
this property.
What is the thousandth integer n > 0 whose binary notation is a palindrome?
3. What is the thousandth integer n > 0 whose decimal notation is a palindrome?
For example, the digits of n = 909 in decimal notation, form the palindrome [9,0,9]. This is the
hundredth integer n having this property.
4. An integer n is a bi-palindrome if its binary notation and its decimal notation are palindromes.
For example n = 585 has a decimal notation which is a palindrome and also is its binary notation
[1,0,0,1,0,0,1,0,0,1]. This is the tenth integer n having this property.
What is the twentieth integer n > 0 to be a bi-palindrome?
– 0 AND 0 = 0
– 0 AND 1 = 0
– 1 AND 0 = 0
– 1 AND 1 = 1
• The logical operation “NOT”, exchange true and false values:
– NOT 0 = 1
– NOT 1 = 0
• For numbers in binary notation, these operations range from bits to bits, i.e. digit by digit (starting
with the digits on the right) as one would add (without carry).
For example:
1.0.1.1.0 1.0.0.1.0
AND 1.1.0.1.0 OR 0.0.1.1.0
1.0.0.1.0 1.0.1.1.0
If the two systems do not have the same number of bits, we add non-significant 0 on the left
(example of 1.0.0.1.0 OR 1.1.0 on the figure at the right).
1. (a) Program a function NOT() which corresponds to the negation for a given list. For example,
NOT([1,1,0,1]) returns [0,0,1,0].
(b) Program a function OReq() which corresponds to “OR” with two lists of equal length. For
example, with mylist1 = [1,0,1,0,1,0,1] and mylist2 = [1,0,0,1,0,0,1], the
function returns [1,0,1,1,1,0,1].
(c) Do the same work with ANDeq() for two lists having the same length.
2. Write a function zero_padding(mylist,p) that adds zeros at the beginning of the list to
get a list of length p. Example: if mylist = [1,0,1,1] and p = 8, then the function returns
[0,0,0,0,1,0,1,1].
3. Write two functions OR() and AND() which correspond to the logical operations, but with two
lists that do not necessarily have the same length.
Example:
• mylist1 = [1,1,1,0,1] and mylist2 = [1,1,0],
• it should be considered that mylist2 is equivalent to the list mylist2bis = [0,0,1,1,0]
of the same length as mylist1,
• so OR(mylist1,mylist2) returns [1,1,1,1,1],
• then AND(mylist1,mylist2) returns [0,0,1,0,0] (or [1,0,0] depending on your
choice).
Hints. You can take over the content of your functions OReq and ANDeq, or you can first add zeros
to the shortest list.
BINARY II 97
Algorithm.
Use: every_binary_number(p)
Input: an integer p > 0
Output: the list of all possible lists of 0 and 1 of length p
• If p = 1 return the list [ [0], [1] ].
• If p > 2, then:
– get all lists of size p-1 by the call every_binary_number(p-1)
– for each item in this list, build two new items:
– on the one hand add 0 at the beginning of this element;
– on the other hand add 1 at the beginning of this element;
– then add these two items to the list of lists of size p.
• Return the list of all the lists with a size p.
3. De Morgan’s laws.
De Morgan’s laws state that for booleans (true/false) or bits (1/0), we always have these properties:
NOT(b1 OR b2 ) = NOT(b1 ) AND NOT(b2 ) NOT(b1 AND b2 ) = NOT(b1 ) OR NOT(b2 ).
Experimentally checks that these equations are still true for any list `1 and `2 of exactly 8 bits.
PA R T I V
PROJECTS
98
Chapter
Probabilities – Par-
rondo’s paradox
14
You will program two simple games. When you play these games, you are more likely to lose than to
win. However, when you play both games at the same time, you have a better chance of winning
than losing! It’s a paradoxical situation.
Goal: model a first simple game, which on average makes the player loses.
Game A. In this first game, we throw a slightly unbalanced coin: the player wins one dollar in 49 cases
on 100; he loses one dollar in 51 cases on 100.
1. One draw. Write a function throw_game_A() that does not depend on any argument and that
models a draw of the game A. For this purpose:
• Pick a random number 0 6 x < 1 using the random() function of the random module.
• Returns +1 if x is smaller than 0.49; and −1 otherwise.
2. Gain. Write a function gain_game_A(N) that models N draws from game A and returns the total
winnings of these draws. Of course, the result depends on the actual runs, it can vary from one
time to another.
3. Expected value. Write a function expected_value_game_A(N) that returns an estimate of the
expected value of the game A according to the formula:
winnings afters N throws
expected value ' with large N .
N
4. Conclusion.
(a) Estimate the expected value by making at least one million draws.
(b) What does it mean that the expected value is negative?
(c) Deduct from the value of the expected value, the win (or loss) that I can expect by playing
1000 times in game A.
random). At the beginning the player starts with a zero win: g = 0. At each step, he chooses at random
(50% of luck each):
• to play game A once,
• or to play game B once; more precisely with subgame B1 or subgame B2 depending on the win
already acquired g.
1. One draw. Write a throw_game_AB(g) function that depends on the win already acquired and
models a draw of the AB game.
2. Gain. Write a function gain_game_AB(N) that models N draws from the AB game (starting from
a zero initial gain) and returns the total gain of these draws.
3. Expected value. Write a function expected_value_game_AB(N) that returns an estimate of the
expected value of the AB game.
4. Conclusion.
(a) Estimate the expected value by performing at least one million game turns.
(b) What can we say this time about the sign of expected value?
(c) How much can I expect to win or lose by playing AB game 1000 times? Surprising, isn’t it?
Reference: “Parrondo’s paradox”, Hélène Davaux, La gazette des mathématiciens, July 2017.
Chapter
Finding and replacing are two very frequent tasks. Knowing how to use them and how they work
will help you to be more effective.
Activity 1 (Find).
Activity 2 (Replace).
2. Write your own function myreplace() which you will call in the following form:
myreplace(string,substring,new_substring)
and which only replaces the first occurrence of substring found. For example,
myreplace("ABBA","B","XY") returns "AXYBA".
Hint. You can use your myfind() function from the previous activity to find the starting position
of the sequence to replace.
3. Improve your function to build a function replace_all() which now replaces all occurrences
encountered.
def python_regex_find(string,exp):
pattern = search(exp,string)
if pattern:
return pattern.group(), pattern.start(), pattern.end()
else:
return None
Program it and test it. It returns: (1) the found substring, (2) the start position and (3) the end position.
FIND AND REPLACE 104
Example.
Apply the transformation 01 → 10 to the sentence 10110.
We read the sentence from left to right, we find the first pattern 01 from the second letter, we replace
it with 10:
1(01)10 7−→ 1(10)10
We can start again from the beginning of the sentence obtained, with always the same transformation
01 → 10:
11(01)0 7−→ 11(10)0
The pattern 01 no longer appears in the sentence 11100 so the transformation 01 →10 now leaves
this sentence unchanged.
Let’s summarize: here is the effect of the iterated transformation 01 → 10 in the sentence 10110:
10110 7−→ 11010 7−→ 11100
Example.
Apply the transformation 001 →1100 to the sentence 0011.
A first time:
(001)1 7−→ (1100)1
A second time:
11(001) 7−→ 11(1100)
And then the transformation no longer modifies the sentence.
Example.
Let’s see a last example with the transformation 01 →1100 for the starting sentence 0001:
0001 7−→ 001100 7−→ 01100100 7−→ 1100100100 7−→ · · ·
We can iterate the transformation, to obtain longer and longer sentences.
We consider here only transformations of the type 0a 1 b →1c 0d , i.e. a pattern with first 0’s then 1’s is
replaced by a pattern with first 1’s then 0’s.
1. One iteration.
Using your myreplace() function from the first activity, check the above examples. Make sure
you replace only one pattern at each step (the leftmost one).
Example: the transformation 01 → 10 applied to the sentence 101, is calculated by
myreplace("101","01","10") and returns "110".
2. Multiple iterations.
Program a function iterations(sentence,pattern,new_pattern) that, from a sentence,
iterates the transformation. Once the sentence is stabilized, the function returns the number of
iterations performed and the resulting sentence. If the number of iterations does not seem to stop
(for example when it exceeds 1000) then returns None.
Example. For the transformation 0011 → 1100 and the sentence 00001101, the sentences obtained
FIND AND REPLACE 106
are:
000011011 7−→ 001100011 7−→ 110000011 7−→ 110001100 7−→ 110110000 7−→ ···
1 2 3 4
For this example, the call to the iterations() function returns 4 (the number of transformations
before stabilization) and "110110000" (the stabilized sentence).
3. The most iterations possible.
Program a function max_iterations(p,pattern,new_pattern) which, among all the sen-
tences of length p, is looking for one of those that takes the longest to stabilize. This function
returns:
• the maximum number of iterations,
• a sentence that achieves this maximum,
• and the corresponding stabilized sentence.
Example: for the transformation 01 → 100, among all the sentences of length p = 4, the maximum
number of possible iterations is 7. Such an example of a sentence is 0111, which will stabilize (after
7 iterations) in 11100000000. So the command max_iteration(4,"01","100") returns:
7, '0111', '11100000000'
Hint. To generate all sentences with a length of p formed of 0 and 1, you can consult the chapter
“Binary II” (activity 3).
4. Categories of transformations.
• Linear transformation. Experimentally check that the transformation 0011 →110 is linear,
i.e. for all sentences with a length of p, there will be at most about p iterations before
stabilization. For example, for p = 10, what is the maximum number of iterations?
• Quadratic transformation. Experimentally check that the transformation 01 →10 is
quadratic, i.e. for all sentences with a length of p, there will be at most about p2 iterations
before stabilization. For example, for p = 10, what is the maximum number of iterations?
• Exponential transformation. Experimentally check that the transformation 01 →110 is
exponential, i.e. for all sentences with a length of p, there will be a finite number of iterations,
but that this number can be very large (much larger than p2 ) before stabilization. For example,
for p = 10, what is the maximum number of iterations?
• Transformation without end. Experimentally verify that for the transformation 01 →1100,
there are sentences that will never stabilize.
Chapter
16
Polish calculator – Stacks
You’re going to program your own calculator! For that you will discover a new notation for formulas
and also discover what a “stack” is in computer science.
Lesson 1 (Stack).
A stack is a sequence of data with three basic operations:
• push: you add an element to the top of the stack,
• pop: the value of the element at the top of the stack is read and this element is removed from the
stack,
• and finally, we can test if the stack is empty.
"Because"
Top of the stack
"Unless"
"If"
6 "While"
11 "Still"
3 "As"
7 "When"
b
pop()
J push(J) return the value (here "b")
J b
A A k k
Z Z s s
U Push U x Pop x
Remarks.
• Analogy. You can make the connection with a stack of plates. You can put plates on a stack one by
one. You can remove the plates one by one, starting of course with the top one. In addition, it must
be considered that on each plate is drawn a data (a number, a character, a string . . . ).
• Last in, first out. In a queue, the first one to wait is the first one to be served and comes out. Here
it’s the opposite! A stack works on the principle of “last in, first out”.
• In a list, you can directly access any element; in a stack, you can only directly access the element at
the top of the stack. To access the other elements, you have to pop several times.
POLISH CALCULATOR – STACKS 108
• The advantage of a stack is that it is a very simple data structure that corresponds well to what
happens in a computer’s memory.
Goal: define the three (very simple) commands to use the stacks.
In this chapter, a stack will be modeled by a list. The item at the end of the list is the top of the stack.
7
11
2
stack = [4,2,11,7]
4
The stack will be stored in a global variable stack. It is necessary to start each function that modifies
the stack with the command:
global stack
1. Write a function push_to_stack() that adds an element to the top of the stack.
push_to_stack()
Use: push_to_stack(item)
Input: an integer, a string. . .
Output: nothing
Action: the stack contains an additional element
Example: if at the beginning stack = [5,1,3] then, after the instruction
push_to_stack(8), the stack is [5,1,3,8] and if you continue with the
instruction push_to_stack(6), the stack is now [5,1,3,8,6].
POLISH CALCULATOR – STACKS 109
2. Write a function pop_from_stack(), without parameters, that removes the element at the top
of the stack and returns its value.
pop_from_stack()
Use: pop_from_stack()
Input: nothing
Output: the element at the top of the stack
Action: the stack contains one less element
Example: if initially stack = [13,4,9] then the instruction
pop_from_stack() returns the value 9 and the stack is now [13,4]; if
you execute a new instruction pop_from_stack(), it returns this time the
value 4 and the stack is now [13].
3. Write a function is_stack_empty(), without parameter, that tests if the stack is empty or not.
is_stack_empty()
Use: is_stack_empty()
Input: nothing
Output: true or false
Action: does nothing on the stack
Example:
• if stack = [13,4,9] then the instruction is_stack_empty() re-
turns False,
• if stack = [] then the instruction is_stack_empty() returns
True.
python: split()
Use: string.split(separator)
Input: a string string and possibly a separator separator
Output: a list of strings
Example :
• "To be or not to be.".split() returns ['To', 'be',
'or', 'not', 'to', 'be.']
• "12.5;17.5;18".split(";") returns ['12.5', '17.5', '18']
2. The function join() is a Python method that gathers a list of strings into a single string. This is
the opposite of split().
python: join()
Use: separator.join(mylist)
Input: a list of strings mylist and a separator separator
Output: a string
Example :
• "".join(["To", "be", "or", "not", "to", "be."]) returns
'Tobeornottobe.' Spaces are missing.
• " ".join(["To", "be", "or", "not", "to", "be."]) re-
turns 'To be or not to be.' It’s better when the separator is a
space.
• "--".join(["To", "be", "or", "not", "to", "be."])
returns 'To--be--or--not--to--be.'
3. The function isdigit() is a Python method that tests if a string contains only numbers. This allows
to test if a string corresponds to a positive integer. Here are some examples: "1776".isdigit()
returns True; "Hello".isdigit() returns False.
Remember that you can convert a string into an integer by the command int(string). The
following small program tests if a string can be converted into a positive integer:
mystring = "1776" # A string
if mystring.isdigit():
myinteger = int(mystring) # myinteger is an integer
else: # Problem
print("I don't know how to convert this string to an integer!")
7 W 13 G S 5
Unsorted train.
POLISH CALCULATOR – STACKS 111
The stationmaster wants to separate the wagons: first all the blues and then all the reds (the order of the
blue wagons does not matter, the order of the red wagons either).
7 5 13 W S G
Sorted train.
For this purpose, there is an output station and a waiting area: a wagon can either be sent directly to the
output station or temporarily stored in the waiting area.
7 W 13 G S 5
Waiting area
Phase 1
Waiting area
7 13 5
Phase 2
S
G
W
POLISH CALCULATOR – STACKS 112
Here is how we will model the train and its waiting area.
• The train is a string of characters made up of a series of numbers (blue wagons) and letters (red
wagons) separated by spaces. For example train = "G 6 Z J 14".
• The list of wagons is obtained by asking train.split().
• We test if a wagon is blue and check if it is marked with a number, by the function
wagon.isdigit().
• The train reconstructed by the sorted wagons is also a string of characters. At first, it is the empty
string.
• The waiting area will be the stack. At the beginning the stack is empty. We’re only going to add the
red wagons. At the end, the stack is drained towards the tail end of the reconstituted train.
Following the station manager’s instructions and using stack operations, write a sort_wagons() function
that separates the blue and red wagons from a train.
sort_wagons()
Use: sort_wagons(train)
Input: a string with blue wagons (numbers) and red wagons (letters)
Output: blue wagons first and red wagons second.
Action: use a stack
Example :
• sort_wagons("A 4 C 12") returns "4 12 C A"
• sort_wagons("K 8 P 17 L B R 3 10 2 N") returns "8 17 3
10 2 N R B L P K"
• When you meet a first operator (+, ×, . . . ) you calculate the operation with the two members just
before this operator:
2 8 +
| {z } 6 11 + ×
2+8
POLISH CALCULATOR – STACKS 113
Other examples:
• 8 2 ÷ 3 × 7 +
8 2 ÷
| {z } 3 × 7 + becomes 4 3 ×
| {z } 7 + becomes 12 7 + that is equal to 19
8÷2=4 4×3=12
• 11 9 4 3 + − ×
11 9 4 3 +
| {z } − × becomes 11 | 7 −
9 {z } × becomes 11 2 × that is equal to 22
4+3=7 9−7=2
Exercise. Calculates the value of expressions:
• 13 5 + 3 ×
• 3 5 7 × +
• 3 5 7 + ×
• 15 5 ÷ 4 12 + ×
1. Write a function operation() that calculates the sum or product of two numbers.
operation()
Use: operation(a,b,op)
Input: two numbers a and b, one operation character "+" or "*"
Output: the result of the operation a + b or a * b
Example:
• operation(2,4,"+") returns 6
• operation(2,4,"*") returns 8
Algorithm.
• – Input: an expression in Polish notation (a string).
– Output: the value of this expression.
– Example: "2 3 + 4 *" (the calculation (2 + 3) × 4) returns 20.
• Start with an empty stack.
• For each element of the expression (read from left to right):
– if the element is a number, then add this number to the stack,
– if the element is an operation character, then:
– pop the stack once to get a number b,
– pop a second time to get a number a,
– calculate a + b or a × b depending on the operation,
– push this result to the stack.
• At the end, the stack contains only one element, it is the result of the calculation.
polish_calculator()
Use: polish_calculator(expression)
Input: an expression in Polish notation (a string)
Output: the result of the calculation
Action: uses a stack
Example:
• polish_calculator("2 3 4 + +") returns 9
• polish_calculator("2 3 + 5 *") returns 25
Here are some examples of well and bad balanced bracketed expressions:
• 2 + (3 + b) × (5 + (a − 4)) is well balanced parenthesized;
• (a + 8) × 3) + 4 is incorrectly bracketed: there is a closing bracket “)” alone;
• (b + 8/5)) + (4 is incorrectly bracketed: there are as many opening parentheses “(” than closing
parentheses “)” but they are badly positioned.
1. Here is the algorithm that decides if the parentheses of an expression are well placed. The stack
acts as an intermediate storage area for opening parenthesis "(". Each time we find a closing
parenthesis ")" in the expression we delete an opening parenthesis from the stack.
POLISH CALCULATOR – STACKS 115
Algorithm.
Input: any expression (a string).
Output: “True” if the parentheses are well balanced, “False” otherwise.
• Start with an empty stack.
• For each character of the expression read from left to right:
– if the character is neither "(", nor ")" then do nothing!
– if the character is an opening parenthesis "(" then add this character to the stack;
– if the character is a closing parenthesis ")":
– test if the stack is empty, if it is empty then return “False” (the program ends
there, the expression is incorrectly parenthesized), if the stack is not empty
continue,
– pop the stack once, it gives a "(".
• If at the end, the stack is empty then return the value “True”, otherwise return “False”.
are_parentheses_balanced()
Use: are_parentheses_balanced(expression)
Input: an expression (string)
Output: true or false depending on whether the parentheses are correctly
placed or not
Action: uses a stack
Example :
• are_parentheses_balanced("(2+3)*(4+(8/2))") returns
True
• are_parentheses_balanced("(x+y)*((7+z)") returns False
2. Enhance this function to test an expression with parentheses and square brackets. Here is a correct
expression: [(a + b) ∗ (a − b)], here are some incorrect expressions: [a + b), (a + b] ∗ [a − b).
Here is the algorithm to program a function are_brackets_balanced().
POLISH CALCULATOR – STACKS 116
Algorithm.
Input: an expression (a string).
Output: “True” if the parentheses and square brackets are well balanced, “False” otherwise.
• Start with an empty stack.
• For each character of the expression read from left to right:
– if the character is neither "(", nor ")", nor "[", nor "]" then do nothing;
– if the character is an opening parenthesis "(" or an opening square bracket "[",
then add this character to the stack;
– if the character is a closing parenthesis ")" or a closing square bracket "]", then:
– test if the stack is empty, if it is empty then return “False” (the program ends
there, the expression is not correct), if the stack is not empty continue,
– pop the stack once, you get a "(" or a "[",
– if the popped (opening) character does not match the character read in the
expression, then return “False”. The program ends there, the expression is not
consistent. To match means that the character "(" corresponds to ")" and "["
corresponds to "]".
• If at the end, the stack is empty then return the value “True”, otherwise return “False”.
This time the stack can contain opening parentheses "(" or opening square brackets "[". Each
time you find a closing parenthesis ")" in the expression, the top of the stack must be an opening
parenthesis "(". Each time you find a closing square bracket "]" in the expression, the top of the
stack must be a opening square bracket "[".
Algorithm.
Input: a classic expression
Output: an expression in Polish notation
• Start with an empty stack.
• Start with an empty string polish which at the end will contain the result.
• For each character of the expression (read from left to right):
– if the character is a number, then add this number to the output string polish;
– if the character is an opening parenthesis "(", then add this character to the stack;
– if the character is the multiplication operator "*", then add this character to the stack;
– if the character is the addition operator "+", then:
while the the stack is not empty:
pop an element from the stack,
if this element is the multiplication operator "*", then:
add this item to the output string polish
otherwise:
push this element to the stack (we put it back on the stack after removing it)
end the “while” loop immediately (with break)
finally, add the "+" addition operator to the stack.
– if the character is a closing parenthesis ")", then:
while the stack is not empty:
pop an element from the stack,
if this element is an opening parenthesis "(", then:
end the “while” loop immediately (with break)
otherwise:
add this item to the output string polish
• If at the end, the stack is not empty, then add each element of the stack to the output string
polish.
polish_notation()
Use: polish_notation(expression)
Input: a classic expression (with elements separated by spaces)
Output: the expression in Polish notation
Action: use the stack
Example:
• polish_notation("2 + 3") returns "2 3 +"
• polish_notation("4 * ( 2 + 3 )") returns "4 2 3 + *"
• polish_notation("( 2 + 3 ) * ( 4 + 8 )") returns "2 3
+ 4 8 + *"
In this algorithm, each element between two spaces of an expression is miscalled “character”. Example:
the characters of "( 17 + 10 ) * 3" are (, 17, +, 10, ), * and 3.
POLISH CALCULATOR – STACKS 118
You see that the addition has a more complicated treatment than the multiplication. This is due to the
fact that multiplication takes priority over addition. For example, 2 + 3 × 5 means 2 + (3 × 5) and not
(2 + 3) × 5. If you want to take into account subtraction and division, you have to be careful about
non-commutativity (a − b is not equal to b − a; a ÷ b is not equal to b ÷ a).
End this chapter by checking that everything works correctly with different expressions. For example:
• Define an expression exp = "( 17 * ( 2 + 3 ) ) + ( 4 + ( 8 * 5 ) )"
• Ask Python to calculate this expression: eval(exp). Python returns 129.
• Convert the expression to Polish notation: polish_notation(exp) returns
"17 2 3 + * 4 8 5 * + +"
• With your calculator calculates the result: polish_calculator("17 2 3 + * 4 8 5 * + +")
returns 129. We get the same result!
Chapter
17
Text viewer – Markdown
You will program a simple word processor that displays paragraphs cleanly and highlights words in
bold and italics.
(0, 0) x
(x 1 , y1 )
(x 2 , y2 )
y
Lesson 2 (Markdown).
The Markdown is a simple markup language that allows you to write your own easy to read text file and
possibly convert it to another format (html, pdf. . . ).
TEXT VIEWER – MARKDOWN 121
Here is an example of a text file with the Markdown syntax with just below its graphic rendering.
# On the Origins of Species
## by Charles Darwin
## Chapters
The syntax is simple, with a clear and clean text file. Here are some elements of this syntax:
• a bold text is obtained by surrounding the text with two asterisks **;
• a text in italics is obtained by surrounding the text with one asterisk *;
• the line of a title begins with one sharp #;
• the line of a subtitle begins with two sharps ##;
• for the elements of a list, each line starts with a special symbol, for us it will be the symbol “plus” +.
• There is also a syntax to display links, tables, code. . .
In the following we will use the simplified syntax as described above.
1. Write a function print_line_v1(par,posy) that displays one by one the words of a paragraph
par (at the line of ordinate posy).
TEXT VIEWER – MARKDOWN 122
Hints.
• These words are obtained one by one with the command par.split().
• The displayed line starts at the very left, it overflows to the right if it is too long.
• After each word we place a space and then the next word.
• On the picture above the words are framed.
2. Improve your function in print_line_v2(par,posy) to take into account titles, subtitles and
lists.
Hints.
• To know in which mode to display the line, simply test the first characters of the line. The
line of a title begins with #, that of a subtitle with ##, that of a list with +.
• For lists, you can get the bullet character “•” by the unicode character u'\u2022'. You can
also indent each item of the list for more readability.
• Use the font_choice() function of the first activity.
• In the image above, each line is produced by a call to the function. For example
print_line_v2("## And there a subtitle",100).
3. Further improve your function in print_line_v3(par,posy) to take into account the words in
bold and italics in the text.
Hints.
• Words in bold are surrounded by the tag **, words in italics by the tag *.
In our simplified syntax, tags are separated from words by spaces, for example:
"Word ** in bold ** and in * italics *"
• Define a boolean variable in_bold that is false at the beginning; each time you encounter the
tag ** then reverse the value of in_bold (“True” becomes “False”, “False” becomes “True”,
you can use the operator not).
• Still use the font_choice() function of the first activity.
• In the image above, each line is produced by a call to the function. For example
print_line_v3("+ Apples and ** pears ** and * ananas *",100)
TEXT VIEWER – MARKDOWN 123
Hints.
• As soon as you place a word that exceeds the length of the line (see those that come out of
the frame in the image above), then the next word is placed on the next line.
• The function will therefore modify the variable posy at each line break. At the end, the function
returns the new value of posy, which will be useful for displaying the next paragraph.
5. Ends with a function print_file(filename) that displays the paragraphs of a text file with our
simplified Markdown syntax.
Activity 3 (Justification).
Goal: understand how it is possible to “justify” a text, i.e. to ensure that the words are well aligned
on the left and right sides of the page. To model the problem we work with a series of integers that
represent the lengths of our words.
In this activity:
• list_lengths is a list of integers (for example a list of 50 integers between 5 and 15) which
represent the lengths of the words;
• we set a constant line_length which represents the length of a line. For our examples, this
length is equal to 100.
In previous activities, we moved to the next line after a word had passed the end of the line. We represent
this by the following figure:
list_lengths = [8, 11, 9, 14, 8, 8, 15, 10, 14, 11, 15, 15, 5, 12, 9, 9, 15, 10, 14, 5, 12, 8, 8, 13, 10,
11, 8, 13, 7, 5, 6, 11, 7, 7, 13, 6, 6, 9, 8, 12, 5, 8, 7, 6, 6, 15, 13, 11, 7, 12]
TEXT VIEWER – MARKDOWN 124
hypenation_simple()
Use: hypenation_simple(list_lengths)
Input: a sequence of lengths (a list of integers)
Output: the list of indices where to make a cut
Example: hypenation_simple(list_lengths) where list_lengths
is the example given above, returns the list [0, 9, 17, 27, 39, 49,
50]. That is to say that:
• the first line corresponds to indices 0 to 8 (given by range(0,9)),
• the second line corresponds to indices 9 to 16 (given by
range(9,17)),
• the third line corresponds to indices 17 to 26 (given by
range(17,27)),
• ...
• the last line corresponds to the index 49 (given by range(49,50)).
2. Modify your work into a function hyphenation_spaces() that adds a space (with
space_length = 1) between two words of the same line (but not at the beginning of the line,
nor at the end of the line). This corresponds to the following drawing:
For our example, the hyphenations returned are [0, 8, 16, 24, 34, 45, 50].
TEXT VIEWER – MARKDOWN 125
3. In order to be able to justify the text, you allow spaces to be larger than the initial length of 1. On
each line, the spaces between the words are all the same length (greater than or equal to 1) so that
the last word is aligned on the right. From one line to another, the length of the spaces can change.
Write a function compute_space_lengths() that returns the length that the spaces of each line
must have in order for the text to be justified. For our example, we obtain the list [2.43, 1.43,
2.14, 1.67, 1.40, 1.00], i.e. for the first line the spaces must be 2.43 long, for the second
line 1.43,. . .
To find the right formula, simply take the results of the hyphenation_spaces() function and
then, for each line, count the total length of words it contains, as well as the value it lacks to arrive
at a total of 100.
You now have everything you need to visualize text written with the syntax Markdown and justify
it (see the displayed text of Darwin in the lesson). It’s still a lot of work! You can also improve the
support of Markdown syntax: code, numbered lists, sublists, bold and italic words at the same time. . .
Chapter
L-systems
18
The L-systems offer a very simple way to code complex phenomena. From an initial word and
replacement operations, we arrive at complicated words. When you “draw” these words, you get
beautiful fractal figures. The “L” comes from the botanist A. Lindenmayer who invented the L-systems
to model plants.
Lesson 1 (L-system).
A L-system is the data of an initial word and replacement rules. Here is an example with the starting
word and only one rule:
BlArB A → ABA
The k-iteration of the L-system is obtained by applying k times the substitution to the starting word.
With our example:
• First iteration. The starting word is BlArB, the rule is A → ABA: we replace the A by ABA. We get
the word BlABArB.
• Second iteration. We start from the word obtained BlABArB, we replace the two A by ABA: we get
the word BlABABABArB.
• The third iteration is BlABABABABABABABArB, etc.
When there are two (or more) rules, they must be applied at the same time. Here is an example of a
two-rules L-system:
A A → BlA B → BB
With our example:
• First iteration. The starting word is A, we apply the first rule A → BlA (the second rule does not
L-SYSTEMS 127
Goal: make a drawing from a “word”. Each character corresponds to a turtle instruction.
You are given a word (for example AlArAArArA) in which each letter (read from left to right) corresponds
to an instruction for the Python turtle.
• A or B: advance of a fixed quantity (by tracing),
• l: turn left, without moving forward, by a fixed angle (most often 90 degrees),
• r: turns right by a fixed angle.
The other characters do not do anything. (More commands will be added later on.)
Program a function draw_lsystem(word,angle=90,scale=1) which displays the drawing corre-
sponding to the letters of word. By default the angle is 90 degrees, and each time you advance, it is of
100×scale.
For example: draw_lsystem("AlArAArArA") displays this:
L-SYSTEMS 128
4. Trace other fractal figures from the following L-systems. For all these examples the starting word is
"ArArArA" (a square) and the rule is to be chosen among:
• ("A","ArAlAlAArArAlA")
• ("A","AlAArAArArAlAlAArArAlAlAAlAArA")
• ("A","AArArArArAA")
• ("A","AArArrArA")
• ("A","AArArArArArAlA")
• ("A","AArAlArArAA")
• ("A","ArAArrArA")
• ("A","ArAlArArA")
Lesson 3 (Stacks).
A stack is a temporary storage area. Details are in the chapter “Polish calculator – Stacks”. Here are just a
few reminders.
(−100, 0), 60
Top of the stack
(0, 0), 0
(100, 100), 0
(0, 0), 90
(0, 0), 30
A stack
• A stack is like a stack of plates; elements are placed one by one above the stack; the elements are
removed one by one, always from the top. It’s the principle: “last in, first out”.
• We model a stack by a list.
• At the beginning the stack is empty: stack = [].
• Push. We add the items at the end of the list: stack.append(element) or stack = stack +
[element].
• Pop. An item is removed by the command pop():
element = stack.pop()
which returns the last item in the stack and removes it from the list.
• On the drawing and in the next activity, the elements of the stack are of the type (x, y), θ that
will store a state of the turtle: (x, y) is the position and θ its direction.
2. Return back.
We now allow square brackets in our words. For example AlA[lAAA]A[rAA]A. When you encounter
a opening bracket “[”, you memorize the position of the turtle, then the commands in brackets are
executed as usual, when you find the closing bracket “]” you go back to the position stored before.
Let us understand the example of the route of the AlA [lAAA] A [rAA] A
• AlA: we start from the point O, we move forward, we turn, we move forward.
L-SYSTEMS 133
• [lAAA]: we retain the current position (the point P) and also the direction; we turn, we
advance three times (we trace the red segment); at the end we return the turtle to the position
P (without tracing and with the same direction as before).
• A: from P we advance (green segment).
• [rAA]: we retain the position Q and the direction, we turn and we trace the purple segment.
We come back in Q with the old state.
• A: from Q we trace the last segment.
Here is how to draw a word containing brackets using a stack:
• At the beginning the stack is empty.
• We read one by one the characters of the word. The actions are the same as before.
• If the character is the opening bracket “[” then add to the stack the current position and
direction of the turtle (x, y), θ that you get by (position(), heading()).
• If the character is the closing bracket “]” then pop (i.e. read the top element of the stack and
remove it). Put the position of the turtle and the angle with the read values, use goto() and
setheading().
3. Trace the following L-systems, where the starting word and rule (or rules) are given. The angle is
to be chosen between 20 and 30 degrees.
• "A" ("A","A[lA]A[rA][A]")
• "A" ("A","A[lA]A[rA]A")
• "A" ("A","AAr[rAlAlA]l[lArArA]")
• "X" ("X","A[lX][X]A[lX]rAX") ("A","AA")
• "X" ("X","A[lX]A[rX]AX") ("A","AA")
• "X" ("X","Ar[[X]lX]lA[lAX]rX") ("A","AA")
Dynamic images
19
We will distort images. By repeating these distortions, the images become blurred. But by a miracle
after a certain number of repetitions the original image reappears!
i =0 A B a b i 0 =0 A a B b
i =1 C D c d i 0 =1
C c D d
For example, the pixel in position (1, 1) (symbolized by the letter D) is sent in position (4, 4).
Let’s explain this principle through formulas. For each couple (i, j), we calculate its image (i 0 , j 0 ) by the
photo booth transformation according to the following formulas:
• If i and j are even: (i 0 , j 0 ) = (i//2, j//2).
• If i is even and j is odd: (i 0 , j 0 ) = (i//2, (n + j)//2).
• If i is odd and j is even: (i 0 , j 0 ) = ((n + i)//2, j//2).
• If i and j are odd: (i 0 , j 0 ) = ((n + i)//2, (n + j)//2).
Here is an example of an array 4 × 4 before (left) and after (right) the transformation of the photo booth.
1 2 3 4 1 3 2 4
5 6 7 8 9 11 10 12
9 10 11 12 5 7 6 8
13 14 15 16 13 15 14 16
DYNAMIC IMAGES 135
Here is what happens if you repeat the photo booth transformation several times:
The image becomes more and more blurred, but after some number of repetitions of the transformation,
we fall back on the original image!
P2
5 5
255
128 192 128 192 128
224 0 228 0 224
228 228 228 228 228
224 64 64 64 224
192 192 192 192 192
stretch
A B
A a B b
a b
Formulas. An element at position (i, j) of the target array, corresponds to an element (2i, j//2) (if j
is even) or (2i + 1, j//2) (if j is odd) of the source array, with here 0 6 i < 2n and 0 6 j < 2n.
Example. Here is an array 4 × 4 on the left, and the stretched array 2 × 8 on the right. The rows 0
and 1 on the left give the row 0 on the right. The rows 2 and 3 on the left give the row 1 on the
right.
1 2 3 4
5 6 7 8 1 5 2 6 3 7 4 8
9 10 11 12 9 13 10 14 11 15 12 16
13 14 15 16
• Fold. The principle is as follows: the right part of a stretched array is turned upside down, then
added under the left part. Starting from an array 2n × 2n you get an array n × n.
A B
fold A
B
Formulas. For 0 6 i < 2n and 0 6 j < n the elements in position (i, j) of the array are kept. For
n n
2 6 i < n and 0 6 j < n an element of the array (i, j), corresponds to an element 2 −i−1, 2n−1− j
of the source array.
DYNAMIC IMAGES 138
Example. From the stretched array 2 × 8 on the left, we obtain a folded array 4 × 4 on the right.
1 5 2 6
1 5 2 6 3 7 4 8 9 13 10 14
9 13 10 14 11 15 12 16 16 12 15 11
8 4 7 3
The transformation of the baker is the succession of a stretching and a folding. Starting from an array
n × n we still get an array n × n.
Let’s see an example of the action of several transformations of the baker. On the left the initial image
size 128 × 128, then the result of k = 1, 2, 3 iterations.
1 2 3 4 1 5 2 6 1 9 5 13
5 6 7 8 9 13 10 14 16 8 12 4
9 10 11 12 16 12 15 11 3 11 7 15
13 14 15 16 8 4 7 3 14 6 10 2
4. Program a function baker_images(image_name,kmax) that calculates the images correspond-
ing to the transformation of the baker, with iterations ranging from k = 1 to k = kmax .
5. Experiment for different values of the size n, to see after how many iterations we find the original
image.
DYNAMIC IMAGES 139
Caution! It sometimes takes a lot of iterations to get back to the original image. For example with
n = 4, we find the starting image after k = 5 iterations; with n = 256 it is k = 17. Conjecture
a return value in the case where n is a power of 2. However, for n = 10, you need k = 56 920
iterations!
Here is an example with an image of size 256 × 256, first the initial image, then one transformation
(k = 1) and a second iteration (k = 2).
k = 3, 4, 5 :
k = 15, 16, 17 :
This chapter is based on the article “Blurred images, recovered images” by Jean-Paul Delahaye and Philippe
Mathieu (Pour la Science, 1997).
Chapter
20
Game of life
The game of life is a simple model of the evolution of a population of cells that born and die over time.
The “game” consists in finding initial configurations that give interesting evolution: some groups of
cells disappear, others stabilize, some move. . .
Birth
• For a square containing a cell at day j, having either 2 or 3 neighboring cells: then the cell continues
to live. In other cases the cell dies (with 0 or 1, it dies of isolation, with more than 4 neighbors, it
dies of overpopulation).
GAME OF LIFE 141
0 0 0 0 0
1 2 3 2 1
1 1 2 1 1
1 2 3 2 1
0 0 0 0 0
Initial position (day j) Numbers of neighbors Evolution (day j + 1)
Here is another example (with directly the number of neighbors), the first evolution and the evolution of
the evolution.
0 1 2 2 1 1 2 3 2 1
1 3 3 2 1 2 2 3 1 1
1 3 4 4 1 3 4 6 3 1
1 3 2 2 0 2 2 2 1 0
0 1 1 1 0 1 2 2 1 0
Day 0 Day 1 Day 2
Activity 1 (Display).
Goal: define and display arrays.
We model the living space of the cells by a double entry table, containing integers, 1 to indicate the
presence of a cell, 0 otherwise. Here is an example of the configuration “toad” and its array:
index j
i=0 0 0 0 0 0 0
i=1 0 0 1 1 1 0
index i n
..
. 0 1 1 1 0 0
i = n−1 0 0 0 0 0 0
p
Cells Array
GAME OF LIFE 142
1. • Initialize two variables n (the height of the table) and p (the width) (for example at 5 and 8).
• Define a two-dimensional table filled with zeros by the command:
array = [[0 for j in range(p)] for i in range(n)]
• By instructions of the type array[i][j] = 1, fill in the table to define the configuration of
the blinker, the toad . . .
2. Program the display of a given array on the screen. For example, the blinker is displayed as follows:
00000000
00000000
00111000
00000000
00000000
Hint. By default the command print() passes to the next line on each call (it adds the character
"\n" which is the end of line character). It can be specified not to do so by the option print("My
text",end="").
1. Program the creation of a tkinter window (see chapter “Statistics – Data visualization”). Write a
function draw_grid(), without parameters, that displays a blank grid of coordinates. You will
need a constant scale (for example scale = 50) to transform the indices i and j into graphic
coordinates x and y, depending on the relationship: x = s × j and y = s × i (s being the scale).
Bonus. You can also mark the values of the indices i and j at the top and the left to make it easier
to read the grid.
2. Build a function draw_array(array) that graphically displays the cells from a table.
Bonus. Add a button “View” and a button “Quit” (see chapter “Statistics – Data visualization”).
Activity 3 (Evolution).
Goal: calculate the evolution of a configuration to the next day.
1. Program a function number_neighbors(i,j,array) that calculates the number of living neigh-
GAME OF LIFE 143
Activity 4 (Iterations).
Goal: end the graphic program so that the user can define configurations and make them evolve
with a simple click.
1. Improve the graphic window to make the user’s life easier:
• A button “evolve” which displays a new evolution with each click.
• Buttons to display predefined configurations (on the screenshot below is the configuration
“pentadecathlon”).
2. Perfect your program so that the user can draw the configuration he wants with mouse clicks.
Clicking on an extinguished cell turns it on, clicking on an living cell turns it off. You can break
this work down into three functions:
• on_off(i,j), which switches the cell (i, j) ;
• xy_to_ij(x,y) that converts graphic coordinates (x, y) into integers coordinates (i, j) (use
variable scale and the integer division).
GAME OF LIFE 144
# Window
root = Tk()
canvas = Canvas(root, width=800, height=600, background="white")
canvas.pack(side=LEFT, padx=5, pady=5)
# Association click/action
canvas.bind("<Button-1>", action_mouse_click)
# Launch
root.mainloop()
Here are some explanations:
• The creation of the window is usual. The program ends with the launch by the command
mainloop().
• The first key point is to associate a mouse click to an action, that’s what the line does:
canvas.bind("<Button-1>", action_mouse_click)
GAME OF LIFE 145
Each time the left mouse button is clicked, Python executes the function action_mouse_click.
(Note that there are no brackets for the call to the function.)
• Second key point: the action_mouse_click function retrieves the click coordinates and then
does two things here: it displays a small rectangle at the click location and displays the (x, y)
coordinates in the terminal window.
• The coordinates x and y are expressed in pixels; (0, 0) refers to the upper left corner of the window
(the area delimited by canvas).
You will find many more on the Internet but above all have fun discovering new ones!
In particular, find configurations:
• that remain fixed over time;
• which evolve, then become fixed;
• which are periodic (the same configurations come back in loops) with a period of 2, 3 or more;
• who travel;
• that propel cells;
• whose population is increasing indefinitely!
Chapter
Ramsey graphs
21
and combinatorics
You will see that a very simple problem, which concerns the relationships between only six people,
will require a lot of calculations to be solved.
We consider n people. For two of them, either they know each other (they are friends) or they do not
know each other (they are strangers to each other). We schematize this by a graph:
• a person is represented by a vertex (numbered from 0 to n − 1);
• if two people are friends, the corresponding vertices are connected by a green solid edge;
• otherwise (they are strangers), the corresponding vertices are connected by a red dotted edge.
The graph below means that 0 is friend with 2; 1 is friend with 3. The other pairs don’t know each other.
3 0
2 1
A graph checks the Ramsey problem, if there are among its vertices, either 3 friends, or either 3 foreigners.
RAMSEY GRAPHS AND COMBINATORICS 147
j0 i0
i
Three stangers
k Three friends k0
Here is an example of 5 peoples that verify the statement: there is group of 3 strangers (the 0, 2 and 4
vertices), even if there is no group of three friends.
1
A graph with n = 5 that satifies Ramsey’s statement
Lesson 2 (Model).
Let be a graph with n vertices, numbered from 0 to n − 1. The array of the graph is a table of size n × n
in which we place a 1 in position (i, j) if the vertices i and j are connected by an edge, otherwise we
place a 0.
First example below: the vertices 0 and 2 are friends (because they are connected by a green edge) so the
table contains a 1 in position (0, 2) and also in (2, 0). Similarly 1 and 3 are friends, so the table contains
a 1 in position (1, 3) and (3, 1). The rest of the table contains 0.
index j
i=0 0 0 1 0
i=1 0 0 0 1
index i n
i=2 1 0 0 0
i=3 0 1 0 0
2 1
i=1 1 0 1 0 1
i=2 0 1 0 1 0
0
i=3 1 0 1 0 1
i=4 0 1 0 1 0
2
Goal: define graphs and test if three given vertices are friends.
1. Define the graph array for the four examples above. You can start by initializing the array with
array = [[0 for j in range(n)] for i in range(n)]
Then add commands:
array[i][j] = 1 and array[j][i] = 1
Don’t forget that if the i vertex is connected to the j vertex by an edge, then you have to put a 1 in
position (i, j) but also in position ( j, i).
2. Define a function print_graph(array) that allows you to display on the screen the table of a
graph. Thus the third example above (with n = 5) should be displayed as follows:
RAMSEY GRAPHS AND COMBINATORICS 149
0 0 1 1 0
0 0 1 0 1
1 1 0 0 0
1 0 0 0 1
0 1 0 1 0
3. We set three vertices i, j, k of a graph. Write a function have_3_fix_friends(array,i,j,k)
that tests if the vertices i, j, k are three friends (the function returns “True” or “False”). Do the
same work with a have_3_fix_strangers(array,i,j,k) function to find out if these vertices
are strangers.
Find by hand on the fourth example, three friend or foreign vertices and check your answer using
the functions you have just defined on these vertices.
Hints. This activity is not necessary for the next steps, it just helps to visualize the graphs. It is neces-
sary to use the module tkinter and the functions create_line(), create_oval() and possibly
create_text().
The most delicate point is to obtain the coordinates of the vertices. You will need the sine and cosine
functions (available in the module math). The coordinates (x i , yi ) of the vertex number i of a graph
with n elements can be calculated by the formulas :
2iπ 2iπ
x i = r cos and yi = r sin .
n n
These vertices are located on the circle of radius r, centered at (0, 0). You will have to choose r large
enough (for example r = 200) and shift the circle to display it on the screen.
RAMSEY GRAPHS AND COMBINATORICS 150
(x 1 , y1 )
(x i , yi )
yi = r sin( 2iπ
n )
(x 0 , y0 )
x i = r cos( 2iπ (0, 0) x
n )
(x n−1 , yn−1 )
Example.
• The binary notation of p = 37 is 1.0.0.1.0.1. If you want its binary notation on n = 8 bits you have
to add two 0 in front of it: 0.0.1.0.0.1.0.1.
• So the result of the command integer_to_binary(37,8) must be [0, 0, 1, 0, 0, 1,
0, 1].
• The command integer_to_binary(37,10) returns the binary notation of 37 on 10 bits: [0,
0, 0, 0, 1, 0, 0, 1, 0, 1].
Hints.
• You can use the command bin(p).
• The command list(mystring) returns the list of characters making up mystring.
• Attention! We want a list of integers 0 or 1, not of characters '0' or '1'. The command int('0')
returns 0 and int('1') returns 1.
• mylist = mylist + [element] adds an item at the end of the list, while mylist =
[element] + mylist adds the item at the beginning of the list.
Lesson 3 (Subsets).
Let En = {0, 1, 2, . . . , n − 1} be the set of all integers from 0 to n − 1. The set En therefore contains n
elements. For example E3 = {0, 1, 2}, E4 = {0, 1, 2, 3}. . .
Subsets.
What are the subsets of En ? For example there are 8 subsets of E3 , these are:
• the subset {0} composed of the single element 0;
RAMSEY GRAPHS AND COMBINATORICS 151
Activity 4 (Subsets).
Goal: generate all subsets to test all triples of vertices. For this we will use binary notation.
Here is how we associate to each integer p verifying 0 6 p < 2n a subset of En = {0, 1, . . . , n − 1}.
Let’s start with an example, with n = 6 and p = 26:
• the binary notation of p = 26 on n = 6 bits is [0,1,1,0,1,0];
• there are 1 at ranks 1, 2 and 4 (starting at rank 0 on the left);
• the associated subset is then {1, 2, 4}.
p = 26 0 1 1 0 1 0 {1, 2, 4}
(n = 6)
rank : 0 1 2 3 4 5
Other examples.
• With n = 8 and p = 57 whose binary notation on 8 bits is [0,0,1,1,1,0,0,1], the associated
subset corresponds to the ranks 2, 3, 4, 7, so it is {2, 3, 4, 7}.
p = 57 0 0 1 1 1 0 0 1 {2, 3, 4, 7}
(n = 8)
rank : 0 1 2 3 4 5 6 7
Initial integer p Binary notation of p on n bits Subset associated to p
• With p = 0, the binary notation is only formed of 0, the associated subset is the empty set.
RAMSEY GRAPHS AND COMBINATORICS 152
• With p = 2n − 1, the binary notation is full of 1, the associated subset is the whole set En =
{0, 1, . . . , n − 1} itself.
[[3, 4, 5], [2, 4, 5], [2, 3, 5], [2, 3, 4], [1, 4, 5],
[1, 3, 5], [1, 3, 4], [1, 2, 5], [1, 2, 4], [1, 2, 3],
[0, 4, 5], [0, 3, 5], [0, 3, 4], [0, 2, 5], [0, 2, 4],
[0, 2, 3], [0, 1, 5], [0, 1, 4], [0, 1, 3], [0, 1, 2]]
Goal: check that all graphs with 6 vertices contain three friends or three strangers.
b = binary_notation.pop()
array[i][j] = b
array[j][i] = b
Here is the principle of this loop that fills the part above the diagonal (and also the part below it
by symmetry). This loop takes the last bit of the list and places it on the first free box above the
diagonal; then the penultimate bit is placed on the second free box. . . ; the first bit of the list fills
the last free square.
1 0 1 1 0 0 0 1 0 1
0 1 0 1 0
0 0 0 1 N boxes above the diago-
N boxes below the diago- 0 1 0 nal
nal (filled by symetry) 0 1
0
Filling of an array
3. Convert the previous function into a function test_all_graphs(n) which tests the conjecture
“there are three friends or three strangers” for all graphs with n vertices. You must find that:
• for n = 4 and n = 5 the guess is wrong. Give a graph having 4 vertices (then 5 vertices) that
has neither 3 friends, nor 3 foreigners;
5×6
• for n = 6 let the computer check that, for each of the N = 2 2 = 32 768 graphs with 6
vertices, either it has 3 friends or it has 3 foreigners.
Goal: improve your program and prove other guesses. Optional activity.
1. Improve your program so that it checks the guess for n = 6 in less than a second.
Ideas.
• The list of triples must be generated once and for all at the beginning of the program (and
not at each new graph).
• It is not necessary to generate a list of all possible graphs, then test them in a second step. It
is better to generate one and then test it before moving on to the next.
• As soon as you find 3 friends (or 3 foreigners) it’s won! Immediately stop the loop even if it
means using the instruction break and move to the next graph.
• You can only test the graphs that correspond to p between 0 and 2N /2 (because for the next
p it is like exchanging the green segments for red and vice versa).
With these tips here are the calculation times you can expect:
RAMSEY GRAPHS AND COMBINATORICS 154
2. There is a more difficult statement. It is a question of finding out at which size n a graph always
contains either 4 friends or 3 foreigners. Being 4 friends means that two by two they are connected
by a green segment, as below:
(a) Find graphs with n = 6 (then n = 7) vertices that do not check this statement.
(b) By searching a little with the machine find graphs with 8 vertices that do not satisfy this
statement.
(c) Prove that any graph having 9 vertices contains 4 friends or 3 foreigners!
Hints. It is necessary to test all the graphs corresponding to integers p between 0 and 2N =
8×9
2 2 = 68 719 476 736. The total calculation time is about 20 days! You can share the
calculations between several computers: one computer does the calculations for 0 6 p 6
1 000 000, a second computer for 1 000 001 6 p 6 2 000 000,. . .
3. • There are arguments to prove with pencil and paper that for n = 6 there is always 3 friends
or 3 foreigners. Look for such reasoning! With a little more effort, we can also prove that it is
n = 9 that answers the problem of 4 friends/3 foreigners.
• We know how to prove that we need n = 18 to always have 4 friends or 4 foreigners.
• However, no one in the world knows what the smallest n is for the 5 friends/5 foreigners
problem!
Chapter
22
Bitcoin
The bitcoin is a dematerialized and decentralized currency. It is based on two computer principles:
public key cryptography and proof of work. To understand this second principle, you will create a
simple model of bitcoin.
given solution is suitable. For higher values of p, the search for a solution x can be much too long and
not succeed. We’ll see how we can adjust the difficulty of the problem.
3. Instead of looking for an exact solution to our problem x 2 = y (mod p), which is equivalent to
x 2 − y (mod p) = 0, we are looking for an approximate solution, i.e. one that checks:
x 2 − y (mod p) 6 m.
For example if m = 5, then you can have (modulo p) : x 2 − y = 0, x 2 − y = 1, x 2 − y = 2,. . . or
x 2 − y = 5. Of course there are now many possible solutions x
Program a function approximate_square_root(y,margin) that finds an approximate solution
to our problem x 2 = y (mod p).
How long does it take to find one solution to the problem when p = 15 486 869, y = 8 371 779
and m = 20? Choose a prime number p large enough and find a margin of error m so that finding
a solution to the approximate problem requires about 30 to 60 seconds of calculations (for any y).
Here are some examples of prime numbers you can use for your tests:
101 1097 10651 100109 1300573 15486869
179426321 2276856017 32416187567
Lesson 1 (Stopwatch).
The time module allows you to measure the execution time but also to know the date and time (see also
the timeit module explained in the “Arithmetic – While loop – I”). Here is a small script to measure the
calculation time of an instruction.
import time
start_chrono = time.time()
time.sleep(2)
end_chrono = time.time()
To prevent someone from falsifying the account book, after each transaction a certification based on a
proof of work is added to the book. Here is what is written in the ledger:
1. We start with any initial proof of work. For us it will be [0,0,0,0,0,0].
2. The first transaction is written (for example "Amir -100").
3. A proof of work is calculated and written in the book, which will serve as a certificate. It’s a list
(for example [56,42,10,98,2,34]) obtained after many calculations taking into account the
previous transaction and the previous proof of work.
4. For each new transaction (for example "Barbara +45"), someone calculates a proof of work for
the last transaction associated with the previous proof. We write the transaction, then the proof of
work.
proof
proof transaction 3
proof transaction 2
The proof of work that is calculated depends on the previous transaction but also on the previous proof
of work, which itself depends on the previous data... Thus, each new proof of work actually depends on
everything that has been written since the beginning (even if the calculation explicitly refers only to the
last two entries).
Someone who would like to fake a past transaction should recalculate all the proofs of work that come
next. This is not possible for a single person: there are several proofs of work to calculate and each proof
requires a lot of calculations.
Goal: build useful functions to manipulate lists of integers for the following activities.
BITCOIN 158
(d) We reduce each integer modulo 100 to get integers between 0 and 99.
b0 b1 b2 b3 b4 b5
+ + +
(a) additions
A B C list
block 1 block 2 block 3
10 rounds
addition
A’
B’ C
10 rounds
addition
B”
C’
10 rounds
C” hash
Example with the list [0, 1, 2, 3, 4, 5, 1, 1, 1, 1, 1, 1, 10, 10, 10, 10, 10, 10].
• The first block is [0, 1, 2, 3, 4, 5], its mix after 10 rounds is [98, 95, 86, 55, 66, 75].
• This mix is added to the second block [1, 1, 1, 1, 1, 1] (see function addition() in activity
2).
• The remaining list is now [99, 96, 87, 56, 67, 76, 10, 10, 10, 10, 10, 10].
• Let’s do it again. The new first block is [99, 96, 87, 56, 67, 76], its mix after 10 rounds is
[60, 82, 12, 94, 6, 80], it is added to the last block [10, 10, 10, 10, 10, 10] to get (modulo 100)
[70, 92, 22, 4, 16, 90].
• A last mix is made with 10 rounds to obtain the hash: [77, 91, 5, 91, 89, 99].
Program a bithash(mylist) function that returns the fingerprint of a list. Test it on the examples
given at the beginning of the activity.
We are going to build a complicated problem to solve, for which, if someone gives us the solution, then it
is easy to check that it is correct.
BITCOIN 161
Problem to solve. We are given a list, it is a matter of finding a block such that, when you add it to the
list, it produces a hash starting with zeros. More precisely, given a list mylist and a maximum target of
max_list, we have to find a block proof which, concatenated to the list and then hashed, is smaller
than the list of max_list, i.e.:
bithash(mylist + proof) smaller than max_list
The list is of any length (a multiple of N = 6), the proof is a block of length N , the objective is to find a
list starting with 0 (see activity 2).
For example: let mylist = [0,1,2,3,4,5] and max_list = [0,0,7]. Which block proof can I
concatenate to mylist to solve my problem?
• proof = [12,3,24,72,47,77] is appropriate because concatenated to our list it gives
[0,1,2,3,4,5,12,3,24,72,47,77] and the hash of this whole list gives [0,0,5,47,44,71]
which starts with [0,0,5] smaller than the target.
• proof = [0,0,2,0,61,2] is also suitable because after concatenation we have
[0,1,2,3,4,5,0,0,2,0,61,2] whose hash gives [0,0,3,12,58,92].
• [97,49,93,87,89,47] is not suitable, because after concatenation and hashing we get
[0,0,8,28,6,60] which is greater than the desired objective.
1. Verification (easy).
Program a function verification_proof_of_work(mylist,proof) that returns true if the
proposed solution proof is suitable for mylist. Use the is_smaller() function of activity 2.
2. Search for a solution (difficult).
Program a function proof_of_work(mylist) that looks for a block proof solution to our
problem for the given list.
Hints.
• The easiest method is to take a block proof of random numbers and start again until a
solution is found.
• You can also systematically test all blocks starting with [0,0,0,0,0,0], then
[0,0,0,0,0,1]. . . and stop at the first appropriate one.
• You adjust the difficulty of the problem by changing the objective: easy with Max =
[0,0,50], medium with max_list = [0,0,5], difficult with max_list = [0,0,0], too
difficult with max_list = [0,0,0,0].
• As there are several solutions, you do not necessarily get the same solution for each search.
3. Calculation time.
Compare the calculation time of a simple check against the time of searching for a solution. Choose
the objective max_list so that the search for a proof of work requires about 30 to 60 seconds of
calculations.
For the bitcoin, those who calculate proofs of work are called the minors. The first one to find a proof
wins a reward. The difficulty of the problem is adjusted so that that the calculation time taken by the
winner (among all the minors) to find a solution is about 10 minutes.
proof
Conclusion: let’s imagine that Alfred wants to cheat, he wants to change the account book in order to
receive 100 bitcoins instead of having a debit, so he has to change the transaction concerning him to
"Alfred +100" but then he has to recalculate a new proof of work which is complicated, moreover he
has to recalculate the proof of the Barnabe transaction and also that of the Chloe transaction!
Someone who wants to modify a transaction must modify all the following proofs of work. If each
proof requires sufficient computing time this is impossible. For the bitcoin each proof requires a lot of
calculations (too much for a single person) and a new proof is to be calculated every 10 minutes. It is
therefore impossible for a person to modify a past transaction.
The other aspect of the bitcoin that we didn’t address is to make sure that each person involved is who
they are, so that no one can get the money of somebody else. This is made possible by private/public key
cryptography (RSA system). Each account is identified by a public key (two very large integers), which
guarantees anonymity. But above all, only the one who has the private key to the account (a large integer)
can access his bitcoins.
Chapter
23
Random blocks
You will program two methods to build figures that look like algae or corals. Each figure is made up
of small randomly thrown blocks that stick together.
1. Block fallen from col. 1 2. Block fallen from col. 4 3. Block fallen from col. 1
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
4. Block fallen from col. 2 5. Block fallen from col. 2 6. Block fallen from col. 3
For example, in step 4, the block thrown in the column 2 does not go down to the bottom but remains
hung on its neighbor, so it is permanently suspended.
The random throwing of hundreds of blocks on a large grid produces pretty geometric shapes resembling
algae.
RANDOM BLOCKS 165
The workspace is modeled by an array of n rows and p columns. At the beginning the array only contains
0’s; then the presence of a block is represented by 1.
Here is how to initialize the table:
array = [[0 for j in range(p)] for i in range(n)]
The table is modified by instructions of the type:
array[i][j] = 1
Here is an example of a table (left) to represent the graphical situation on the right (the block at the top
right is falling).
index j
i=0
0 0 0 0 1 0
i=1
0 0 1 0 0 0
index i
0 0 1 0 0 0 i=2
0 0 1 1 0 0
i=3
1. Program a function can_fall(i,j) that determines if the block in position (i, j) can drop to the
square below or not.
Here are the cases in which the block cannot fall:
• if the block is already on the last line,
• if there is a block just below,
• if there is a block just to the right or just to the left.
2. Program a function drop_one_block(j) which drops a block in the j column until it can no
longer go down. This function modifies the array.
For example, here is the table before (left) and after (right) dropping a block in the j = 3 column.
RANDOM BLOCKS 166
0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 1 1 0 0
0 0 1 0 0 0 0 0 1 0 0 0
0 0 1 1 0 0 0 0 1 1 0 0
0 1 2 3 4 5 0 1 2 3 4 5
Before After
3. Program a function drop_blocks(k) that launches k blocks one by one, each time choosing a
random column (i.e. an integer j with 0 6 j < p).
Here is an example of a table obtained after throwing 10 blocks:
0 0 0 1 1 0
0 1 1 1 0 0
0 0 1 0 0 1
0 0 1 1 0 1
Throw of 10 blocks
Hints.
• Use the module tkinter, see chapter “Statistics – Data visualization”.
• You can add a button that launches a block (or several at once).
RANDOM BLOCKS 167
Dynamic display (optional and difficult). Program the display of falling blocks.
Hints.
• It’s much more complicated to program, but very nice to see!
• For moving the blocks, use the program “Moves with tkinter” at the end of this chapter.
• How to make a “block rain”? On a regular basis (for example every tenth of a second) all existing
blocks are dropped by one square and a new one appears on the top line.
Gradually, we obtain a kind of tree that looks like coral. The calculations are very long because many
blocks come out of the grid or take a long time to fix (especially at the beginning). In addition, the blocks
can only be thrown one by one.
Part 1.
1. Model the workspace again with an array of n rows and p columns containing 0 or 1. Initialize all
values to 0, except 1 in the center of the table.
2. Program a function is_inside(i,j) which determines if the position (i, j) is in the grid (other-
wise the block is coming out).
3. Program a function can_move(i,j) that determines if the block in position (i, j) can move (the
function returns “True”) or if it is hung on (the function returns “False”).
4. Program a function launch_one_block(), without parameters, that simulates the creation of a
block and its random movement, until it sticks or leaves the grid.
Hints.
• The block is created at a random position (i, j) of the grid.
• As long as the block is in the grid and free to move:
– you choose a horizontal move by randomly drawing an integer from {−1, 0, +1}, the
same for a vertical move;
– you move the block according to the combination of these two movements.
• Then modify the table.
5. End with a function launch_blocks(k) that launches k blocks.
Second part.
RANDOM BLOCKS 169
Program the graphic display using tkinter. You can add a button that launches 10 blocks at once.
the_width = 400
the_height = 200
root = Tk()
canvas = Canvas(root, width=the_width, height=the_height, background="white")
canvas.pack(fill="both", expand=True)
RANDOM BLOCKS 170
# Main function
def mymove():
global x0, y0, dx, dy
x0 = x0 + dx # New abscissa
y0 = y0 + dy # New ordinate
canvas.coords(rect,x0,y0,x0+20,y0+20) # Move
return
# Buttons
button_move = Button(root,text="Move", width=20, command=action_move)
button_move.pack(pady=10)
root.mainloop()
PA R T V
GUIDES
171
Chapter
keyword "if"
a condition
colon
if condition :
instruction_1 indented block
instruction_2 will be executed only
... if the condition is true
other instructions
program continuation
if condition :
instruction this block will be executed
instruction if the condition is true
...
else:
instruction this block will be executed
...
if the condition is not true
other instructions
PYTHON SURVIVAL GUIDE 173
keyword "while"
a condition
colon
while condition :
instruction_1 indented block will
instruction_2 be executed as long as
... the condition is true
other instructions
program continuation
2. Data type
• int Integer. Examples: 123 or -15.
• float Floating point (or decimal) number. Examples: 4.56, -0.001, 6.022e23 (for 6.022×1023 ),
4e-3 (for 0.004 = 4 × 10−3 ).
• str Character or string. Examples: 'Y', "k", 'Hello', "World!".
• bool Boolean. True or False.
• list List. Example: [1,2,3,4].
PYTHON SURVIVAL GUIDE 174
3. Define functions
keyword "def"
well-chosen name
parentheses
colon
def my_function () :
instruction_1
instruction_2 instructions
...
return
end of the function
returned result
p = x * y
return p
def my_function(x):
x = x + 1
return x
x = 7
print(my_function(x))
print(x)
• Variables defined within a function are called local variables. They do not exist outside the function.
• If there is a variable in a function that has the same name as a variable in the program (like the x in
the example above), it is as if there were two distinct variables; the local variable only exists inside
the function.
To understand the scope of the variables, you can color the global variables of a function in red, and the
local variables with one color per function. The following small program defines a function that adds one
and another that calculates the double.
PYTHON SURVIVAL GUIDE 177
global variable
x = 7
def add_one( x ):
x = x +1
local variable
return x
def double( x ):
x = 2 * x
another local variable
return x
print( x )
print(add_one( x ))
print(double( x ))
print( x )
The program first displays the value of x, so 7, then it increases it by 1, so it displays 8, then it displays
twice as much as x, so 14. The global variable x has never changed, so the last display of x is still 7.
• The command draw(100, color="red") traces my line with a new color (the thickness is the
default one).
• The command draw(100, width=10, color="red") traces my line with a new thickness and a
new color.
• Here is also what you can use:
– draw(100, 10, "red"): do not specify the names of the options if you pay attention to the
order.
– draw(color="red", width=10, length=100): you can name any variable, the named
variables can pass as arguments in any order.
4. Modules
5. Errors
a = 3
b = 2
Python returns the error message IndentationError: unexpected indent. It also indicates the line number
where the indentation error is located, it even points using the symbol “^” to the exact location of the error.
5.2. Syntax errors
• while x >= 0
x = x - 1
PYTHON SURVIVAL GUIDE 179
Python returns the error message SyntaxError: invalid syntax because the colon is missing after the
condition. It should be while x >= 0 :
• string = Hello world! returns an error because the quotation marks to define the string are
missing.
• print("Hi there" Python returns the error message SyntaxError: unexpected EOF while parsing
because the expression is incorrectly parenthesized.
• if val = 1: Another syntax error, because you would have to write if val == 1:
def product(a,b):
return a*b
Returns an error NameError: name ’product’ is not defined because a function must be defined before it
can be used.
PYTHON SURVIVAL GUIDE 180
5.5. Exercise
Fix the code! Python should display 7 5 9.
a == 7
if (a = 2) or (a >= 5)
b = a - 2
c = a + 2
else
b = a // 2
c = 2 * a
print(a b c)
25
Main functions
1. Mathematics
Classical operations
• a + b, a - b, a * b classic operations
• a / b “real” division (returns a floating point number)
• a // b Euclidean division quotient (returns an integer)
• a % b remainder of the Euclidean division, called a modulo b
• abs(x) absolute value
• x ** n power x n
• 4.56e12 for 4.56 × 1012
Module “math”
The use of other mathematical functions requires the module math which is called by the command:
from math import *
p
• sqrt(x) square root x
• cos(x), sin(x), tan(x) trigonometric functions cos x, sin x, tan x in radians
• pi approximate value of π = 3.14159265 . . .
• floor(x) integer just below x
• ceil(x) integer just above x
• gcd(a,b) gcd of a and b
Module “random”
The random module generates numbers in a pseudo-random way. It is called by the command:
from random import *
• random() on each call, returns a floating number x at random satisfying 0 6 x < 1.
• randint(a,b) for each call, returns an integer n at random satisfying a 6 n 6 b.
• choice(mylist) on each call, randomly draws an item from the list.
• mylist.shuffle() mixes the list (the list is modified).
Binary notation
• bin(n) returns the binary notation of the integer n as a string. Example: bin(17) returns
'0b10001'.
• To write a number directly in binary notation, simply write the number starting with 0b (without
quotation marks). For example 0b11011 is equal to 27.
MAIN FUNCTIONS 182
2. Booleans
A boolean is a data that takes either the value True or the value False.
Comparisons
The following comparison tests return a boolean.
• a == b equality test
• a < b strict lower test
• a <= b large lower test
• a > b or a >= b higher test
• a != b non-equality test
Do not confuse “a = b” (assignment) and “a == b” (equality test).
Boolean operations
• P and Q logical “and”
• P or Q logical “or”
• not P negation
3. Strings I
Chains
• "A" or 'A' one character
• "Python" or 'Python' a string
• len(string) the string length. Example: len("Python") returns 6.
• string1 + string2 concatenation.
Example: "I love" + "Python" returns "I lovePython".
• string[i] returns the i-th character of string (numbering starts at 0).
Example with string = "Python", string[1] is equal to "y". See the table below.
Letter P y t h o n
Rank 0 1 2 3 4 5
Number/string conversion
• Chain. str(number) converts a number (integer or floating point number) into a string. Examples:
str(7) returns the string "7"; str(1.234) returns the string "1.234".
• Integer. int(string) returns the integer corresponding to the string. Example: int("45") re-
turns the integer 45.
• Floating point number. float(string) returns the floating point number corresponding to the
string. Example: float("3.14") returns the number 3.14.
Substrings
• string[i:j] returns the substring of characters with a rank of i to j − 1 from string.
Example: with string = "This is a string", string[2:7] returns "is is".
• string[i:] returns characters with a rank of i until the end of string.
Example : string[5:] returns "is a string".
• string[:j] returns characters from the beginning to the rank j − 1 of string. Example:
string[:4] returns "This".
MAIN FUNCTIONS 183
Format
The format() method allows you to format text or numbers. This function returns a string.
• Text
4. Strings II
Encoding
• chr(n) returns the character associated with the ASCII/unicode code number n. Example: chr(65)
returns "A"; chr(97) returns "a".
• ord(c) returns the ASCII/unicode code number associated with the character c. Example:
ord("A") returns 65; ord("a") returns 97.
The beginning of the ASCII/unicode table is given below.
MAIN FUNCTIONS 184
39 ’ 49 1 59 ; 69 E 79 O 89 Y 99 c 109 m 119 w
Upper/lower-case
• string.upper() returns a string in upper case.
• string.lower() returns a string in lowercase.
Search/replace
• substring in string returns “true” or “false” depending on if substring appears in string.
Example : "NOT" in "TO BE OR NOT TO BE" returns True.
• string.find(substring) returns the rank at which the substring was found (and -1 otherwise).
Example: with string = "ABCDE", string.find("CD") returns 2.
• string.replace(substring,new_substring) replaces each occurrence of the substring by
the new substring.
Example: with string = "ABCDE", string.replace("CD","XY") returns "ABXYE".
Split/join
• string.split(separator) separates the string into a list of substrings (by default the separator
is the space).
Examples:
– "To be or not to be.".split() returns ['To', 'be', 'or', 'not', 'to', 'be.']
– "12.5;17.5;18".split(";") returns ['12.5', '17.5', '18']
• separator.join(mylist) groups the substrings into a single string by adding the separator
between each.
Examples:
– "".join(["To", "be", "or", "not", "to", "be."]) returns 'Tobeornottobe.'
Spaces are missing.
– " ".join(["To", "be", "or", "not", "to", "be."]) returns 'To be or not to
be.' It’s better when the separator is a space.
– "--".join(["To", "be", "or", "not", "to", "be."]) returns 'To--be--or--not--to--be.'
MAIN FUNCTIONS 185
5. Lists I
Construction of a list
Examples:
• mylist1 = [5,4,3,2,1] a list of integers 5.
• mylist2 = ["Friday","Saturday","Sunday"] a list of 3 strings.
• mylist3 = [] the empty list.
• list(range(n)) list of integers from 0 to n − 1.
• list(range(a,b)) list of integers from a to b − 1.
• list(range(a,b,step)) list of integers from a to b − 1, with a step given by the integer step.
Get an item
• mylist[i] returns the element of rank i. Be careful, the rank starts at 0.
Example: mylist = ["A","B","C","D","E","F"] then mylist[2] returns "C".
• mylist[-1] returns the last element, mylist[-2] returns the second last element. . .
• mylist.pop() removes the last item from the list and returns it.
Example of construction. Here is how to build the list that contains the first squares:
Browse a list
• len(mylist) returns the length of the list. Example: len([5,4,3,2,1]) returns 5.
• Just browse a list (and here display each item):
for element in mylist:
print(element)
• Browse a list using the rank.
MAIN FUNCTIONS 186
n = len(mylist)
for i in range(n):
print(i,mylist[i])
6. Lists II
Mathematics
• max(mylist) returns the largest element. Example: max([10,16,13,14]) returns 16.
• min(mylist) returns the smallest element. Example: min([10,16,13,14]) returns 10.
• sum(mylist) returns the sum of all elements. Example: sum([10,16,13,14]) returns 53.
Slicing lists
• mylist[a:b] returns the sublist of elements from the rank a to the rank b − 1.
• mylist[a:] returns the list of elements of rank a until the end.
• mylist[:b] returns the list of items from the beginning to the rank b − 1.
Order
• sorted(mylist) returns the ordered list of items.
Example: sorted([13,11,7,4,6,8,12,6]) returns the list [4,6,6,7,8,11,12,13].
• mylist.sort() does not return anything but the list mylist is now ordered.
Invert a list
Here are three methods:
• mylist.reverse() modifies the list in place;
• list(reversed(mylist)) returns a new list;
• mylist[::-1] returns a new list.
Delete an item
Three methods.
MAIN FUNCTIONS 187
List comprehension
• Let’s start from a list, for example mylist = [1,2,3,4,5,6,7,6,5,4,3,2,1].
• list_doubles = [ 2*x for x in mylist ] returns a list that contains the doubles of the
items of mylist. So this is the list [2,4,6,8,...].
• liste_squares = [ x**2 for x in mylist ] returns the list of squares of the items in the
list mylist. So this is the list [1,4,9,16,...].
• partial_list = [ x for x in mylist if x > 2 ] extracts from the list only the elements
greater than 2. So this is the list [3,4,5,6,7,6,5,4,3].
List of lists
Example:
array = [ [2,14,5], [3,5,7], [15,19,4], [8,6,5] ]
corresponds to the table:
index j
i=0 2 14 5
i=1 3 5 7
index i
i=2 15 19 4
i=3 8 6 5
Then array[i] returns the sublist of rank i, and array[i][j] returns the element located in the sublist
number i, at rank j of this sublist. For example:
• array[0] returns the sublist [2,14,5].
• array[1] returns the sublist [3,5,7].
• array[0][0] returns the integer 2.
• array[0][1] returns the integer 14.
• array[2][1] returns the integer 19.
A table of n rows and p columns.
• array = [[0 for j in range(p)] for i in range(n)] initializes an array and fills it
with 0.
• array[i][j] = 1 modifies a value in the table (the one at the location (i, j)).
MAIN FUNCTIONS 188
7. Input/output
Display
• print(string1,string2,string3,...) displays strings or objects. Example: print("Value
=",14) displays Value = 14. Example: print("Line 1 \n Line 2") displays on two lines.
• Separator. print(...,sep="...") changes the separator (by default the separator is the space
character). Example: print("Bob",17,13,16,sep="; ") displays Bob; 17; 13; 16.
• End of line. print(...,end="...") changes the character placed at the end (by default it is
the line break \n). Example print(17,end="") then print(76) displays 1776 on a single line.
Keyboard entry
input() pauses the program and waits for the user to send a message on the keyboard (end by pressing
the “Enter” key). The message is a string.
Here is a small program that asks for the user’s first name and age and displays a message like “Hello Kevin”
then “You are a minor/adult” according to age.
first_name = input ("What's your name? ")
print("Hello",first_name)
8. Files
Order
• fi = open("my_file.txt","r") opening in reading ("r" = read).
• fi = open("my_file.txt","w") opening in writing ("w" = write). The file is created if it does
not exist, if it existed the previous content is first deleted.
• fi = open("my_file.txt","a") opening for writing, the data will be written at the end of the
current data ("a" = append).
• fi.write("one line") write to the file.
• fi.read() reads the whole file (see below for another method).
• fi.readlines() reads all the lines (see below for another method).
• fi.close() file closing.
fi.write("Hello world!\n")
fi.close()
fi.close()
9. Turtle
The turtle module is called by the command:
from turtle import *
Main commands
• forward(length) advances a number of steps
• backward(length) goes backwards
• right(angle) turns to the right (without advancing) at a given angle in degrees
• left(angle) turns left
• setheading(direction) points in one direction (0 = right, 90 = top, −90 = bottom, 180 = left)
• goto(x,y) moves to the point (x, y)
• setx(newx) changes the value of the abscissa
• sety(newy) changes the value of the ordinate
• down() sets the pen down
• up() sets the pen up
• width(size) changes the thickness of the line
• color(col) changes the color: "red", "green", "blue", "orange", "purple". . .
• position() returns the (x, y) position of the turtle
• heading() returns the direction angle to which the turtle is pointing
• towards(x,y) returns the angle between the horizontal and the segment starting at the turtle and
ending at the point (x, y)
• speed("fastest") maximum travel speed
• exitonclick() ends the program as soon as you click
Several turtles
Here is an example of a program with two turtles.
MAIN FUNCTIONS 190
turtle1.color('red')
turtle2.color('blue')
turtle1.forward(100)
turtle2.left(90)
turtle2.forward(100)
10. Matplotlib
With the matplotlib module it is very easy to draw a list. Here is an example.
mylist1 = [3,5,9,8,0,3]
mylist2 = [4,7,7,2,8,9]
plt.plot(mylist1,color="red")
plt.plot(mylist2,color="blue")
plt.grid()
plt.show()
Main functions.
• plt.plot(mylist) traces the points of a list (in the form (i, `i )) that are linked by segments.
• plt.plot(list_x,list_y) traces the points of a list (in the form of (x i , yi ) where x i browses the
first list and yi the second).
• plt.scatter(x,y,color='red',s=100) displays a point in (x, y) (of a size s).
• plt.grid() draws a grid.
• plt.show() displays everything.
• plt.close() exits the display.
MAIN FUNCTIONS 191
11. Tkinter
11.1. Graphics
To display this:
# A rectangle
canvas.create_rectangle(50,50,150,100,width=2)
# An ellipse
canvas.create_oval(50,110,180,160,width=4)
# Some text
canvas.create_text(400,75,text="Bla bla bla bla",fill="blue")
• Attention! The window’s graphic marker has its y-axis pointing downwards. The origin (0, 0) is the
top left corner (see figure below).
• Command to draw a rectangle: create_rectangle(x1,y1,x2,y2); just specify the coordinates
(x 1 , y1 ), (x 2 , y2 ) of two opposite vertices. The option width adjusts the thickness of the line, outline
defines the color of this line, fill defines the filling color.
• An ellipse is traced by the command create_oval(x1,y1,x2,y2), where (x 1 , y1 ), (x 2 , y2 ) are the
coordinates of two opposite vertices of a rectangle framing the desired ellipse (see figure). A circle is
obtained when the corresponding rectangle is a square!
• Text is displayed by the command canvas.create_text(x,y,text="My text") specifying the
coordinates (x, y) of the point from which you want to display the text.
(0, 0) x
(x 1 , y1 )
(x 2 , y2 )
(x 1 , y1 )
(x 2 , y2 )
y
11.2. Buttons
It is more ergonomic to display windows where actions are performed by clicking on buttons. Here is the
window of a small program with two buttons. The first button changes the color of the rectangle, the second
button ends the program.
root = Tk()
canvas = Canvas(root, width=400, height=200, background="white")
canvas.pack(fill="both", expand=True)
def action_button():
canvas.delete("all") # Clear all
colors = ["red","orange","yellow","green","cyan","blue","violet","purple"]
col = choice(colors) # Random color
canvas.create_rectangle(100,50,300,150,width=5,fill=col)
return
root.mainloop()
Some explanations:
• A button is created by the command Button. The text option customizes the text displayed on the
button. The button created is added to the window by the method pack.
• The most important thing is the action associated with the button! It is the option command that
receives the name of the function to be executed when the button is clicked. For our example
command=action_button, associate the click on the button with a change of color.
• Attention! You have to give the name of the function without brackets: commande=my_function
and not command=my_function().
• To associate the button with “Quit” and close the window, the argument is command=root.quit.
• The instruction canvas.delete("all") deletes all drawings from our graphic window.
11.3. Text
Here’s how to display text with Python and the graphics window module tkinter.
(0, 0) x
(x 1 , y1 )
(x 2 , y2 )
y
# Window
root = Tk()
canvas = Canvas(root, width=800, height=600, background="white")
canvas.pack(side=LEFT, padx=5, pady=5)
x = event.x
y = event.y
canvas.create_rectangle(x,y,x+10,y+10,fill="red")
print("Click at x =",x,", y =",y)
return
# Association click/action
canvas.bind("<Button-1>", action_mouse_click)
# Launch
root.mainloop()
Here are some explanations:
• The creation of the window is usual. The program ends with the launch by the command mainloop().
• The first key point is to associate a mouse click to an action, that’s what the line does:
canvas.bind("<Button-1>", action_mouse_click)
Each time the left mouse button is clicked, Python executes the function action_mouse_click.
(Note that there are no brackets for the call to the function.)
• Second key point: the action_mouse_click function retrieves the click coordinates and then does
two things here: it displays a small rectangle at the click location and displays the (x, y) coordinates
in the terminal window.
• The coordinates x and y are expressed in pixels; (0, 0) refers to the upper left corner of the window
(the area delimited by canvas).
11.5. Movement
Here is a program that moves a small square and bounces it off the edges of the window.
the_width = 400
the_height = 200
root = Tk()
canvas = Canvas(root, width=the_width, height=the_height, background="white")
canvas.pack(fill="both", expand=True)
# Main function
def mymove():
global x0, y0, dx, dy
x0 = x0 + dx # New abscissa
y0 = y0 + dy # New ordinate
canvas.coords(rect,x0,y0,x0+20,y0+20) # Move
return
# Buttons
button_move = Button(root,text="Move", width=20, command=action_move)
button_move.pack(pady=10)
root.mainloop()
Chapter
26
Notes and references
You will find here comments and readings on each of the activities.
General resources
• The official documentation of Python contains tutorials and explanations of each of the functions.
docs.python.org/3/
• Wikipedia is a reliable source for learning more about some concepts (mainly projects) but the level is
not always suitable for a high school student.
• Internet and in particular the forums often have the answer to the questions you ask yourself!
• The most experienced among you can participate in the Euler project which offers a list of mathematics-
with-computer puzzles. Hang on! Hang on!
projecteuler.net
1. Hello world
Learning a programming language can be very difficult. It’s hard enough to learn alone in your own corner.
It is not uncommon to stay blocked for several hours for a stupid syntax error. You have to start small, don’t
hesitate to copy code already written by others, be persistent and ask for help quickly!
4. Functions
Quite quickly it is necessary to understand the structure of a computer program: the program is broken
down into blocks of definitions and simple actions. Simple actions are grouped into intermediate actions.
And at the end the main program is just to perform some good functions.
The arguments/parameters of a function are a delicate learning process. You can define a function by def
func(x): and call it by func(y). The x corresponds to a dummy mathematical variable. In computing,
we prefer to talk about the scope of the variable which can be local or global.
What we can remember is that nothing that happens within a function is accessible outside the function. You
just have to use what the function returns. It is necessary to avoid the use of global in the first instance.
Last but not least, it is really important to comment extensively on your code and explain what your functions
are doing. If you define a function func(x), plan three lines of comments to (a) say what this function
does, (b) say what input is expected (x must be an integer? a floating point number ? positive?. . . ), (c) say
what the function returns.
It is also necessary to comment on the main points of the code, give well-chosen names to the variables.
You’ll be happy to have a readable code when you come back to your code again later!
A good computer scientist should check that the parameter passed as an argument verifies the expected
hypothesis. For example if func(x) is defined for an integer x and the user transmits a string, then a nice
warning message should be sent to the user without causing the whole program to fail. The commands
assert, try/except allow to manage this kind of problem. For our part, we will refrain from these checks
assuming that the user/programmer uses the functions and variables in good intelligence.
NOTES AND REFERENCES 199
7. Lists I
Python is particularly flexible and agile for using lists. The “old” languages often only allowed lists containing
a single type of element, and to browse a list you always had to do this:
for i in range(len(mylist)):
print(mylist[i])
While:
for element in mylist:
print(element)
is much more natural.
Sorting a list is a fundamental operation in computer science. Would you imagine a dictionary containing
60 000 words, but not sorted in alphabetical order? Sorting a list is a difficult operation, there are many sorting
algorithms. The bubble sort algorithm presented here is one of the simplest. Programming faster algorithms
in high school is a great challenge: you have to understand recursivity and the notion of complexity.
9. Files
The files make it possible to communicate Python with the outside world: for example, you can retrieve a
file of grades to calculate the averages and produce a report card for each student.
The activities on the images are nice and these image formats will be used later, even if this format has the
big disadvantage of producing large files. Nevertheless they are standard and recognized by image software
(Gimp for example). Note that some software writes files with only one data per line (or all data on a single
line). It is a good exercise to implement the reading of all possible formats.
11. Binary I
The first difficulty with binary notation is to make a good distinction between a number and writing the
number. We are so used to decimal numeral system that we forgot its origin, 1234 is just 1 × 1000 + 2 ×
100 + 3 × 10 + 4 × 1. As computers work with 0 and 1 you have to be comfortable with binary numeral
system. The transition to binary notation is not very difficult, but it is still better to make a few examples by
hand before starting the programming.
Binary writing will be used for other problems on the following principle: you have 4 switches so 1.0.0.1
means that you activate the first and last switch and not the others.
12. Lists II
Lists are so useful that Python has a whole efficient syntax to manage them: list slicing and list comprehen-
sion. We could of course do without it (which is the case for most other languages) but it would be a pity.
We will also need lists of lists and in particular arrays to display beautiful images.
13. Binary II
There are 10 kinds of people, those who understand binary and others!
NOTES AND REFERENCES 201
5 4
+ 3
18. L-systems
We come back to the theme “find/replace” but this time with a geometric vision. The figures obtained
are beautiful, easy to program using the turtle, but the most beautiful is to see in live the layout from the
L-systems. For L-systems defined by expressions containing brackets, we find again the notion of stacks.
The formulas are taken from the book The algorithmic beauty of plants, by P. Prusinkiewicz and A. Lindenmayer
(Springer-Verlag, 2004) with free access here: The algorithmic beauty of plants (pdf).
The illustrations that begin each part of this book are iterations of the L-system called the Hilbert curve and
defined by:
start = "X" rule1 = ("X","lYArXAXrAYl") rule2 = ("Y","rXAlYAYlAXr")
22. Bitcoin
Before investing all your savings in bitcoins it is better to understand how it works! The activities presented
here are intended to present a (very) simplified version of the blockchain that is the basis of this virtual
currency. The principle of the blockchain and the proof of work are not so complicated.
NOTES AND REFERENCES 203
You can retrieve all the activity codes Python and all the source files on the Exo7 GitHub page: “GitHub :
Python in high school”.
Exo7
π, 5 chr, 45
**, 2 click, 144
+=, 36 close, 68
=, 3, 21 comments, 3
#, 3 concatenation, 26, 40, 51
!=, 21 cos, 5
//, 33 csv, 70
<=, 21
def, 24
==, 21
degrees, 76
>=, 21
del, 53
%, 33
digits, 21
abs, 6 distance, 42, 74
absolute value, 6 divisor, 36
and, 21, 96 DNA, 43
angle, 76 docstring, 27
append, 50 down, 10
argument, 27, 127
else, 18
array, 90
entry, 19
ascii, 44
Euclidean division, 2, 33
assignment, 3, 21
eval, 118
average, 59, 66
expected value, 99
ballistics, 56
False, 21
base 10, 82
file, 68
bin, 86
find, 102
binary, 82, 95, 150
first number, 36
bitcoin, 155
float, 69
bits, 83
floating point number, 2
blockchain, 157
floor, 5
boolean, 21
font, 120
break, 80
for, 6, 42, 51
button, 63
forward, 9
calculation time, 37, 156 function, 24
character, 40 argument, 27
character encoding, 44 docstring, 27
choice, 69 hash, 158
optional argument, 127 while, 34
parameter, 24
return, 27, 175 magic square, 91
markdown, 120
game of life, 140 math, 5
gcd, 5 matplotlib, 55
global, 108 max, 59
Goldbach, 77 median, 64
goto, 10 min, 59
graph, 146 mining, 160
graphic, 9, 60 module, 5
math, 5
hash, 158 matplotlib, 55
if, 18 random, 19
if/then, 18
re, 103
image, 71, 134
time, 156
import, 5 timeit, 37
in, 6, 42, 89, 102 tkinter, 60, 119, 144, 169
indentation, 6
turtle, 9
modulo, 2, 33
index, 89, 102
Morgan’s laws, 97
input, 19
mouse, 144
int, 19, 69
interest, 51 None, 44
isdigit, 110 not, 21, 96
join, 110 not in, 42