P1-E002

In this exercise, you learn about some more basic concepts of programming, incl. arrays and ways to let your programme automate calculations and make decisions.

Information

Learning goals

Concepts

  • index value

  • array/vector

  • for loops

  • if statements (if, else if, else)

  • comparison operators

Skills

  • work with arrays

  • implement a for loop

  • let your programme make a decision

Array like collections

Collections can hold multiple values and working with them saves a lot of time, effort and memory. We will explore this a little more in today’s lesson. In Python, we will use 3 types of array like collections: Tuples, Lists and Dictionaries. Let’s have a look at the properties of each and experiment with them.

A tuple is an ordered, unchangeable collection that can store any type of data values (integers, strings, etc.). You can define a tuple using rounded brackets.:

myTuple = ('EARTH', 2140)

A list is an ordered, changeable collection that can store any type of data values (integers, strings, etc.); You can define a list using square brackets, e.g.:

myList = ['EARTH', 2150]

A dictionary - an unordered, indexed, changeable collection that can store any type of data values (integers, strings, etc.); You can define a dictionary using curly brackets, specifying a key and a value e.g.:

myDict = {'place':'EARTH','year':2160}

Start your IDE (e.g. Spyder) and create a tuple, a list and a dictionary in your console, as described above. For each of the array types, we created a 1 dimensional array with a length of 2. In each array, we store 2 values of different data types: 1 string (‘EARTH’) and 1 integer (year). Next, we will explore the properties of each of the Python arrays. Before we can do that, we need to first familiarise ourselves with the concept of an index value.

Index Values

If you type:

print(myTuple)

the print function will return to you the full list:

('EARTH', 2140)

However, often you will only want to use one of the values stored in an array. This is where index values come in handy. From mathematical notation, we are already familiar with index values. Think about the notation for a simple sum of all elements in a vector x (= 4,1,3,9,2):

\[\begin{equation} sum={\sum_{i=1}^{5} }x_i = x_1 + x_2 + x_3 + x_4 + x_5 = 4 + 1 + 3 + 9 + 2 \end{equation}\]

Here, the index value ranges from 1 to 5, and \(x_1 = 4, x_2 = 3\), etc. Index values in programming work in the same way. The index value allows you to access a specific value in your array. If the array is ordered, the index value (an integer), corresponds to the a specific position in the ordered array. Depending on your programming language, the first number may either be 1 or 0. In Python, it is 0.

A good analogy for indexing are elevator controls that take you to floors with different contents. Python would be a German elevator control panel, on which 0 marks the ground floor.

../../_images/elevator_cc0.jpg

The first value in your defined tuple (EARTH) can therefore be accessed by referencing myTuple[0]. Try this by typing:

print(myTuple[0])

We can perform calculations on specific values in an array by referencing it with the index value. Try adding 20 years to the year stored in the second position in the array:

print(myTuple[1]+20)

Now let’s try to update the year with the same calculation and overwrite the old year with the new year:

myTuple[1] = myTuple[1]+20

Did this work? It shouldn’t, because tuples are unchangable and thus don’t allow item assignment. Now try the same with your list and display the updated value using the print function:

myList[1] = myList[1]+20
print(myList[1])

Unlike tuples, lists allow items in the array to be updated as you just did. Finally, let’s explore the properties of dictionaries a little. Try accessing and displaying the year value of the dictionary by typing:

print(myDict[1])

You should get an error message at this point, because dictionaries are not ordered. However, dictionaries are indexed via their keys, and we can access a specific value in dictionaries by using the pre-defined key values. In case of our dictionary, those keys are ‘place’ and ‘year’. Try accessing and displaying the year value by typing:

print(myDict['year'])

This should display to you the year 2160. Since dictionaries are not ordered, the order in which you define its entries doesn’t matter. Try this out by defining a new dictionary just as we did before, but swap the place and year, then repeat the print command above. It will yield the same result.

Useful List Functions

Assume we are managing and maintaining weather station data using Python scripts. Somewhere in the scripts, we would probably want to store the names of different weather stations in a list. Let’s create this list quickly:

stationNames = ['Pan de Azucar', 'Santa Gracia', 'La Campana', 'Reserva Nacional Paposo']

It is possible, that we set up a new weather station in Nahuelbuta and now want to include its name in our list. We can do this ussing the append() function.

stationNames.append('Nahuelbuta')

Check with the print() function if it has been included in the list. You will noticed that it has been appended at the end of the list. Unfortunately, our weather station at ‘Reserva Nacional Paposo’ will no longer be maintained and has to be removed from our list. We can remove it by using del and accessing the entry using an index value to point at the correct position in the list. The station to be removed is in 4th position, which corresponds to the index value 3 in the Python numbering system. Try deleting it by typing:

del stationNames[3]

Check the list again with the print() function. It should be back to a length of 4, include Nahuelbuta at the end, and no longer include Reserva Nacional Paposo.

Finally, here are a few more functions before we move on. Check what they do by printing the results.

stationNames.reverse()              # This will reverse the order in your list
stationNames.sort()                 # This will sort your values in your list
stationNames.count('Pan de Azucar') # This will count the number of times 'Pan de Azucar' occurs in your list
stationNames.index('Pan de Azucar') # This will return the index value for 'Pan de Azucar' (0 before and 3 after list reversal)

Comparison Operators

Most decisions are based on examining a value, comparing it to a reference value, and using their relation as a basis for decision. These comparisons are made possible in programming by using comparison operators. Here’s a list of those operators:

Operator

Meaning

==

equal to

!=

not equal to

<

less than

<=

less than or equal to

>

greater than

>=

greater than or equal to

The general syntax for comparing two values with these operators is:

[value] [comparison operator] [reference value]

We will examine how this is used in practical decision making below.

If Statements

We let our programmes make decisions using If Statements. Let’s look at an example of that. Type the following into your console and make sure the print statement is indented as below.

exercise='boring'
if exercise == 'boring':
    print('deal with it')
print('done')

Now that you have dealt with this, let’s examine what happened. First, you assigned the value ‘boring’ to the variable exercise. In the next line, you used the comparison operator == to check if the value for exercise is indeed boring. It is so, because we defined it in the line above. Since the comparison statement is true, the print function was used to display ‘deal with it’.

Note

Python Syntax

Note the line that started with if ended with a colon. This is important if you use Python. Also important is the the indentation for the next line. It tells Python that the print command is still part of your if statement. In other programming languages, you explicitly state the end of an if statement with something like end if. An unindented code block (in this case the second print statement) following the indented code block tells Python that the end of the if statement is reached.

Try the same again, but assign the value ‘exciting’ to the variable exercise. This should result only in the displaying of the word done, because the programme ignored the indented print statement following a negative result of the value comparisons in the first line.

Decisions can be more complex than that. If one condition is not met, we may want to check if an alternative condition is true. We achieve that using the elif statement in Python, which is short for ‘If the first condition is not met, check this second one’. The else statement translates to ‘for all other conditions’. In your code editor, create a script like below and execute it.

# in this script, we decide on an action based on 1. our target and 2. on who we are

# let's assign some values to our variables
target='human'                    # here, we assign the value 'human' to the target variable
i_am='dalek'                      # here, we assign the value 'dalek' to our identity variable
action='do nothing'               # the default action is set to 'do nothing'

# in the code below, we determine our action based on the values of the 2 variables above
if target == 'human':             # if the target is 'human', proceed down the lines of indented code
    if i_am == 'dalek':           # if we are 'dalek' ...
        action = 'exterminate'    # we set our action to 'exterminate'
    elif i_am == 'cyberman':      # if we are not 'dalek', but we are 'cyberman' ...
        action = 'upgrade'        # we set our action to 'upgrade'
    else:                         # if both checks for our identity came out negative (if we are neither 'dalek' nor 'cyberman') ...
        action = 'greet human'    # we set our action to 'greet human'

print(action)                     # we display the result of our decision making process - note that this function will be executed in disregard of the results of the decision making above, because it is an unindented code block and therefore outside the if statement.

Here, we have nested if statements. Play around with the values you assign to the variables target and i_am and execute your modified code to get a better feeling for how these if statements work.

It’s also possible to combine comparisons in an if statement by using and as such:

# in this script, we decide on an action based on 1. our target and 2. on who we are

# let's assign some values to our variables
target='human'                    # here, we assign the value 'human' to the target variable
i_am='dalek'                      # here, we assign the value 'dalek' to our identity variable
action='do nothing'               # the default action is set to 'do nothing'

# in the code below, we determine our action based on the values of the 2 variables above
if target == 'human' and i_am == 'dalek':       # if the target is 'human' and we are 'dalek' ...
    action = 'exterminate'                      # we set our action to 'exterminate'
elif target == 'human' and i_am == 'cyberman':  # if the target is 'human' and we are 'cyberman' ...
    action = 'upgrade'                          # we set our action to 'upgrade'

print(action)                     # we display the result of our decision making process - note that this function will be executed in disregard of the results of the decision making above, because it is an unindented code block and therefore outside the if statement.

Note that this time, there is no case for target == ‘human’ and i_am being neither dalek nor cyberman, because we lost one level in the if statement hierarchy. We could add this case with another elif statment like:

elif target == 'human' and i_am != 'dalek' and i_am != 'cyberman':
    action = 'greet human'

However, this would not be particularly efficient.

If an action is dependent on only one of several conditions to be true, you can use or to state that. Have a look at the third version of this decision making progress:

# in this script, we decide on an action based on 1. our target and 2. on who we are

# let's assign some values to our variables
target='human'                    # here, we assign the value 'human' to the target variable
i_am='dalek'                      # here, we assign the value 'dalek' to our identity variable
action='do nothing'               # the default action is set to 'do nothing'

# in the code below, we determine our action based on the values of the 2 variables above
if target == 'human':                         # if the target is 'human', proceed down the lines of indented code
    if i_am == 'dalek' or i_am == 'cyberman': # if we are 'dalek' or 'cyberman'...
        action = 'a bad thing'                # we set our action to 'a bad thing'
    else:                                     # if one of the 2 conditions above are not met ...
        action = 'greet human'                # we set our action to 'greet human'

print(action)                                 # we display the result of our decision making process

If you execute this script, it will display a bad thing. Now change the value of the i_am variable to ‘cyberman’ and see what happens. It should give you the exact same result, because assigning ‘a bad thing’ to action is conditional on i_am being either dalek or cyberman.

For Loops

for loops, in other languages also referred to as do loops, are essential in programming as they allow you to automate things. Let’s make the following array:

year = [1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990]

Assume we made a systematic mistake in our list of 10 years and we would like to correct that by adding 1 year to each of our entries. An inefficient way to do this would be:

year[0] = year[0]+1
year[1] = year[1]+1
year[2] = year[2]+1
year[3] = year[3]+1
year[4] = year[4]+1
year[5] = year[5]+1
year[6] = year[6]+1
year[7] = year[7]+1
year[8] = year[8]+1
year[9] = year[9]+1

This is where for loops come in handy. We can tell our programme to do the same calculation for every entry in the array and print the updated value as such:

for i in range(10):
    year[i] = year[i]+1
    print(year[i])

We tell the programme to execute the indented line of code for each instance of the index value i, which is updated 10 times by increments of 1, starting with an initial value of 0. If we only want to update everything after 1984, we can specify the index value range as such:

for i in range(4,10):
    year[i] += 1             # the += operator allows you to shorten the correction of a value
    print(year[i])

This loop now explicitly starts with an index value of 4, which corresponds to the 5th value (1985) and continue updating the index value until the 10th entry.

If you want to create a loop for all values, but do not know the length of your list, you can use the len() function to get it. This can be incorporated into your loop as such:

for i in range(len(year)):
    year[i] += 1

Your Task

You just finished grading 9 exams on atmospheric physics (ugh!). You have 10 students (and number them in a rather dystopian manner), but only 9 of them showed up. You saved the grades in an array and entered a ridiculous number (-9999.0) for the missing student, so you know they didn’t take the exam.

g = [1.7, 2.0, -9999.0, 2.3, 1.3, 1.0, 1.3, 3.3, 1.7, 1.0]

You now want to calculate the arithmetic mean of the students’ greades according to:

\[\begin{equation} mean = \frac { {\sum_{i=1}^{n} }g_i } n \end{equation}\]

Since one of the student was missing, n=9. Write code for at least two different ways to calculate the mean grade based on the g array. Somewhere in your code, you should make use of the following:

  • list functions

  • comparison operators

  • if statements

  • for loops

Try to keep your code as flexible as possible. Ideally, it should still work next year, when a different student may be missing (corresponding to a different position in your list of grades) or when more students fail to take the exam. Also make sure you comment each line of code to let other programmers know what you are doing.

When you are happy with your code, put your two (or more) different methods in one file, save it as [your surname]_e002.[ext] and submit it via ILIAS.

Warning

Late submissions won’t be accepted!