You are on page 1of 10

3.

4 Exercises 97

25
20
15
10
y

5
0
5
10
40 30 20 10 0 10
x
Fig. 3.2 One realization of a random walk (N-E-S-W) with a 1000 steps. Initial and final
positions are marked in blue with a circle and a star, respectively.

3.4 Exercises

Exercise 3.1: A for loop with errors


Assume some program has been written for the task of adding all integers
i = 1, 2, . . . , 10 and printing the final result:
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
sum = Sum + x
print ’sum: ’, sum

a) Identify the errors in the program by just reading the code.


Solution. The variable sum is not initialized to zero. Also, that variable
is written with a capital S inside the loop, which gives an error, since
sum and Sum will be regarded as two different variables by Python. The
list in the loop header ends with ) in stead of ]. In addition, the header
must end with a colon. Within the loop, the single statement should be
indented by the recommended 4 spaces, and x is used in stead of i. The
print command is written with wrong syntax (Python 2.7).
b) Write a new version of the program with errors corrected. Run this
program and confirm that it gives the correct output.
98 3 Loops and branching

Solution. The code reads:


sum = 0
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum + i
print(’sum: {:g}’.format(sum))

Running the program gives the correct number 55 as the answer.


Filename: for_loop_errors.py.

Exercise 3.2: The range function


Write a slightly different version of the program in exercise 3.1. Now, the
range function should be used in the for loop header, and only the even
numbers from [2, 10] should be added. Also, the (only) statement within
the loop should read sum = sum + i.
Solution. The code reads:
sum = 0
for i in range(2, 11, 2):
sum = sum + i
print(’sum: {:g}’.format(sum))

Running the code gives the correct number 30.


Filename: range_function.py.

Exercise 3.3: A while loop with errors


Assume some program has been written for the task of adding all integers
i = 1, 2, . . . , 10:
some_number = 0
i = 1
while i < 11
some_number += 1
print some_number

a) Identify the errors in the program by just reading the code.


Solution. There is a missing colon at the end of the while loop header.
Within the loop, some_number is updated by adding 1 instead of i.
Finally, there is no update of the loop variable i, and the print command
is written with wrong syntax (Python 2.7).
b) Write a new version of the program with errors corrected. Run this
program and confirm that it gives the correct output.
3.4 Exercises 99

Solution. The code reads:


some_number = 0;
i = 1
while i < 11:
some_number += i
i += 1
print(some_number)

Running the program gives 55 as the correct answer.


Filename: while_loop_errors.py.

Exercise 3.4: While loop instead of for loop


Rewrite average_height.py from Chapter 3.1.3, using a while loop
instead.
Solution. The modified code reads:
import numpy as np

N = 5
h = np.zeros(N) # heights of family members (in meter)
h[0] = 1.60; h[1] = 1.85; h[2] = 1.75; h[3] = 1.80; h[4] = 0.50

sum = 0
i = 0
while i <= 4:
sum = sum + h[i]
i = i + 1
average = sum/N

print(’Average height: {:g} meter’.format(average))

Filename: while_instead_of_for.py.

Exercise 3.5: Compare integers a and b


Explain briefly, in your own words, what the following program does.
a = int(input(’Give an integer a: ’))
b = int(input(’Give an integer b: ’))

if a < b:
print(’\na is the smallest of the two numbers’)
elif a == b:
print(’\na and b are equal’)
else:
print(’\na is the largest of the two numbers’)
100 3 Loops and branching

Proceed by writing the program, and then run it a few times with
different values for a and b to confirm that it works as intended. In
particular, choose combinations for a and b so that all three branches of
the if construction get tested.
Solution. The program takes two integers as input and checks if the
number a is smaller than b, equal to b, or larger than b. A message is
printed to the screen in each case.
Filename: compare_a_and_b.py.
Remarks. The program is not too robust, since it assumes the user types
an integer as input (a real number gives trouble).

Exercise 3.6: Area of rectangle versus circle


Consider one circle and one rectangle. The circle has a radius r = 10.6.
The rectangle has sides a and b, but only a is known from the outset. Let
a = 1.3 and write a program that uses a while loop to find the largest
possible integer b that gives a rectangle area smaller than, but as close
as possible to, the area of the circle. Run the program and confirm that
it gives the right answer (which is b = 271).
Solution. The code reads:
import math as m

r = 10.6
a = 1.3 # one side of rectangle
circle_area = m.pi*r**2

b = 0 # chosen starting value for other side of rectangle


while a*b < circle_area:
b += 1
b -= 1 # must reverse the last update to get the right value
print(’The largest possible value of b: {:d}’.format(b))

Running the program gives 271 as output for b.


Filename: area_rectangle_vs_circle.py.

Exercise 3.7: Frequency of random numbers


Write a program that takes a positive integer N as input and then draws
N random integers from the interval [1, 6]. In the program, count how
many of the numbers, M , that equal 6 and print out the fraction M/N .
3.4 Exercises 101

Also, print all the random numbers to the screen so that you can check
for yourself that the counting is correct. Run the program with a small
value for N (e.g., N = 10) to confirm that it works as intended.
Hint. Use random.randint(1,6) to draw a random integer between 1
and 6.
Solution. The code may be written as follows
from random import randint

# Assume user types an integer...


N = int(input(’How many random numbers should be drawn? ’))

# Draw random numbers


M = 0 # Counter for the occurences of 6
for i in range(N):
drawn_number = randint(1, 6)
print(’Draw number {:d} gave: {:d}’.format(i+1, drawn_number))
if drawn_number == 6:
M += 1
print(’The fraction M/N became: {:g}’.format(M/N))

Running the program produces the dialog


How many random numbers should be drawn? 10
Draw number 1 gave: 2
Draw number 2 gave: 4
Draw number 3 gave: 3
Draw number 4 gave: 2
Draw number 5 gave: 2
Draw number 6 gave: 1
Draw number 7 gave: 2
Draw number 8 gave: 6
Draw number 9 gave: 2
Draw number 10 gave: 3
The fraction M/N became: 0.1

We see that, in this case, 6 was drawn just a single time, so one out of
ten gives a fraction M/N of 0.1.
Filename: count_random_numbers.py.
Remarks. For large N , this program computes the probability M/N of
getting six eyes when throwing a dice.

Exercise 3.8: Game 21


Consider some game where each participant draws a series of random
integers evenly distributed between 0 and 10, with the aim of getting the
102 3 Loops and branching

sum as close as possible to 21, but not larger than 21. You are out of
the game if the sum passes 21.
After each draw, you are told the number and your total sum, and are
asked whether you want another draw or not. The one coming closest to
21 is the winner.
Implement this game in a program.
Hint. Use random.randint(0,10) to draw random integers in [0, 10].
Solution. The code may be written as follows
from random import randint

upper_limit = 21
not_finished = True
sum = 0
while not_finished:
next_number = randint(0, 10)
print(’You got: {:d}’.format(next_number))
sum += next_number
if sum > upper_limit:
print(’Game over, you passed 21 (with your {:d} points)!’\
.format(sum))
not_finished = False
else:
print(’Your score is now: {:d} points!’.format(sum))
answer = input(’Another draw (y/n)? ’)
if answer != ’y’:
not_finished = False
print(’Finished!’)

Running the program may produce this dialog


You got: 8
Your score is now: 8 points!

Another draw (y/n)? y


You got: 6
Your score is now: 14 points!

Another draw (y/n)? y


You got: 8
Game over, you passed 21 (with your 22 points)!

Filename: game_21.py.

Exercise 3.9: Simple search - verification


Check your understanding of the search procedure in ball_max_height.py
from Chapter 3.3.3 by comparing what you get “by hand” to printouts
3.4 Exercises 103

from the code. Work on a copy of ball_max_height.py. Comment out


what you do not need, and use an array y of just 4 elements (or so). Fill
that array with integers, so that you place a maximum value in a certain
location. Then, run through that code by hand for every iteration of the
loop, writing down the numbers in largest_height. Finally, place a
print command in the loop, so that largest_height gets printed with
every iteration. Run the program and compare to what you found by
hand.
Solution. The modified code reads:
import numpy as np
#import matplotlib.pyplot as plt

#v0 = 5 # Initial velocity


#g = 9.81 # Acceleration of gravity
#t = np.linspace(0, 1, 1000) # 1000 points in time interval
#y = v0*t - 0.5*g*t**2 # Generate all heights
y = np.array([1, 3, 7, 5]) # ...just pick simple values for verification

# At this point, the array y with all the heights is ready.


# Now we need to find the largest value within y.

largest_height = y[0] # Starting value for search


for i in range(1, len(y)):
if y[i] > largest_height:
largest_height = y[i]
print(largest_height) # print command added

print(’The largest height achieved was {:f} m’.format(largest_height))

# ...plotting is not of interest now, so we just comment it out


# We might also like to plot the path again just to compare
#plt.plot(t,y)
#plt.xlabel(’Time (s)’)
#plt.ylabel(’Height (m)’)
#plt.show()

Running the code results in a printout of 3 and 7, followed by the message


that 7.0 was the largest height achieved.
Filename: simple_search_verify.py.

Exercise 3.10: Sort array with numbers


Write a script that uses the uniform function from the random module
to generate an array of 6 random numbers between 0 and 10.
The program should then sort the array so that numbers appear in
increasing order. Let the program make a formatted print of the array
104 3 Loops and branching

to screen both before and after sorting. Confirm that the array has been
sorted correctly.
Solution. The code may be written as follows
import numpy as np
import random

N = 6
numbers = np.zeros(N)

# Draw random numbers


for i in range(len(numbers)):
numbers[i] = random.uniform(0, 10)
print(’Unsorted: {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f}’\
.format(numbers[0], numbers[1], numbers[2],\
numbers[3], numbers[4], numbers[5]))

for reference in range(N):


smallest = numbers[reference]
i_smallest = reference
# Find the smallest number in remaining unprinted array
for i in range(reference + 1, N, 1):
if numbers[i] <= smallest:
smallest = numbers[i]
i_smallest = i
# Switch numbers, and use an extra variable for that
switch = numbers[reference]
numbers[reference] = numbers[i_smallest]
numbers[i_smallest] = switch

print(’Sorted: {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f} {:5.3f}’\


.format(numbers[0], numbers[1], numbers[2],\
numbers[3], numbers[4], numbers[5]))

Running the program, we get the output


Unsorted: 1.393 5.765 3.946 4.860 5.712 6.751
Sorted: 1.393 3.946 4.860 5.712 5.765 6.751

From the printout, we see that the code sorts the array correctly.
Filename: sort_numbers.py.

Exercise 3.11: Compute π


Up through history, great minds have developed different computational
schemes for the number π. We will here consider two such schemes, one
by Leibniz (1646 − 1716), and one by Euler (1707 − 1783).
The scheme by Leibniz may be written
3.4 Exercises 105


1
π=8
X
,
k=0
(4k + 1)(4k + 3)
while one form of the Euler scheme may appear as
v
u ∞
u X 1
π =t6 2
.
k=1
k

If only the first N terms of each sum are used as an approximation to π,


each modified scheme will have computed π with some error.
Write a program that takes N as input from the user, and plots
the error development with both schemes as the number of iterations
approaches N . Your program should also print out the final error achieved
with both schemes, i.e. when the number of terms is N. Run the program
with N = 100 and explain briefly what the graphs show.
Solution. The code may be written as follows
from numpy import pi, zeros, sqrt

# Assume user types an integer


no_of_terms = int(input(’Give number of terms in sum for pi: ’))
Leibniz_error = zeros(no_of_terms)
Euler_error = zeros(no_of_terms)

#Leibniz
sum1 = 0
for k in range(0, no_of_terms):
sum1 += 1.0/((4*k + 1)*(4*k + 3))
Leibniz_error[k] = pi - 8*sum1
sum1 *= 8
final_Leibniz_error = abs(pi - sum1)
print(’Leibniz: {:g}’.format(final_Leibniz_error))

# Euler
sum2 = 0
for k in range(1, no_of_terms+1): # Note index range
sum2 += 1.0/k**2
Euler_error[k-1] = pi - sqrt(6*sum2)
sum2 *= 6
sum2 = sqrt(sum2)
final_Euler_error = abs(pi - sum2)
print(’Euler: {:g}’.format(final_Euler_error))

import matplotlib.pyplot as plt


plt.plot(list(range(no_of_terms)), Leibniz_error, ’b-’,\
list(range(no_of_terms)), Euler_error, ’r-’)
plt.xlabel(’No of terms’)
plt.ylabel(’Error with Leibniz (blue) and Euler (red)’)
106 3 Loops and branching

plt.show()

Running the program as told produces the dialog


Give number of terms in sum for pi: 100
Leibniz: 0.00499996875098
Euler: 0.00951612178069

and the plot in Figure 3.3

0.7
Error with Leibniz (blue) and Euler (red)

0.6
0.5
0.4
0.3
0.2
0.1
0.0
0 20 40 60 80 100
No of terms
Fig. 3.3 Error as a function of number of terms.

We see that the scheme of Leibniz gives the least error all over the
interval. However, the difference in the error with the two schemes
becomes smaller as the number of terms increases.
Filename: compute_pi.py.

You might also like