This assignment has been closed on October 01, 2024.
You must be authenticated to submit your files

Tutorial 1: Functions and branching

G. Pogudin d’après B. Smith

Objectives

The course material we will practice today: Writing simple functions with def, branching with if.

Setup: before you start

Launching Spyder

We will be writing our programs using the Spyder programming environment. This is the Python programming environment that we recommend for this course (though the programs you write will run on any Python platform).

Where can you get it?

To launch Spyder,

  1. Click on the Applications menu
  2. Click on the Programming menu
  3. Click Spyder3.
  4. If you see a “Spyder update” message, just click OK and ignore it.

Create a new project

Before you start: create a new project, called Tutorial_1. This can be done as follows:

  1. Click on Projects (n the top menu of Spyder),
  2. then select New Project....
  3. Make sure New Directory is checked.
  4. Enter Tutorial_1 in the box next to Project name, and click Create.
  5. Make sure you see Tutorial_1 appear in the left-most window pane of Spyder.

This will ensure that files from this week and future weeks do not get mixed up together.

Exercises

Each of the tutorials in CSE101 is a collection of programming exercises. You can upload them (via the upload forms below) to the server for autograding. You are free to do this as many times as you wish, so we strongly encourage you to upload your file after completing each exercise so that we can see your progress.

The version of your code which will be used for grading a tutorial is the last version you submit before 23:59 on Monday of the week following the tutorial (for example, your solutions for this tutorial must be submitted before 23:59 October 2).

Now create a new program file called dates.py. Warning: make sure you get the filename right, or the submission form will not accept it!

At the top of each of the Python source files generated by Spyder, we see something similar to

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 28 10:58:13 2023

@author: firstname.lastname
"""

Exercise 0: Using the console

The goal of this exercise is to get used to the console in Spyder, and try out some basic operations. This exercise (unlike the rest) will not be submitted anywhere and graded.

Basic arithmetic

Go to the console (generally in the bottom right-hand corner of the Spyder window), and type the following at the prompt:

In [1]: a = 5

This will create a variable, assign the integer value 5 to it, and name the resulting variable a. Technically, we say the name a is bound to the value 5.

Now create an integer variable named b with value 10.

Now type

In [3]: a + b

The console will evaluate this expression, and show the result (the sum of the values referred to by a and b), which should be 15:

Out[3]: 15

(Notice the console starts this line with Out[n]: to indicate that this is the result of the expression entered at the prompt In [n]:).

Try some other arithmetic operations: a * b, a / b, a // b (integer division), b % a (computing the remainder). Make sure that all the results make sense to you - and note the difference between the results of a / b and a // b!

Strings

Another important data type for us will be string. The + operation is also defined for strings: it computes the concatenation of two strings strings. Try this:

In [4]: h = 'Hello '

In [5]: w = 'world!'

In [6]: h + w
Out[7]: 'Hello world!'

One can ask Python to try to convert a given value to an integer or string type using the built-in functions int and str, respectively. Try typing str(a) + str(b) in the console, and explain the output. Will it be the same as for str(b) + str(a) or str(a + b)?

Exercise 1: Getting started

To get used to the submission interface and discuss basic things about functions, let us look at this:

def hello_world():
    """
    This function simply returns the string 'Hello world!'
    """
    return 'Hello world!'

Here you see

  1. the function definition def hello_world():, where hello_world is the function name
  2. the docstring, surrounded by triple-quotes ("""); the docstring explains what the function does
  3. the body of the function, consisting only of a return statement

Add this function to dates.py. Now save dates.py, and click on the triangular “play” icon to make Python load and run your new program.

Testing

Now you should be able to test your code by doing this in the console:

In [8]: hello_world()
Out[8]: 'Hello world!'

Upload your solution to the form below, it will be tested automatically.

Upload form is only available when connected

Caveat emptor: return vs print

Caveat. There is an important difference between return and print. Consider the following function

def hello_world2():
    """
    Prints 'Hello world!'
    """
    print('Hello world!')

Calling it, you will see

In [9]: hello_world2()
Hello world!

Notice that

  1. There are no quotation marks: the content of the string appears directly in the console.
  2. There is no Out[9]: before the string! The string has been displayed on the console, but it is not treated as a “result” or “return value” of the hello_world2 function.

These two functions will behave very differently if you will try to use their return values in the further computation:

In [10]: a = hello_world()

In [11]: a
Out[11]: 'Hello world!'

In [12]: print(a)
Hello world!

In [13]: b = hello_world2()
Hello world!

In [14]: print(b)
None

Recall that None is Python’s special object that represents “nothing”. This is the default result for functions that do not explicitly return anything.

Exercise 2: To work or not to work?

In this exercise, we will check whether a day of the week is a workday or a holiday.

Complete the following function check_day and add it to dates.py:

def check_day(n):
    """
    Given an integer between 1 and 7 inclusive,
    return either string 'work!' or string 'rest!'
    depending on whether the day is a workday or not
    """
    if n < 1 or n > 7:
        return None # invalid m
    pass # remove this line and replace it with your code

Hint: you will have to use an if statement (actually, only one!).

Testing

Now test your code. You should be able to reproduce the following behaviour in the console:

In [15]: check_day(1)
Out[15]: 'work!'

In [16]: check_day(7)
Out[16]: 'rest!'

Upload your solution using the form below for further, automatic testing.

Upload form is only available when connected

Exercise 3: The months of the year

In this exercise, we will write a function that takes the number corresponding to a month (like 1 for January, 9 for September, or 10 for October), and returns the name of the month (as a string).

Complete the following function name_of_month, and add it to dates.py:

def name_of_month(m):
    """Given an integer m between 1 and 12 inclusive,
    indicating a month of the year, returns the name of that month.
    For example: name_of_month(1) == 'January' and name_of_month(12) == 'December'.
    If the month does not exist (that is, if m is outside the legal range),
    then this function returns None.
    """
    if m < 1 or m > 12:  # Non-existent month
        return None
    pass # remove this line and replace it with your code to compute month names

Hints:

  • You will need to use a series of if, elif, and else statements (with multiple elifs).
  • Be careful with the spelling of the month names! And make sure that the first letter of each name is a capital letter, with the others in lower case (that is: we want 'December', not 'DECEMBER' or 'december').

Testing

Now test your code by doing this in the console (after re-running dates.py):

In [17]: name_of_month(1)
Out[17]: 'January'

In [18]: name_of_month(8)
Out[18]: 'August'

Check the capitalization of your month names carefully!

Once you have done this, upload your solution using the form below for automatic testing.

Upload form is only available when connected

Exercise 4: From numbers to words

When you are counting items in a sequence, like days of a month, you say the 1st, 2nd, 3rd, 4th, 5th, …

Complete the following function str_with_suffix, and add it to dates.py:

def str_with_suffix(n):
    """Convert the integer n to a string expressing the corresponding 
    position in an ordered sequence.
    Eg. 1 becomes '1st', 2 becomes '2nd', etc.
    """
    pass # remove this line and replace with your code

For example:

  • str_with_suffix(1) should return '1st' ;
  • str_with_suffix(2) should return '2nd' ;
  • str_with_suffix(3) should return '3rd' ;
  • str_with_suffix(4) should return '4th' ;
  • str_with_suffix(11) should return '11th' ;
  • str_with_suffix(21) should return '21st' ;
  • str_with_suffix(32) should return '32nd' ;
  • str_with_suffix(43) should return '43rd' .

By convention, we say str_with_suffix(0) is '0th'.

Hints:

  • Use str to convert integers to strings.
  • Use + to join strings together.
  • The possible suffixes are 'st', 'nd', 'rd', and 'th'.
  • If you want to get the last digit (in base ten) of an integer, use % 10.
  • Be careful of numbers ending in 11, 12, and 13!

Testing

Test your code using the examples above in the console (after re-running dates.py).

Upload your solution to the form below, it will be tested automatically.

Upload form is only available when connected

Exercise 5: Leap years

A leap year is a year with 366 days (including a 29th of February) instead of the usual 365. Here are the rules (for the standard Gregorian calendar):

  1. Every year that is exactly divisible by four is a leap year,
  2. except for years that are exactly divisible by 100,
  3. unless they are exactly divisible by 400 (in which case they are leap years).

The definition might seem a bit tricky, but for example:

  • 1900 was not a leap year (divisible by 100)
  • 2000 was a leap year (divisible by 400
  • 2016 was a leap year (divisible by 4, but not 100)
  • 2018 is not a leap year (not divisible by 4)

Define a new function is_leap_year (in dates.py) that

  • takes an integer y as an argument, and
  • returns True if the year y is a leap year, and False if not.

Here’s a start:

def is_leap_year(y):
    """ Return True if y is a leap year, False otherwise. """
    pass # remove this line and replace with your own code

Here’s what we expect to happen in the console, once you’ve run your code:

In [19]: is_leap_year(1800)
Out[19]: False

In [20]: is_leap_year(2000)
Out[20]: True

In [21]: is_leap_year(2012)
Out[21]: True

In [22]: is_leap_year(2018)
Out[22]: False

Testing

Test your code using the examples above in the console (after re-running dates.py). Make sure you get the expected answer in each case!

Upload your solution using the form below. It will be tested automatically.

Upload form is only available when connected

Exercise 6: How many days in a month?

Now we want a function that tells us the number of days in a given month of a given year. Recall that

  • January, March, May, July, August, October, and December all have 31 days in any given year;
  • April, June, September, and November all have 30 days in any given year;
  • February has 28 days most of the time, but 29 days in a leap year.

Define a new function number_of_days (in dates.py) that

  • takes integers m and y as arguments (indicating the number of the month and year), and
  • returns the number of days in that month.

Make sure to use your is_leap_year function to check what to return when m == 2!

Here’s a start:

def number_of_days(m, y):
    """Returns the number of days in month m of year y."""
    pass # remove this line and replace with your own code

Testing

Here’s what we expect to happen in the console, once you’ve run your code:

In [23]: number_of_days(9, 2018)
Out[23]: 30

In [24]: number_of_days(3, 2018)
Out[24]: 31

In [25]: number_of_days(2, 2018)
Out[25]: 28

In [26]: number_of_days(2, 2000)
Out[26]: 29

Test your code using these examples - and think of some new tests for yourself (like today’s month, for example, and February of this year).

Upload your solution to the form below. It will be tested automatically.

Upload form is only available when connected

Exercise 7: Constructing dates

Define a function date_string which takes three integer arguments, d, m, and y representing the day, month, and year, and returns a string expressing the date in words, in the following format:

'The D of M, Y' where

  • D is d followed by its suffix (as in Exercise 2)
  • M is 'January' if m is 1, 'February' if m is 2, …
  • Y is just y.

If the date given does not exist (eg. the 32nd of January, 1970, or the 29th of February, 1900) then return the string 'Nonexistent date'. (You should use your number_of_days function to help check this). You should use your str_with_suffix function to treat the day argument d, and your name_of_month function to treat the month argument m. If name_of_month returns None, then the month was illegal and you can return 'Nonexistent date'.

Here is a table of sample inputs and expected arguments:

  • date_string(28, 9, 2017) should return 'The 28th of September, 2017'
  • date_string(31, 12, 1999) should return 'The 31st of December, 1999'
  • date_string(2, 3, 786) should return 'The 2nd of March, 786'
  • date_string(29, 2, 2000) should return 'The 29th of February, 2000'
  • date_string(29, 2, 1800) should return 'Nonexistent date'
  • date_string(33, 1, 1979) should return 'Nonexistent date'
  • date_string(12, 0, 105) should return 'Nonexistent date'

Don’t forget to include a useful docstring at the top of your function!

Testing

Make sure you test your function - it should correctly reproduce the seven examples above.

Then, upload your solution to the form below, for further automated testing.

Upload form is only available when connected

Exercise 8: Breaking down times

Everybody knows that there are sixty seconds in a minute, sixty minutes in an hour, and 24 hours in a day.

Define a new function time_string which takes a number of seconds n as an argument, and returns a string describing the corresponding number of days, hours, minutes, and seconds. time_string always includes a number of seconds in its output (even if 0), but ‘0 days’, ‘0 hours’, and ‘0 minutes’ are always omitted.

We expect the following outputs:

  • time_string(0) returns '0 seconds'
  • time_string(1) returns '1 second'
  • time_string(10) returns '10 seconds'
  • time_string(100) returns '1 minute, 40 seconds'
  • time_string(1000) returns '16 minutes, 40 seconds'
  • time_string(10000) returns '2 hours, 46 minutes, 40 seconds'
  • time_string(1000000) returns '11 days, 13 hours, 46 minutes, 40 seconds'
  • time_string(100000000) returns '1157 days, 9 hours, 46 minutes, 40 seconds'

Don’t forget to include a useful docstring at the top of your function!

Testing

Test your code in the console using the eight examples above (after re-running dates.py). Make sure the outputs are all correct. Be careful with spaces and punctuation!

Upload your solution to the form below, it will be tested automatically.

Upload form is only available when connected