Week 7: Tuples and data structure#

Important

First, download_week07.py and run the script in VSCode. You may need to confirm the download in your browser.

The script should end with Successfully completed!. If you encounter an error, follow the instructions in the error message. If needed, you can proceed with the exercises and seek assistance from a TA later.

In this week, we discuss how data can be structured using tuples. At first sight, tuples are very similar to lists, but a tuple cannot be changed once it has been created. This makes tuples slightly more efficient and also means that they can be used as dictionary keys. Moreover, tuples are very powerful in combination with functions that return several values.

A tuple is defined by a number of values separated by commas.

coordinates = (23.456, 45.789)

In the provided example, we have a tuple coordinates containing two elements, representing latitude and longitude coordinates, respectively. To access the elements within a tuple, you can do so like this:

>>> coordinates = (23.456, 45.789)
>>> print("These are the coordinates – latitude:", coordinates[0], "and longitude:", coordinates[1])
These are the coordinates – latitude: 23.456 and longitude: 45.789

In this lecture, we also cover pseudorandom numbers.

Exercise 7.1: Warm up - Tuples#

Exercise 7.1

Update: Unfortunately, the original videos were garbled due to some sort of computer issue on my end (you can hear me notice a problem with the preview at the end of the first video, but since I was too dumb to check the full recording, I thought the video were okay..). I have re-recorded the videos but will leave the first on as is since only the last 20 seconds are affected. The example that I type in at the very end is d[3,1], which evaluates to the same result as d[(3,1)].

Tuples share some properties with lists. For example, you can use the len() function to determine the length of a tuple. The most important difference between tuples and lists is that tuples are immutable. This means that you cannot change the values in a tuple after it has been created. In this warm up exercise, you will try some simple operations with tuples.

  • Create an empty tuple and a tuple with one item

  • Check if two tuples have the same length (test your solution by inserting it into the file cp/ex07/have_equal_length.py)

  • Use tuple assignment to swap the values of two variables (compare to the exercise in week 1 (1.8))

  • Try changing a value in a tuple, what happens?

  • Try adding a value to a tuple, what happens?

Exercise 7.2: Warm up - Random numbers#

In this exercise, you will use the random module to generate random numbers and try some useful functions of the random module.

  • Import the random module

  • Generate a random number between 0 and 1

  • Generate a random integer between 1 and 10

  • Generate two random integers between 5 and 10

  • Choose a random element from a list of strings

  • Sample 10 times from [1, 2, 3, 4, 5] with replacement (i.e. the same number can be drawn multiple times)

  • Sample 10 times from [1, 2, 3, 4, 5] with the probabiltiy of drawing each number being proportional to the number itself (i.e. 1 is drawn with probability 1/15, 2 with probability 2/15, etc.)

Repeat all to see how the results change.

Now, fix the seed by using random.seed(42) and repeat all to see how the results change. You should get the same results every time now, why can this be useful? This works, because the generated numbers are pseudorandom, so they are actually generated by a deterministic process based on the seed.

Optional: Try testing your functions this week by generating some random inputs.

Exercise 7.3: Last difference#

In this exercise we want to compute a difference between the values which are at the last position in two tuples, regardless of the length of the tuples.

Consider two tuples \((12, 25, 17.6)\) and \((14, 12.1, 18, -6.7)\). The last element of the first tuple is 17.6 while the last element of the second tuple is -6.7. So, the function should return \(17.6-(-6.7)=24.3\).

You can test your function by running the following code block:

>>> last_difference((12, 25, 17.6), (14, 12.1, 18, -6.7))
24.3

You can also test your function by inserting your solution into the file cp/ex07/last_difference.py.

cp.ex07.last_difference.last_difference(a, b)#

Return the difference between last elements regardless of length.

Parameters
  • a (tuple) – The first tuple.

  • b (tuple) – The second tuple.

Return type

float

Returns

The difference between the last elements of the two tuples.

Exercise 7.4: Returning multiple values#

Using tuples, we can create functions that return multiple values. This can be very useful if you are intrested in multiple values from a function.

In this exercise, we want to return a list of all elements that are bigger than a threshold and the minimum value of the list. You are given a list and a threshold value. The function should return a list of all elements that are bigger than the threshold and the minimum value of the list in a tuple.

Consider a list \([3, 2.4, 1.2, 4.3, -0.5]\) and a threshold value of 2. The function should return the list \([3, 2.4, 4.3]\) and the minimum value of the list, which is -0.5. So, the function should return the tuple \(([3, 2.4, 4.3], -0.5)\).

You can test your function by running the following code block, also try assigning the outputs to separate variables:

>>> returning_multiple_values([3, 2.4, 1.2, 4.3, -0.5], 2)
([3, 2.4, 4.3], -0.5)
>>> threshold_list, minimum_value = returning_multiple_values([3, 2.4, 1.2, 4.3, -0.5], 2)
>>> print(threshold_list)
[3, 2.4, 4.3]
>>> print(minimum_value)
-0.5

You can also test your function by inserting your solution into the file cp/ex07/returning_multiple_values.py.

cp.ex07.returning_multiple_values.returning_multiple_values(values, threshold)#

Return a tuple containing a list of all elements in the list that are greater than the threshold and the minimum of the values.

Parameters
  • values (list) – A list of integers.

  • threshold (int) – An integer.

Return type

tuple

Returns

A tuple containing the a list of elements that are greater than the threshold and the minimum of values

Exercise 7.5: Box packing#

We aim to determine whether a rectangular object can fit within another rectangle (the box). Both the dimensions of the rectangular object and the rectangular box are defined using two-element tuples. Our goal is to calculate the length that object is sticking out from the box for each dimension. When there is sufficient space in a dimension, the function should return 0 for that dimension.

Consider an object with dimensions \((2, 5)\) and a box with dimensions \((4, 2.1)\). In the first dimension there is sufficient space as \(4-2>0\), so the function should return 0 for the first dimension. In the second dimension there is not sufficient space as \(2.1-5<0\), and the object is sticking out. So the function should return \(5-2.1=2.9\) for the second dimension.

Write a function that takes two tuples as input and returns a tuple with the length that the object is sticking out from the box, or 0, for each dimension. You can test your function by running the following code block:

>>> box_packing((2, 5), (4, 2.1))
(0, 2.9)

You can also test your function by inserting your solution into the file cp/ex07/box_packing.py.

cp.ex07.box_packing.box_packing(object, box)#

Return the amount of object sticking in each dimension, or zero if sufficient space.

Parameters
  • object (tuple) – Tuple (h,w) the dimensions of the object

  • box (tuple) – Tuple (H, W) the dimensions of the box.

Return type

tuple

Returns

Tuple

Exercise 7.6: Color hue#

For the next exercise we have to compute the hue of a color given the RGB values. RGB is a color model which uses three values indicating the amount of red, green and blue light. Here we use a convention where each of three RGB values is in a range \([0,1]\). The hue is the color component represented by an angle in degrees, where 0 degree is red, 120 degree is green and 240 degree is blue.

Given a color \((R, G, B)\), the hue can be computed according to the following formulas:

\[\Delta = \max(R,G, B)-\min(R,G,B)\]
\[\begin{split}H = \begin{cases}60 \cdot \frac{G-B}{\Delta} & \text { if } R \text { is the largest RGB-value,} \\ 120+60 \cdot \frac{B-R}{\Delta} & \text { if } G \text { is the largest RGB-value,} \\ 240+60 \cdot \frac{R-G}{\Delta} & \text { if } B \text { is the largest RGB-value. }\end{cases}\end{split}\]

Write a function that takes a tuple of three RGB-values as input and returns the corresponding hue. You can assume that \(\Delta \neq 0\). Also note that:

  • If two of the RGB-values are both largest, the two corresponding lines from the formula will lead to the same result.

  • If the computed value of H is negative, you must add 360 to get the correct value in degrees, so that you have:

\[0 \leq H \leq 360^\circ\]

For example, consider RGB values \((0.6, 0.2, 0.3)\). We have \(\Delta = 0.6-0.2=0.4\). Since \(R\) is the largest RGB-value, we have \(H=60 \cdot \frac{0.2-0.3}{0.4}=-15^\circ\). Since \(H\) is negative, we have to add 360 to get the correct value in degrees, so that we have \(H=345^\circ\).

You can check your function by running the following code block:

>>> RGB = (0.6, 0.2, 0.3)
>>> rgb_to_hue(RGB)
345.0

You can also test the function by inserting your solution into the file cp/ex07/rgb_to_hue.py.

cp.ex07.rgb_to_hue.rgb_to_hue(RGB)#

Return the hue given RGB values.

Parameters

RGB (tuple) – Tuple containing three RGB values.

Return type

float

Returns

Hue in degrees.

Exercise 7.7: Code shift#

A bike lock has 4 dials each with digits from 0 to 9. The code is set by turning the dials in discrete steps. Turning a dial for one stop will increment the digits from 0 to 9, but digit 9 will be set to 0. The dials can be turned in both directions, and we define the positive direction as the direction where digits smaller than 9 increase. If all dials of the lock are turned at once, all code digits will change.

For this exercise create a function which takes as an input a 4-digit code as a tuple of int, and a 4-digit tuple of int, representing a turn of all dials for a number of steps in a positive or a negative direction. The function should return a tuple representing the code after the turn.

For example, consider code \((9, 9, 9, 9)\) and the turns \((1, -1, 2, -2)\). The first dial is turned one step in the positive direction, so the code becomes \((0, 9, 9, 9)\). The second dial is turned one step in the negative direction, so the code becomes \((0, 8, 9, 9)\). The third dial is turned two steps in the positive direction, so the code becomes \((0, 8, 1, 9)\). The fourth dial is turned one step in the negative direction, so the code becomes \((0, 8, 1, 7)\).

You can test your function by running the following code block:

>>> code_shift((9, 9, 9, 9), (1, -1, 2, -2))
(0, 8, 1, 7)

You can also test the function by inserting your solution into the file cp/ex07/code_shift.py.

cp.ex07.code_shift.code_shift(code, turn)#

Return the updated code pattern.

Parameters
  • code (tuple) – Tuple with the initial code in the lock

  • turn (tuple) – Tuple with the turn on each lock dial

Return type

tuple

Returns

Updated lock code.

Exercise 7.8: Morse code#

For project exercises in week 7, the focus is not on tuples, but on general competencies combining all you learned up to now.

Morse code is a method of transmitting messages using a series of short and long signals called “dots” and “dashes”. Letters are separated by a single space ” “, and words are separated by a double space ” “. The Morse alphabet is shown using a dict below:

# Morse code dictionary mapping Morse code symbols to letters
morse_code_dict = {
    '.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G',
    '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N',
    '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R', '...': 'S', '-': 'T', '..-': 'U',
    '...-': 'V', '.--': 'W', '-..-': 'X', '-.--': 'Y', '--..': 'Z'}

Write a function that takes as input a string of Morse code and returns the corresponding text. You can assume that the input string is a valid Morse code string.

For example, consider the string ..  .- --  .-  ... --.- ..- .. .-. .-. . .-... There are four words in this string, separated by two spaces. First word is ... It contains only one letter, letter I. Second word is .- -- which has two letters .- and --. Those letters are A and M, so second word is AM. The third word is one letter A and the fourth word contains letters spelling SQUIRREL. So the function should return I AM A SQUIRREL.

You can test your function by running the following code block:

>>> morse_to_text("..  .- --  .-  ... --.- ..- .. .-. .-. . .-..")
'I AM A SQUIRREL'

You can test the function by inserting your solution into the file cp/ex07/morse_to_text.py.

cp.ex07.morse_to_text.morse_to_text(morse_code)#

Return the extracted message from its Morse code.

Parameters

morse_code (str) – String with the initial message encoded in Morse.

Return type

str

Returns

The decoded message.

Exercise 7.9: Astronomical season#

Task Description:

You are given a date represented as a tuple with two elements:

  • The first element is the day of the month.

  • The second element is the name of the month (jan-dec).

You can use the following dictionary:

month_name_to_month_number = {
    'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6,
    'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12
}

Your task is to write a Python function that as input takes a date as a tuple and returns the string with the corresponding astronomical season.

Astronomical seasons start on specific days of the year:

  • Spring starts on the 20th of March (the first day of astronomical spring).

  • Summer starts on the 21st of June (the first day of astronomical summer).

  • Autumn starts on the 23rd of September (the first day of astronomical autumn).

  • Winter starts on the 21st of December (the first day of astronomical winter).

Your function should determine the season based on the provided date and return one of the following: spring, summer, autumn or winter.

Check the following examples to get a better understanding of how your implementation output should look like:

>>> astronomical_season((20, "mar"))
'spring'
>>> astronomical_season((21, "mar"))
'spring'
>>> astronomical_season((1, "jan"))
'winter'

You can test the function by inserting your solution into the file cp/ex07/astronomical_season.py.

cp.ex07.astronomical_season.astronomical_season(date)#

Return the astronomical season of the given date.

Parameters

date (tuple) – Tuple with the given date.

Return type

str

Returns

String with astronomical season