```
from IPython.core.display import HTML
HTML(open("custom.html", "r").read())
```

We learned about:

- logical values
`True`

and`False`

of type`bool`

and how to combine them with operations`and`

,`or`

and`not`

- comparisons
`==`

,`!=`

,`<`

,`>`

,`<=`

and`>=`

which produce logical values - several ways of branching with
`if`

,`elif`

and`else`

.

`+=`

¶Increasing a given value like `sum = sum + i`

is a common task in programming. Thus Python offers the abbreviation `sum += i`

.

```
a = 7
a += 3
print(a)
```

We will use both versions in the script, sometimes `sum = sum + ...`

is more readable.

`for`

¶Looping means that we instruct the Python interpreter to repeat execution of a given code block multiple times. We had a simple example in the first script when we introduced how to compute the sum of the first `n`

natural numbers:

```
n = 3
acc = 0
i = 0
for x in range(n):
i += 1
acc = acc + i
print("the sum of the first", n, "natural numbers is", acc)
```

`for x in range(Y):`

instructs the Python interpreter to execute the succeeding code block `Y`

times.
We name this code block **the body of the (for) loop**.

```
for x in range(3):
print("hi")
```

`x`

we use above is the so called **loop counting variable**. You can choose other valid variable names instead of `x`

. The key point is that this variable changes for every iteration. During the first execution of the body this variable has the value `0`

, during the second iteration it has value `1`

and so on:

```
for i in range(4):
print("i is", i)
```

So in general `range(n)`

iterates over values `0`

to `n - 1`

.

Knowing this we can simplify our script from above:

```
n = 3
acc = 0
for j in range(n):
acc = acc + j + 1
print("j is", j, "acc is", acc)
print("the sum of the first", n, "natural numbers is", acc)
```

Why do we use `j + 1`

above and just `j`

??

The `range`

function can be used with two arguments as `range(m, n)`

. Here iteration starts with `m`

and counts up to `n - 1`

. So **the upper limit is exclusive** (we will see this in other places again):

** Counting in Python starts with 0, upper limits are exclusive**.

(I' only aware of one exception for the "upper limits are exclusive" rule which I will mention below)

```
n = 3
acc = 0
for j in range(1, n + 1):
acc += j
print("j is", j, "acc is", acc)
print("the sum of the first", n, "natural numbers is", acc)
```

What does the following code compute ? Try to forecast the result using pen and paper, then use Python to check your result. The code has no practical application and just serves to check if you read the foregoing explanations carefully enough:

```
n = 2
k = 0
for i in range(3):
n = n * n
k = k + n + i
for i in range(3, 4):
n = n - i
print(n, k)
```

**Hint**: if your prediction is not correct, it helps to insert `print`

statements as follows, matching the output to the print statements assists in understanding the code:

```
n = 2
k = 0
for i in range(3):
n = n * n
k = k + n + i
print("i=", i, "n=", n, "k=", k) # this line is new
print() # this line is new
print("n=", n, "k=", k) # this line is new
print() # this line is new
for i in range(3, 4):
n = n - i
print("i=", i, "n=", n) # this line is new
print(n, k)
```

The plain `print()`

statements create empty lines which increases the readability of the output.

- Reread the explanations above, type and run the code examples.
- Modify the previous script so that the sum of the first
`n`

square numbers`1 + 4 + 9 + ..`

is computed. - Modify the previous script so that the product of the first
`n`

natural numbers is computed. - Can you compute
`1 + 2 + 4 + 8 + 16 + .. + 1024`

using a`for`

loop ? (The correct answer is`2047`

) Do you remember what happens if we multiply a number with a string ? We introduced this in solution proposals for script 03. Use

`for`

loops to produce the following figure:`* ** *** **** *****`

Display the following triangle with

`for`

and`print`

. (string addition is your friend):`* *** ***** *******`

Extend both so the user can provide the height of the triangles.

Up to now the body of a loop of a branch consisted of one block showing the same indentation. But we can extend this when we loop over a code block which in turn has a branched flow of execution.

For example we can extend our example above to compute the sum of the odd numbers among the first `n`

natural numbers:

```
n = 5
odd_numbers_added = 0
for i in range(1, n + 1):
if i % 2 != 0:
# division remainder != 0 means not a multiple of two
odd_numbers_added = odd_numbers_added + i
print(odd_numbers_added)
```

Explanations:

**The body of the for statement above consists of the two succeeding lines**, the

`if`

statement has a body of one line.- in the first iteration
`i`

is`1`

, so the`if`

condition is`True`

, so`odd_numbers_added`

is set to`1`

. We reach the end of the body of`for`

so execution continues with`for`

. - in the second iteration
`i`

is`2`

, so the`if`

condition is`False`

, so the block of`if`

is skipped. This finished the body of the`for`

statement, so we continue iterating. - in the third iteration
`i`

is`3`

, so the`if`

condition is`True`

, so`odd_numbers_added`

is set to`3`

. - ...

The last example demonstrated how we can nest and combine the statements we learned up to now. Code blocks may have an arbitrary number of lines and we may nest loop and branching statements as deep as required.

Statements as `for`

, `if`

, `elif`

and `else`

are followed by a **code block** comprising one or more lines. Such a code block may contain other nested code blocks marked by an increased indentation of the lines. To detect the span of such a more complex code block the following two rules are very helpful:

- the indentation of first line of a code block is crucial, (usually we use multiples of four spaces)
- as soon as the indentation of a line is lower than the initial indentation ...
- ... or if we reach the end of a script the code block ends.

Example:

```
for i in range(1, n + 1):
if i % 2 != 0:
# division remainder != 0 means not a multiple of two
odd_numbers_added = odd_numbers_added + i
print(odd_numbers_added)
```

Here the first line of the code block after `for`

is indented by four spaces, the second and third line by 8 spaces. Then zero spaces. So the code block ends before the `print`

and comprises the three lines

```
if i % 2 != 0:
# division remainder != 0 means not a multiple of two
odd_numbers_added = odd_numbers_added + i
```

The same procedure determines that the code block after `if`

has two lines:

```
# division remainder != 0 means not a multiple of two
odd_numbers_added = odd_numbers_added + i
```

Determine the extent of the code block after `for`

in the following snippet by applying the rules we introduced above.

```
s = 1
for xxx in range(6):
if xxx > 4:
s = s * xxx
elif xxx > 3:
s = s - xxx
else:
s += xxx
print(s)
```

What does the code compute ? Try to forecast the result using pen and paper, then use Python to check your result. Insert `print`

statements to understand the code if your result is not correct.

Comment: the code has no practical application and just serves to check if you read the foregoing explanations above carefully enough.

Some more difficult exercises in the script are marked as "optional", solving them is not required, but try to work on them if you have time to spare.

- Reread the explanations above, type and run the code.
- Modify the first example it to sum up the even numbers among the first
`n`

natural numbers - Extend it to compute the sum of the even as well as the sum of the odd numbers among the first
`n`

natural numbers. Write a separate script for each of the following strategies:- you compute both counts in sequence, so you have two loops in your script,
- you extend the
`if`

with an`else`

in the body of a single`for`

loop.

Write a program which prints numbers

`1`

to`10`

indicating whether the respective number is even. The expected output should be similar to`1 is odd 2 is even 3 is odd ...`

Write a Python program which produces the first 30 iterations of https://en.wikipedia.org/wiki/Fizz_buzz#Play Hint: you may need one

`if`

followed by two`elif`

s and one final`else`

statement for this.Find all numbers in the range

`1500`

to`2000`

(both limits included) which are multiples of $7$ and $13$.- (optional): What do the following program compute for a given number
`n`

? Run it for`n`

having values`2`

to`19`

and record the output. You should see a pattern. Do you understand now how this program works ?

```
n = 4
nip = True
for i in range(2, n):
if n % i == 0:
nip = False
print(nip)
```

As in `for`

loops, Python starts counting with `0`

in many places. For example the expression `"abcd"[0]`

computes the 0th character of the string `"abc"`

which is `a`

:

```
print("abc"[0])
print("abc"[1])
```

The string and the index in brackets can be variables:

```
txt = "abcde"
for i in range(len(txt)):
print("the", i, "th letter is", txt[i])
```

Type the examples above, play with them and try to understand them. What happens if the index is the same as the length of the string or larger, what do you get for indices

`-1`

, and`-2`

?Write a program which asks the user for a valid nucleotide sequence and prints all positions (starting with zero) of

`G`

symbols. You need`for`

for this. The output for input`GCCGGA`

should look like`found G at position 0 found G at position 3 found G at position 4`

Write a program which takes a string and counts the number of

`A`

s. Hint: iterate over all characters in the string and every time you see a`A`

increment a counting variable.Extend this to compute the relative

`GC`

content of a given DNA sequence.Write a program which reverses a given string. So "abcde" is transformed to "edcba". Idea: start with an empty string

`""`

and then use`+`

to prepend the input string character by character.

- Python was invented by the Dutch computer scientist Guido van Rossum in 1989 as a hobby project over Christmas.
- The name "Python" does not refer to a snake but to the "Monty Python Flying Circus", the official Python documentation often contains various obscure Monty Python references.
- The word
`spam`

which we use for junk email advertising is also based on a Monty Python sketch: https://en.wikipedia.org/wiki/Spam_(Monty_Python)#Impact - Development of Python is an open source project carried out by a team of volunteers.
- If you run
`import this`

you see the https://en.wikipedia.org/wiki/Zen_of_Python, a list of basic design principles of the language. - Try
`import antigravity`

. - Users and admirers of Python, especially those considered knowledgeable or experienced, are often referred to as Pythonists, Pythonistas, and Pythoneers.
- Python programs can be found in many places, check https://wiki.python.org/moin/OrganizationsUsingPython
- The Micro:bit micro-controller developed by BBC runs Python code and was given away to one million British pupils of age 11-12 in 2016: http://www.bbc.co.uk/programmes/articles/4hVG2Br1W1LKCmw8nSm9WnQ/the-bbc-micro-bit

Some reading tips:

`while`

.¶Python has an alternative way to loop. In contrast to a `for`

loop which executes a block of code for a given number of iterations, the `while`

loop repeats a code block as long as a given condition is `True`

.

```
i = 0
while i < 3:
print("Rule number", i + 1, ": Python is awesome")
i += 1
```

As you can see the `while`

keyword is followed by a logical expression and the line is again terminated with an `:`

.
The flow of execution is as follows:

- check if condition is
`True`

. - if this is the case execute the block
- jump back to
`while`

, check the condition again - if this is the case execute the block
- ...
- if the condition is
`False`

the code block after`while`

is skipped and the interpreter processes the lines after this block.

- the condition after
`while`

**IS ONLY CHECKED AT THE BEGINNING OF EVERY ITERATION**. - so if the condition becomes
`False`

during execution of the code block the computer will still complete the remaining lines in the code block. - if the condition is
`False`

from the beginning the code block is not executed at all !

You can rewrite all programs we had up to now from using `for`

to using `while`

. But you have to take care to increase the loop counting variable on your own, whereas `for`

does this automatically.

The next example is a simple transformation of an example above where we computed the sum using a `for`

loop. Compare both !

```
n = 3
i = 0
acc = 0
while i < n:
i += 1
acc = acc + i
print("the sum of the first", n, "natural numbers is", acc)
```

What does the following code snippet display ? Try to forecast the result using pen and paper, then use Python to check your result. If your prediction is not correct insert `print`

statements to find the reason:

```
s = 0
i = 1
while s < 16:
s += i
i = 2 * i
print(s, i)
while s >= 16:
s = 15
print(s)
i = i / 2
s = i + 1
```

- Reread the explanations above, type and run the code.
- What is the difference if you would write
`if i < n:`

instead of`while i < n:`

above? - Rewrite the solutions from exercises 4 from block 1 and exercise 3 from block 2 with
`while`

instead of`for`

.

`break`

to stop looping¶`break`

within the body of a loop (no matter whether this is a `for`

or a `while`

loop), the execution of the body will end immediately and the program execution continues after the body. A very simple example is:

```
for a in range(3):
print("a is", a)
break
print("this message will never be displayed")
print("after the for loop")
```

Or:

```
a = 11
while a < 1000:
print("a is", a)
break
print("this message will never be displayed")
print("after the while loop")
```

`break`

to break out from an infinite loop as follows:

```
summed = 0
while True:
number = input("please input a number, use 'x' or 'X' to finish: ")
if number == 'x' or number == 'X':
break
summed = summed + float(number)
print("the sum of the numbers you entered is", summed)
```

`while`

is always followed by a logical value. Usually we compute this logical value, e.g. as `a < 1000`

as we did above. If we provide the constant logical value `True`

the loop will be executed forever.

The only way to leave this infinite loop is by using `break`

as we did it above. You can see that this `break`

also works if it is nested within the `while`

loop.

What does the following code compute ? Try to forecast the result using pen and paper, then use Python to check your result. As always additional `print`

statements will help you to understand the code in case your prediction is not correct:

```
i = 1
s = 1
while i >= 0:
s = s + i
if s == 3:
break
print(i, s)
```

Extra question: where does the code block after `while`

start, where does it end ?

- Type and run the examples above and try to understand them !
- Extend the program so that additionally the numbers provided by the user are counted and the count is displayed in the end. Further compute and display the average of the numbers. Extend your program to also handle the case when the user immediately enters
`X`

. This is the so called "$3n + 1$" (or collatz) iteration:

- We start with a number $n$
- Replace $n$ by $\frac{n}{2}$ if $n$ is even, else replace $n$ by $3n + 1$
- Repeat step B until $n == 1$

So if we start with

`17`

this procedure computes values`17`

,`52`

,`26`

,`13`

,`40`

,`20`

,`10`

,`5`

,`16`

,`8`

,`4`

,`2`

,`1`

.Implement this procedure: ask the user for a starting value $n$ and print the intermediate values of

`n`

.Note: The still unproven

*Collatz conjecture*states that this procedure stops for every starting value $n$.- Extend your implementation to count the number of iterations needed to reach $1$.
Implement the algorithm for computing the greatest common divisor of two numbers which we introduced in the first script.

(optional) Rewrite the solution of 2. without using

`break`

. For this you have to change the`while True:`

statement to`while number != 'x' and number != 'X':`

, and you have to use`input`

twice: first before the`while`

and second within the body of the loop.(optional) Now extend it so that additionally the maximum of the provided numbers is determined and displayed in the end. Strategy: Use a variable

`max_so_far`

to track the "maximum of the numbers seen so far". The trick is to find an appropriate starting value.(optional) Alternative solution to 7.: Initialize

`max_so_far`

with the first given number. Then update this variable after every user input if the given number is larger than the "maximum seen so far".(optional) Which starting value $n$ up to 100 produces the longest collatz sequence ? Don't determine this manually. Hint: you need two variables to track the "longest sequence seen so far" when iterating over the start values in range $1 ... 100$. On variable tracks the length of the "best" sequence, the other one the corresponding starting value.

The two final exercises of this script are to implement two games.

- The computer creates a secret random number in the range
`1`

to`100`

- The user has to guess it. After every guess from the user the computer tells if the given number is to low, to high or correct. If the guess is correct the game ends, else this step is repeated.

- use pen and paper to write some "pseudo Python code" which plays the number guessing game. Check this by "executing" the pseudo code with pen and paper !

The only missing piece to implement this game is to compute a random number. Python ships with the `random`

module, this is how we use this:

```
import random
for i in range(5):
print(random.randint(3, 7)) # random number in range 3..7
```

`random.randint`

is the **only exception** I'm aware of where the upper limit is inclusive.

Else:

** Counting in Python starts with 0, upper limits are exclusive**.

- Run the last example a few times and see how the output changes.
- Implement the number guessing game in Python (to facilitate the development process display the secret number when generated). Hint: do not forget to use type conversion of the user input.
- Extend this program to count the number of guesses needed by the user
- If your program uses two
`input`

function calls reduce to on call this by using an infinite`while`

loop. - Extend your program to play multiple games: after a finished game the computer asks the user to play another game and a new game is started depending on the input. (tip: use an infinite loop around the existing code)
- Use random numbers to create a string with random characters
`A`

,`T`

,`G`

and`C`

of length 10. You need either`if`

-`elif`

-`else`

or clever string indexing to transform random numbers from`0`

to`3`

in to the corresponding characters. Start with an empty string and add character by character.

You remember the procedure for doing the repetition exercises as described at the end of script 01 ?

- Write a program which checks if a given number is prime.
- Write a program which reverts a given string

We already introduced https://en.wikipedia.org/wiki/Rock-paper-scissors in the previous script. Please repeat this before you go on.

The overall strategy to implement the game is:

- We ask the user to enter R, S or P.
- Then the computer chooses randomly a number 0, 1, 2 which we transform to R, S or P. You can generate the numbers using
`random.randint(0, 2)`

as we introduced for the number guessing game and then transform the number to the according symbol. - Then we compute the outcome of the game and display the result.

- Implement one iteration the game: ask the user, create an random computer move and display the outcome.
- Write Python code which uses an infinite
`while`

loop to ask the user until he enters one of`R`

,`S`

or`P`

. In case of invalid input print a message before you ask again. Combine this with the solution from the previous step and test it. - Allow the user to play as many games as wanted: In addition to R, S and P allow the user to enter X to stop playing.
- Extend the previous exercise to count the number of ties, player wins and computer wins and display a final message indicating these numbers and the final winner of the game.

```
```

```
```