Week 3: Conditionals, recursion, and frutiful functions#
Important
You must start by downloading the script
Right-click and select “Save link as…”. You may need to confirm the download in your browser.
Run this script in VSCode to download the code snippets and tests you need for week 3. The script does not need to be located a specific place on your computer.
If you get an error from the script, please follow the instructions in the error message. If you give up, proceed to the exercises (which you can still do), and ask a TA once they arrive.
The script should end with Successfully completed!
, which means that you now have the tests for this week.
Videos (Watch this before the other videos)#
Hello everyone! My name is Tue Herlau, and I asked Vedrana if I could upload a few videos for this exercise as an experiment. What I am going to cover is:
What the videos are about and how to use them (please watch this first)
A bit about common VS Code problems involving multiple interpreters (i.e., nearly all installation problems – I know this video will not fix everyones problem, but hopefully it can make it a little more clear; use Piazza and Discord!)
How to start and use the interpreter
How to work with scripts
How to solve the exercises (but please see the first video!)
How to use the test system (important)
How to get started on the project and use the tests
Please note the videos are not a stand-in for the lectures or Think Python, which you should prioritize over my blabber :-).
Video 3a: Watch this first
Video 3b: Using VS Code and install problems
Exercise 3.1: Relational operators#
Video 3.1: Exercise walkthrough
- Subexercise a
Does each of the following bits of code print out
True
orFalse
? Evaluate the expression on paper or in your mind first and verify your answers by pasting the code into the terminal.math.pi < 3
- with
x = 10
, x < 5
- with
- with
x = 6
, math.pi > 3 and x > 5
math.pi > 3 or x < 5
- with
- with
x = 5
, math.pi > 3 and x == 5
- with
- Subexercise b
Define a variable
y
that isTrue
whenx
is greater than 7.
Tip
Consider this code:
x = 45 # an example value
y = True # 'True' when x > 7
Replace y = True
with an expression so that y
is True
with the given value of x > 7
.
- Subexercise c
Define a variable
z
that isTrue
whenx
is smaller than .
Solutions
a:
False
,False
,True
,True
,True
b:
y = x > 7
c:
z = x < math.pi
Exercise 3.2: Logical operators#
Video 3.2: Exercise walkthrough
Write some code that evaluates the follwoing statements to True
or False
.
Evaluate the expression on paper first and verify your answers with your code.
Tip
greater than or equal can be expressed as
>=
Not equal can be expressed as
!=
Equal can be expressed as
==
either a or b can be expressed using
a or b
a and b can be expressed using
a and b
The cosine of
can be evaluated usingmath.cos(x)
divisble by a number can be checked using the modulo operator
%
- Subexercise a
is greater than or equal to- Subexercise b
is not equal to- Subexercise c
Either
is greater than or is not equal to- Subexercise d
The cosine of
is a negative number- Subexercise e
9 is greater than or equal to
and divisible by- Subexercise f
The cosine of
is a positive number or is equal to- Subexercise g
Assign the value
True
orFalse
to the variabley
depending onx
being greater than and an even number. Try different values ofx
to verify your answer.
Tip
even number can be checked using the modulo operator
%2
negative number translates to being less than
True and True
evaluates toTrue
True and False
evaluates toFalse
True or False
evaluates toTrue
False or False
evaluates toFalse
Solutions
a:
9>=3*3
b:
91!=11*9
c:
(2>3 or 3*3!=9)
d:
math.cos(3*math.pi)<0
e:
9>=5 and 9%3==0
f:
math.cos(3*math.pi)>0 or math.cos(3*math.pi)==0
g:
y = (x>10 and x%2==0)
Exercise 3.3: Function with return value#
Video 3.3: Exercise walkthrough
Up to this point, you have been crafting Python functions that execute a series of computational steps and then print
a message containing the result.
However, in this exercise, we will construct a function that returns the result instead.
>>> def is_equal(a, b):
... if a == b:
... return "yes"
... else:
... return "no"
...
>>> a = 2 + 4
>>> b = 3 + 5
>>> c = 2 * 4
Test the function is_equal()
with different combinations of a
, b
and c
and store the result in a variable result
.
Print the result outside of the function, e.g. print("Is a equal to b?", result)
.
Notice how, instead of printing a message directly, the function is_equal()
returns a value that is stored in the variable result
, which can then
printed outside of the function.
Optional Write your own function that checks if a
is greater than b
and returns the result.
Exercise 3.4: Classify body temperature using the if
statement#
Video 3.4: Exercise walkthrough
In this exercise, you will implement a function body_temperature
that returns the body’s state based on the
body’s temperature.
The function should return a str
depending on the temperature:
Open and closed intervals
An interval such as
If
temperature
is below , it should return"Hypothermia"
If
temperature
is in the interval , it should return"Normal"
If
temperature
is in the interval , it should return"Slight fever"
If
temperature
is in the interval , it should return"Fever"
If
temperature
is higher than , it should return"Hyperthermia"
Does your function return the right answer to the following examples?
>>> body_temperature(34.5)
'Hypothermia'
>>> body_temperature(35)
'Normal'
>>> body_temperature(38)
'Slight fever'
>>> body_temperature(39)
'Fever'
>>> body_temperature(39.5)
'Hyperthermia'
Tip
Begin by implementing the if-statement for the lowest temperature range. Remember the
return
-keyword!For temperature ranges
, you can check these as if is greater than and is less thanConsider using
elif
andelse
(not strictly necessary, but it will make your code more readable and robust)
To test your solution, add it to the file cp/ex03/body_temperature.py
.
- cp.ex03.body_temperature.body_temperature(temperature)#
Calculate the body’s response based on the given temperature.
- Parameters
temperature – The temperature in degrees Celsius.
- Returns
The body’s response as a string.
Exercise 3.5: Comparing numbers#
Video 3.5: Exercise walkthrough
In this exercise, you will implement a function compare_numbers
that returns which of two numbers is greater.
Think of appropriate arguments. The function should return a str
as follows:
if the first number is greater than the second number, the program should return
"the first number is greater"
.if the second number is greater the program should display
"the second number is greater"
.if both numbers are equal, the program should display
"the numbers are equal"
.
Does you function work as intended? Test the following examples:
>>> compare_numbers(29,16)
'the first number is greater'
>>> compare_numbers(10,20)
'the second number is greater'
>>> compare_numbers(13,13)
'the numbers are equal'
Add your solution to the file cp/ex03/compare_numbers.py
to run the tests.
- cp.ex03.compare_numbers.compare_numbers(first_number, second_number)#
Return a string based on which number has the greatest numerical value.
- Parameters
first_number (
int
) – first number.second_number (
int
) – second number.
- Return type
str
- Returns
string stating which number is the greatest.
Exercise 3.6: Blood alcohol concentration calculator#
Video 3.6: Exercise walkthrough
Blood Alcohol Concentration (BAC) is a numerical measure of the amount of alcohol present in a person’s bloodstream. The calculation of BAC is influenced by several factors, including the person’s weight, gender, the amount of alcohol consumed, and the time elapsed since drinking, according to the equation:
where
is the mass of alcohol consumed in kg. is the distribution ratio. It is for males and for females. is the body weight in kg. is the rate at which alcohol is metabolized. It is for males and for females. is the time elapsed since consumption in hours.
Note
There are several formulas used to estimate BAC, we are using one commonly used formula, the Widmark formula, which was developed by Swedish professor Erik Widmark in the 1920s.
Implement a function bac_calculator
which takes the total amount of alcohol
consumed alcohol_consumed
, the person’s body weight weight
, the person’s gender gender
,
and the time elapsed (in hours) since consumption time
and returns the calculated blood alcohol concentration BAC
.
Example: Suppose a 80 kg male consumes 28 grams of alcohol in total, and the time elapsed since alcohol consumption is 2 hours.
As we are calculating the BAC for a male, we assume a distribution ratio of 0.68 and a
or the same example in code (test if your function returns the same values):
>>> alcohol_consumed = 0.028 # Total alcohol consumed: 28 grams
>>> weight = 80.0 # Body weight: 80 kilograms
>>> time = 2 # Time elapsed since alcohol consumption: 2 hours
>>> bac_calculator(alcohol_consumed, weight, "male", time) # BAC for a man
0.02147058823529411
>>> bac_calculator(alcohol_consumed, weight, "female", time) # Same for a woman
0.02963636363636364
Tip
Note we specify the gender as the third argument as a
str
, which can be either"male"
or"female"
Use conditional statements (
if
-else
) to determine the appropriate distribution ratio and elimination rate based on the gender. Use the provided values of 0.68 and 0.015 for male, and 0.55 and 0.017 for female.
Add your solution to the file cp/ex03/bac_calculator.py
to run the tests.
- cp.ex03.bac_calculator.bac_calculator(alcohol_consumed, weight, gender, time)#
Calculate the blood alcohol concentration based on the alcohol consumed, body weight, and time since consumption.
- Parameters
alcohol_consumed (
float
) – The total amount of alcohol consumed in grams (float)weight (
float
) – The person’s body weight in kilograms (float)gender (
str
) – The person’s gender, which must be a string of either “male” or “female” (str)time (
float
) – The time elapsed since alcohol consumption in hours (float)
- Return type
float
- Returns
The calculated blood alcohol concentration (BAC) as a float value.
Exercise 3.7: Solar panel installation#
Video 3.7: Exercise walkthrough
In this assignment, you will implement a function solar_panel
that
decides the ponderous question if we should put solar panels on something
based on the following decision diagram developed by experts:

Decision tree for whether you should install solar panel on an object (source & copyright).#
The function should take the following arguments and print out the appropriate answer according to the diagram:
move
: Does it move around?swap
: Does it have regular chances to recharge or swap batteries?hot
: When running is it hot to the touch?empty
: Is there empty space nearby where it would be easier to put them?
These will have the value of either True
or False
.
Note
Note the last example below, where it should print
out "haha, good luck"
, now works regardless of whether you use one or two lines (this is a change compared to the version shown in the video).
Try out the following examples:
>>> print("Should I install solar panel on the chimney?")
Should I install solar panel on the chimney?
>>> solar_panel(False, True, True, True)
'probably not'
>>> print("Should I install solar panel on the roof?")
Should I install solar panel on the roof?
>>> solar_panel(False, True, True, False)
'sure'
>>> print("Should I install solar panel on the windmill?")
Should I install solar panel on the windmill?
>>> solar_panel(True, False, False, False)
'maybe'
>>> print("Should I install solar panel on a fighter jet?")
Should I install solar panel on a fighter jet?
>>> solar_panel(True, False, True, False)
'haha, good luck'
This is a slight change compared to the video solution. Add your function to the file cp/ex03/solar_panel.py
to test your solution.
- cp.ex03.solar_panel.solar_panel(move, swap, hot, empty)#
Print out whether it is a good idea to install solar panels on an object with the given properties.
- Parameters
move (
bool
) – does the object move around?swap (
bool
) – does the object allow swapping or recharging battery?hot (
bool
) – is the object hot to the touch when it is running?empty (
bool
) – are there other empty places near the object?
- Return type
str
- Returns
Whether you should put solar panels on the object as a string.
Exercise 3.8: Risk of heart attack#
Video 3.8: Exercise walkthrough
Now, you will implement a function that determines the risk of a person having a heart attack based on the following decision tree:

Decision tree for the risk of a person having heart attack (source).#
Think about suitable arguments for the function and return low
or high
depending on the risk.
Does your function return the same values as in the examples below?
>>> print("Risk for a 30-year-old, 45kg, non-smoking person?", heart_attack(30, 45, False))
Risk for a 30-year-old, 45kg, non-smoking person? low
>>> print("Risk for a 60-year-old, 70kg, smoking person?", heart_attack(60, 70, True))
Risk for a 60-year-old, 70kg, smoking person? high
>>> print("Risk for a 17-year-old, 40kg, smoking person?", heart_attack(17, 40, True))
Risk for a 17-year-old, 40kg, smoking person? low
Add your function to the file cp/ex03/heart_attack.py
to test your solution.
- cp.ex03.heart_attack.heart_attack(age, weight, smoker)#
Return a string indicating the risk of a person for having heart attack.
- Parameters
age (
int
) – The age of the person.weight (
int
) – The weight of the person in kilograms.smoker (
bool
) – Does the person smoke cigarettes?
- Return type
str
- Returns
A string, either “low” or “high”, indicating the risk for having heart attack.
Exercise 3.9: Exponential function#
Video 3.9: Exercise walkthrough
In this exercise, you will implement a function that computes the exponential of a number using recursion.
Given a base number
This means we can also compute the exponential in a recursive manner:
where we handle negative
Note
Obviously, the better way to compute the exponential function is as x**n
. However, try to solve this exercise
using recursion, i.e. without the **
operator or loops (a topic we will consider next week).
Do you get the right results? Try a few examples.
>>> print("3 to the power of 4 =", exponential(3, 4))
3 to the power of 4 = 81.0
>>> print("2 to the power of 5 =", exponential(2, 5))
2 to the power of 5 = 32.0
>>> print("4 to the power of -2 =", exponential(4, -2))
4 to the power of -2 = 0.0625
Add your function to the file cp/ex03/exponential.py
to test your solution.
- cp.ex03.exponential.exponential(x, n)#
Compute the exponential
using recursion.First focus on the case where
, then and finally .- Parameters
x (
float
) – the base number .n (
int
) – the power .
- Return type
float
- Returns
the computed value.
Exercise 3.10: Ackermann function#
Video 3.10: Exercise walkthrough
Now, you will implement the Ackermann function using recursion.
The Ackermann function,
Try the following examples to see if your solution is correct:
>>> print("A(3,4) =", ackermann(3, 4))
A(3,4) = 125
>>> print("A(2,5) =", ackermann(2, 5))
A(2,5) = 13
Add your function to the file cp/ex03/ackermann.py
to test your solution.
- cp.ex03.ackermann.ackermann(m, n)#
Compute the Ackermann’s function
.Your implementation should use recursion and not loops.
- Parameters
m (
int
) – the variable m.n (
int
) – the variable n.
- Returns
the computed value
.
Note
The following exercises are part of Project 2: Strings and basic iterations. The link contains additional details, including how to hand in your results.
Exercise 3.11: The bisection algorithm.#
Video 3 project work: Get started and use tests to solve your problems
Consider a function
In some cases, we can compute the roots explicitly. For instance, if
You can find a plot of

Plot of the function we wish to find roots of. The function has infinitely many roots.#
As a warmup, implement the function defined in (1) as f()
.
For testing and handing in your function put in the file cp/ex03/bisect.py
.
- cp.ex03.bisect.f(x)#
Find the roots of this function.
You should implement the function f(x) here.
- Parameters
x (
float
) – The value to evaluate the function in x- Return type
float
- Returns
f(x)
Exercise 3.12: Concluding there is a root#
The bisection algorithm assumes that the function
If a function is continuous, then if we select two points numbers
Note
To understand the last condition, if
Either
or are themselves a root (i.e. or )The values
and are on opposite sides of the -axis
The figure below we have illustrated two examples. In the first (blue) example cp.ex03.bisect.is_there_a_root()
which,
given an True
when the criteria is met and otherwise False
.

Examples of intervals where we can, and cannot, conclude the function has a root.#
Here is an example of how you might use the function
>>> is_there_a_root(1, 2) # yes
True
>>> is_there_a_root(3.2, 3.8) # no
False
>>> is_there_a_root(1, 3.5) # actually there is a root, but the method here does not know it.
False
Warning
You might have noticed that the criteria may well be False
even if there is a root in the interval
To check your function with the supplied tests and to be able to hand it in, add it to the same file as in the previous exercise (cp/ex03/bisect.py
).
- cp.ex03.bisect.is_there_a_root(a, b)#
Return
True
if we are guaranteed there is a root off
in the interval .- Parameters
a (
float
) – Lowest x-value to considerb (
float
) – Highest x-value to consider
- Return type
bool
- Returns
True
if we are guaranteed there is a root otherwiseFalse
.
Exercise 3.13: Bisection#

First step of the bisection method#
We are now ready to discuss the bisection algorithm. Consider the above figure and suppose we are given
two values
It should be clear that at least one of the intervals is_there_a_root()
and hence must contain a root.
We can now repeat the procedure on the interval that satisfy the criteria and select a new

Second step of the bisection method.#
Note
It is very common for numerical algorithms to contain terms such as
Clearly in each step, the intervals become smaller and smaller, and hence we can select a tolerance
we can compute the mid-point
The method you implement in the function bisect()
should therefore do the following:
It is given two values
and so that and a toleranceIt checks if the tolerance condition in (2) is met and if so return the midpoint
Otherwise, it computes
, and check if the left-hand split must contain a zero according to the criteria inis_there_a_root()
If so, it (recursively) evaluates itself on the left-hand root
Otherwise, it (recursively) evaluates itself on the right-hand root
To prevent infinite recursion, if
and does not satisfy the condition inis_there_a_root()
it should return the special valuemath.nan
:
To check your function with the supplied tests and to be able to hand it in, add it to the same file as in the previous exercise (cp/ex03/bisect.py
).
>>> bisect(1, 3, 0.01) # Compare to the figure
1.7734375
>>> bisect(1, 3, 0.2) # Much higher tolerance
1.875
>>> bisect(1, 3.5, 0.01) # return math.nan to avoid a potential infinite recursion
nan
- cp.ex03.bisect.bisect(xmin, xmax, delta)#
Find a candidate root within
xmin
andxmax
within the given tolerance.- Parameters
xmin (
float
) – The minimum x-value to considerxmax (
float
) – The maximum x-value to considerdelta (
float
) – The tolerance.
- Return type
float
- Returns
The first value
which is withindelta
distance of a root according to the bisection algorithm