
Warning
This page shows last year’s version. We might still make small changes, but you’re welcome to take a look. We’ll remove this notice once the page is final.
Week 10: In-Class#
Coding Practice#
Code 10.1: My Time#
Time is written in the 24-hour format as HH:MM, where HH represents the hour (00 to 23) and MM the minute (00 to 59). When time changes, both the hour and minute values must update correctly.
Problem Analysis
How should the time change when one minute passes? Consider the following cases:
Time is
07:15Time is
14:59Time is
23:59
Demo
Write a class with a constructor that takes two integer parameters, hour and minute, and initializes the corresponding attributes. The class should be able to return the time in a tuple with minutes and hours as integers. It should also include methods to increment the time by a specified number of hours and a specified number of minutes.
The expected behavior is shown below:
>>> my_time = MyTime(10, 23)
>>> my_time.increment_minutes(36)
>>> my_time.get_time()
(10, 59)
>>> my_time.increment_hours(13)
>>> my_time.get_time()
(23, 59)
>>> my_time.increment_minutes(1)
>>> my_time.get_time()
(0, 0)
>>> my_time.increment_hours(30)
>>> my_time.get_time()
(6, 0)
>>> my_time.increment_minutes(123)
>>> my_time.get_time()
(8, 3)
The class requirements are:
my_time.pyMyTime()
A class to represent 24 hour time in the format HH:MM.
__init__(hours, minutes)
Initializes the time to the given hours and minutes.
Parameters:
|
|
The hour value (0 to 23). |
|
|
The minute value (0 to 59). |
get_time()
Returns the time currently represented in the class.
Returns:
|
A tuple (hours, minutes) representing the current time. |
increment_hours(hours)
Increments the hours.
Parameters:
|
|
The number of hours to increment. |
increment_minutes(minutes)
Increments the minutes.
Parameters:
|
|
The number of minutes to increment. |
Use the following script to check your function test_my_time.py. If your function fails the test in this script, it would also fail if you could hand it in.
Code 10.2: Weather Station Revisited#
In week 8, you created a dictionary that represented a weather station, and you defined a function which took that dictionary as input and returned some processed information. You will now do something similar using classes. The advantage of using classes is that instead of having a dictionary that stores data and a function that processes that data, we can have a class that does both.
Create a class WeatherStation. The constructor method should as input take a string with station name, and a boolean indicating whether the station is operational. These inputs should be assigned to the attributes station_name and is_operational. The constructor should create two additional attributes wind_readings and temperature_readings and assign them to an empty list. Later you will change these attributes.
Before you continue, try to create an object cph_station of the class WeatherStation with the name "CPH Airport Weather Station" and operational status True.
Check
You should be able to achieve the behavior below.
>>> cph_station = WeatherStation("Copenhagen", True)
>>> cph_station.station_name
'Copenhagen'
>>> cph_station.is_operational
True
>>> cph_station.wind_readings
[]
>>> cph_station.temperature_readings
[]
Add two methods to the class WeatherStation. The first method should be named take_daily_wind_readings and take a list of floating points as input. The method should assign the input list to the attribute wind_readings, but only if the station is operational. If the station is not operational, the method should print a message saying that the station is not operational. The second method should be named take_daily_temperature_readings and take a list of floating points as input. The method should assign the input list to the attribute temperature_readings, also only if the station is operational. If the station is not operational, the method should print a message saying that the station is not operational.
Test your code.
Check
You should be able to achieve the behavior below.
>>> cph_station.take_daily_wind_readings([3.5, 6.2, 7.1, 12.1])
>>> cph_station.take_daily_temperature_readings([18.1, 18.3, 19.0, 18.5])
>>> cph_station.wind_readings
[3.5, 6.2, 7.1, 12.1]
>>> cph_station.temperature_readings
[18.1, 18.3, 19.0, 18.5]
Add a method get_highest_readings to the class WeatherStation. The method should output a tuple containing the maximum wind speed reading and the maximum temperature reading. If one or both of the readings are empty, the corresponding value in the tuple should be None.
Test your code.
Check
You should be able to achieve the behavior below.
>>> max_wind, max_temp = cph_station.get_highest_readings()
>>> max_wind
12.1
>>> max_temp
19.0
Code 10.3: Health Analysis Revisited#
In this exercise we look back at Problem 2.14: Health Analysis. Recall how body mass index (BMI) and body fat percentage (BFP) are calculated from weight \(w\) in kilograms, height \(h\) in meters, age \(y\) in years.
where \(s\) is equal to \(0\) for women and \(1\) for men.
Create a class PersonHealth. The constructor of the class should take as input the age, height, weight, and sex of the person. The age, height, and weight should be numerical values, as well as the corresponding attributes. The sex should be given to the constructor as a string, either 'm' or 'f'. The attribute sex should be assigned value 1 if the input is 'm' and 0 if the input is 'f'.
Write a class method body_mass_index that calculates and returns the BMI of the person.
Write a class method body_fat_percentage that calculates and returns the body fat percentage.
Finally, write a class method get_health_description that returns a string with an informative description of the person’s health. The string should contain the age, BMI, and BFP of the person.
Check
You should be able to achieve the behavior below.
>>> person1 = PersonHealth(20, 1.70, 69, 'f')
>>> person1.get_health_description()
'Age: 20, BMI: 23.88, BFP: 27.85'
>>> person2 = PersonHealth(61, 1.92, 91, 'm')
>>> person2.get_health_description()
'Age: 61, BMI: 24.69, BFP: 27.45'
Problem Solving#
Problem 10.4: Simple Statistics#
We want to create a class to store a sequence of numbers, and to compute some basic statistics.
Write a class definition for the class SimpleStatistics. The constructor method should take a list of numbers as argument, and it to an attribute called samples. The class should have get_mean method that returns the mean of the samples, and a get_standard_deviation method that returns the standard deviation of the samples. The mean \(\mu\) and the standard deviation \(\sigma\) should be calculated as
where \(N\) is the number of samples and \(x_i\) is the value of the \(i^\text{th}\) sample.
Finally, the class should have a method one_sample_ttest that given an input value \(\mu_0\) computes the t-statistics
and returns True if \(|t| \geq 1.96\) and False otherwise.
Here is an example of using the class.
>>> samples = [0.1763, -1.2523, 0.9099, -0.0679, 0.1999, 0.1175, 0.143, 0.1118,
... 0.9854, -1.1836, -0.5868, 0.4839, 1.2069, 0.142, 0.2523]
>>> stat = SimpleStatistics(samples)
>>> stat.get_mean()
0.10922000000000003
>>> stat.get_standard_deviation()
0.6984926241557602
>>> stat.one_sample_ttest(0.0)
False
>>> stat.one_sample_ttest(0.1)
False
>>> stat.one_sample_ttest(-0.1)
False
>>> stat.one_sample_ttest(-0.25)
True
The filename and requirements are in the box below:
simple_statistics.pySimpleStatistics()
Class to get summary statistics and compute one-sample t-test.
__init__(samples)
Initialize the statistics class with the samples.
Parameters:
|
|
List of samples. |
one_sample_ttest(mu_0)
Compute one sample t-value and determine whether it is outside the expected range.
Parameters:
|
|
Proposed mean. |
Returns:
|
True if the proposed mean is significantly different from the mean of the samples, else False. |
You should also test your function with test_simple_statistics.py.
Problem 10.5: Study Planner#
In this exercise, you will create a simple study planner to manage the courses a student has registered for in each course block (e.g., foundations, directions, projects, and electives). The planner will also track the remaining ECTS available in each course block.
Define a class named StudyPlanner. The constructor of this class should take two parameters: blocks which is a list of strings with the names of the course blocks and points which is a list of integers indicating the maximum number of points allowed in the corresponding blocks. The constructor should create two dictionaries as attributes. The dictionary registered_courses has the names of the course blocks as keys and, initially, empty lists as values. The dictionary points_left has the names of the course blocks as keys and the corresponding maximum number of points as values.
In the StudyPlanner, define a method add_course that as input takes three values: a string with the course name, a string with the block the course should be added to, and an integer with ECTS points. The method should verify that there are enough points left in the course block to add the course. If there are, it should add the course name to the list in registered_courses under the specified course block and decrease the corresponding value in points_left by the number of ECTS points for the course. The method should return 1 if the course was added successfully, and -1 if the course could not be added.
Define a method print_courses that displays a message summarizing the registered courses and the remaining points for each course block. You may decide on the format of this message.
study_planner.pyStudyPlanner()
Study planner class to manage courses in different course groups.
__init__(blocks, points)
Initialize the study planner.
Parameters:
|
|
The course block names. |
|
|
The maximum number of points allowed in course blocks. |
add_course(name, block, ects)
Add a course to the study planner.
Parameters:
|
|
The name of the course to add. |
|
|
The course block to add the course to. |
|
|
The number of ects points the course is worth. |
Returns:
|
-1 if unsuccessful, 1 if successful. |
print_courses()
Print an overview of the courses in the study planner.
Test your class using the following code.
Check
Your should be able to use the class as shown below.
blocks = ['foundations', 'directions', 'projects', 'electives']
points = [55, 55, 25, 45]
planner = StudyPlanner(blocks, points)
planner.print_courses()
planner.add_course('Programming', 'foundations', 5)
planner.print_courses()
planner.add_course('Mathematics 1a', 'foundations', 10)
planner.add_course('Mathematics 1b', 'foundations', 10)
planner.add_course('Signals and systems', 'directions', 5)
planner.add_course('Optics and photonics', 'directions', 5)
planner.add_course('BSc project', 'projects', 15)
planner.add_course('Prototyping', 'projects', 10)
planner.add_course('Acoustics and noise', 'electives', 5)
planner.print_courses()
One possible output is shown below, but the exact format is up to you.
Example
---------------
BLOCK FOUNDATIONS
Points left: 30
Courses:
Programming
Mathematics 1a
Mathematics 1b
BLOCK DIRECTIONS
Points left: 45
Courses:
Signals and systems
Optics and photonics
BLOCK PROJECTS
Points left: 0
Courses:
BSc project
Prototyping
BLOCK ELECTIVES
Points left: 40
Courses:
Acoustics and noise
---------------