Example solutions for script 04_looping exercise blocks 4 and 5

Exercise 4.2

Replacing while i < n: by if i < n: would execute the following code block only once if the condition is true.

Exercise 4.3

My solution for 1.4 was:

n = 11
acc = 0

for j in range(n):
    acc = acc + 2 ** j
    
print(acc)
2047

If we use while we have to implement the couting which is done by for automatically. So we introduce the variable j which starts with 0, we iterate up to n - 1 and must not forget to increase this counter at the end of the code block after while:

n = 11
acc = 0

j = 0
while j < n:
    acc = acc + 2 ** j
    j = j + 1
    
print(acc)
2047

The rewritten solution of 2.3.B is:

n = 5

odd_numbers_added = 0
even_numbers_added = 0

i = 1
while i <= n:
    if i % 2 == 1:
        odd_numbers_added = odd_numbers_added + i
    else:
        even_numbers_added = even_numbers_added + i
    i = i + 1
        
print(even_numbers_added, odd_numbers_added)
6 9

Exercise 5.2

In case the user enters "x" at the beginning the count is zero and the computation of the average is not defined. We handle this case explicitly.

If you test your programs do not forget to test corner cases !!!

summed = 0
count = 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)
    count = count + 1

if count > 0:
    average = summed / count
else:
    average = "not computable"
    
print("you provided", count, "numbers. their sum is", summed, "and the average is", average)
please input a number, use 'x' or 'X' to finish: x
you provided 0 numbers. their sum is 0 and the average is not computable

Exercise 5.4

The integier division // produces an integer. If you use regular division / we get "ugly" floating point values with trailing .0 in the output:

n = int(input("n = ? "))

length = 1
while n != 1:
    print(n, end=" ")
    if n % 2 == 0:
        n = n // 2
    else:
        n = 3 * n + 1
    length += 1
print(1)
print("collatz sequence has length", length)
n = ? 17
17 52 26 13 40 20 10 5 16 8 4 2 1
collatz sequence has length 13

Exercise 5.5

a = int(input("a ? "))
b = int(input("b ? "))
while a != b:
    if a > b:
        a = a - b
    else:
        b = b - a
print("gcd is", a)
a ? 94
b ? 106
gcd is 2

Exercise 5.6

summed = 0
count = 0

number = input("please input a number, use 'x' or 'X' to finish: ")
   
while number != "x" and number != "X":
    summed = summed + float(number)
    count = count + 1
    number = input("please input a number, use 'x' or 'X' to finish: ")

if count > 0:
    average = summed / count
else:
    average = "not computable"
    
print("you provided", count, "numbers. their sum is", summed, "and the average is", average)
please input a number, use 'x' or 'X' to finish: 1
please input a number, use 'x' or 'X' to finish: 2
please input a number, use 'x' or 'X' to finish: 3
please input a number, use 'x' or 'X' to finish: x
you provided 3 numbers. their sum is 6.0 and the average is 2.0

Exercise 5.7 + 5.8

The following snippet tries to solve the computation of the largest of the given input values (I stripped the other computations so we can focus on the actual problem).

If you test it you will see that it fails if the user enters x at the beginning, or if the user provides only numbers small than -1000:

max_so_far = -1000
   
while True:
    number = input("please input a number, use 'x' or 'X' to finish: ")
    if number == "x" or number == "X":
        break
    
    number = float(number)
    if number > max_so_far:
        max_so_far = number

print("the maximum of the provided numbers is", max_so_far)
please input a number, use 'x' or 'X' to finish: -2000
please input a number, use 'x' or 'X' to finish: x
the maximum of the provided numbers is -1000

Even if you change the initial value -1000 the problem is not solved, you always find user inputs which break the computation.

So the actual problem is to find a proper starting value for max_so_far.

For this we must handle the first input differently to the other inputs. Either we use a separate input for the first value, or we need an extra variable to track if the current input is the first input or another one.

So try to understand the following solutions and then read the preceeding sentences again !

"""
here we use an extra input for the first value
"""

summed = 0
count = 0

number = input("please input a number, use 'x' or 'X' to finish: ")

if number != "x" and number != "X":
    max_so_far = float(number)
    
while number != "x" and number != "X":
    summed = summed + float(number)
    count = count + 1
    number = input("please input a number, use 'x' or 'X' to finish: ")
    if number != "x" and number != "X":
        number = float(number)
        if number > max_so_far:
            max_so_far = number

if count > 0:
    average = summed / count
else:
    average = "not computable"
    max_so_far = "unknown"
    
print("you provided", count, "numbers. their sum is", summed, "and the average is", average)
print("further the maximum of the provided numbers is")
please input a number, use 'x' or 'X' to finish: x
you provided 0 numbers. their sum is 0 and the average is not computable
further the maximum of the provided numbers is

If you use an infinite while loop instead you have to follow a different strategy to handle the input of the first value:

"""
here we use an start value with a different type to distinguish the first from the other inputs
"""

summed = 0
count = 0

max_so_far = "unknown"
   
while True:
    number = input("please input a number, use 'x' or 'X' to finish: ")
    if number == "x" or number == "X":
        break
    
    number = float(number)
    summed = summed + number
    count = count + 1
    
    if max_so_far == "unknown":
        max_so_far = number
    elif number > max_so_far:
        max_so_far = number


if count > 0:
    average = summed / count
else:
    average = "not computable"
    
print("you provided", count, "numbers. their sum is", summed, "and the average is", average)
print("further the maximum of the provided numbers is", max_so_far)
please input a number, use 'x' or 'X' to finish: x
you provided 0 numbers. their sum is 0 and the average is not computable
further the maximum of the provided numbers is unknown

The solution below uses an extra indicator variable to handle the first input aproppriately:

"""
here we use an extra indictator variable (also called 'flag') to distinguish the first from the other inputs
"""

summed = 0
count = 0

max_so_far = 0
first_value_handled = False
   
while True:
    number = input("please input a number, use 'x' or 'X' to finish: ")
    if number == "x" or number == "X":
        break
    
    number = float(number)
    summed = summed + number
    count = count + 1
    
    if not first_value_handled:
        max_so_far = number
        first_value_handled = True
    elif number > max_so_far:
        max_so_far = number


if count > 0:
    average = summed / count
else:
    average = "not computable"
    
print("you provided", count, "numbers. their sum is", summed, "and the average is", average)
if first_value_handled:
    print("further the maximum of the provided numbers is", max_so_far)
else:
    print("further the maximum of the provided numbers is unknown")
please input a number, use 'x' or 'X' to finish: x
you provided 0 numbers. their sum is 0 and the average is not computable
further the maximum of the provided numbers is unknown

Exercise 5.9

This exercise was very tricky ! We have to use two variable to track the longest collatz sequence and the according valueof $n$. As the collatz loop changes $n$ we have to use anothe variable for the outer loop:

n_max = 100

max_length = 0
optimal_n = 0

for n_start in range(1, n_max + 1):

    length = 1
    n = n_start
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
        length += 1
        
    if length > max_length:
        max_length = length
        optimal_n = n_start
        
print("n =", optimal_n, "produces longest collatz sequence of length", max_length, "for starting values 2 ..", n_max)
n = 97 produces longest collatz sequence of length 119 for starting values 2 .. 100