I need help with my programming exam on Sunday at 8;30 am (arabian standard time)
I need help with my programming exam on Sunday at 8;30 am (arabian standard time)
I need help with my programming exam on Sunday at 8;30 am (arabian standard time)I need help with my programming exam on Sunday at 8;30 am (arabian standard time) For example, if bank_statement is the dictionary above, then accountBalance(bank_statement)
should return the following dictionary (note that keys/days are shown ordered just for clarity,
but in the dictionary they could appear in any order):
{
0: 645.03 ,
10: -15.5 ,
15: -172.17 ,
25: 10000.0 ,
32: 10457.36
}
In addition to return the dictionary, the function also saves the content of the dictionary in a file
bank_statement.csv, where each line reports the day and the total of the transactions during
that day, separated by a comma. Note that the lines must be written in ascending order for the
day and the file must be closed after completing the writing. For the example above, the file
will look like the following:
0 , 645.03
10 , -15.5
15 , -172.17
25 , 10000.0
32 , 10457.36
2. 5 points Write the function plotDailyTransactions(bank_statment) that takes as input the
name of a CSV file organized like the file bank_statement.csv and makes a plot of the daily
transactions during the month. More precisely, the function plots the values of the transactions
vs. the days the transactions took place. Days 0 and 32 must be excluded from the data used
for the plot.
Remember to add some meaningful title to the plot and labels to the axes. Moreover, the line
between the data points must be colored in blue.
Variation. What if we wanted a list of balances per day? Can you compute this using the
resulting dictionary?
2
3. Relevant Word Frequency
You are tasked to write a program for finding out the category a text belongs to. In order to
find this out, you decided to see which words occur more frequently in the text, and you wrote a
python program for that. However, on a first attempt, you realized that the most frequent words
are usually irrelevant for guessing a category, such as “the”, “is”, and “are”. You also noticed
that your program would count “Python” and “Python’s” as two different words because of the
contraction.
There are a lot of improvements you can do to your code, so you have decided to implement it
again. This time, instead of having a bare count of each word, it is more meaningful to compute
its frequency, i.e. the number of times the word occurs divided by the total number of relevant
words.
Implement the function relevantWordFreq(text) that takes the text (a string) as a parameter,
and returns a dictionary where the keys are words and values are each word’s frequency. Note
that:
• You should only count words that have more than 3 characters (so “are” should not be
counted, for example).
• All punctuation should be ignored.
• All contractions should be ignored. They are:
– ’m
– ’re
– ’s
– ’ve
– ’ll
– ’d
– n’t
• Capitalization should be ignored and the words in the dictionary should appear in lower
case.
For example, if S is the string:
“””
I am hungry .
Me too , I ’m really hungry ! Let ’s get some food !
“””
then relevantWordFreq(S) should return the dictionary:
{
’ hungry ’: 0.4 ,
’ really ’: 0.2 ,
’ some ’: 0.2 ,
’ food ’: 0.2
}
Variation. What if we also want to take into account verb conjugations? For example, consider
walked and walking as the same “word”.
3
4. Inverted Index
When we search for a term on a search engine (such as Google), it retrieves all documents where
that term occurs. Suppose that information about the documents is stored in a file where each
line contains the name of the document followed by the document’s content. In practice, the file
stores a dictionary data structure, where document names are the keys and document contents
are the values. For example (note the colon character to separate name and content fields):
cs . txt : Python is a programming language
bio . txt : Python is a serpent in the python family
myth . txt : Apollo killed a python serpent
You may assume that in the file the document content was already sanitized, i.e. punctuation
and contractions were removed.
To make retrieval of documents easier, search engines processe the above information file to
convert it into something called inverted index. An inverted index dictionary has words to
search as keys, and the list of documents where the words occur as the values.
Implement the function invertedIndex(information_file) that takes as input a file with documents such as the one above, and returns an inverted index dictionary. Note that:
• You must consider only words of 4 or more characters.
• The keys in the inverted key dictionary appear in lower case.
For example, calling invertedIndex(information_file), where information_file is the file with
the content above, the function must return:
{
’ python ’: [ ’ cs . txt ’ , ’ bio . txt ’ , ’ myth . txt ’] ,
’ programming ’: [ ’ cs . txt ’] ,
’ language ’: [ ’ cs . txt ’] ,
’ serpent ’: [ ’ bio . txt ’ , ’ myth . txt ’] ,
’ family ’: [ ’ bio . txt ’] ,
’ apollo ’: [ ’ myth . txt ’] ,
’ killed ’: [ ’ myth . txt ’]
}
Note that it may be useful / easier to read the file into a dictionary first and then use the
dictionary.
Variation. Can we add some information to this dictionary that will also indicate the number
of times that term occurred in the document, as opposed to only if it occurred or not?
4
5. Bad Friend
You have created a survey to find out who is friends with whom, and the result of this survey
is given to you as a string in the following format:
’’’
Homer : Apu , Moe
Flanders : Homer , Apu , Moe
Apu :
Moe : Homer
’’’
That means that Homer answered that his friends are Apu and Moe; Flanders answered that
his friends are Homer, Apu, and Moe; Apu answered that he has no friends; and Moe answered
that Homer is his only friend.
As you can see, friendship does not go both ways in Springfield. Some people are bad friends,
in the sense that they are considered friends of people that they do not consider friends. For
example, Apu is a bad friend from Homer, because Homer considers Apu his friend, but Apu
does not consider Homer his friend. Curious about this phenomenon, you decided to calculate
how many bad friends each person has.
Implement the function badFriends(s) that takes a string such as the one above as input,
and returns a dictionary where the keys are each person’s name, and the value is an integer
representing the number of bad friends the person has.
For example, if friends is the string above, then badFriends(friends) should return the dictionary:
{
’ Homer ’: 1 ,
’ Flanders ’: 3 ,
’ Apu ’: 0 ,
’ Moe ’: 0
}
Variation. If we want to compute the number of good friends instead, how would you change
your code to achieve that?
5
6. Antisocial Score
You have created a survey to find out who is friends with whom, and the result of this survey
is given to you as a string in the following format:
’’’
Homer : Apu , Moe
Flanders : Homer , Apu , Moe
Apu :
Moe : Homer
’’’
That means that Homer answered that his friends are Apu and Moe; Flanders answered that
his friends are Homer, Apu, and Moe; Apu answered that he has no friends; and Moe answered
that Homer is his only friend.
As you can see, friendship does not go both ways in Springfield. Whenever a person A does not
list B as their friend, but person B lists A, we can say that A is antisocial towards B. This way,
we can compute a person’s antisocial score. We will consider person A’s antisocial score to be
the number of people B such that A does not list B as a friend, but B does list A.
For example, Apu’s antisocial score is 2 because Homer and Flanders list Apu as a friend, but
Apu lists neither as a friend.
Implement the function antisocialScore(s) that takes as input a string as above, and returns
a dictionary where keys are each person’s name, and the value is an integer representing that
person’s antisocial score.
For example, if friends is the string above, then antisocialScore(friends) should return the
dictionary:
{
’ Homer ’: 1 ,
’ Flanders ’: 0 ,
’ Apu ’: 2 ,
’ Moe ’: 1
}
6
7. Friends of Friends
You have created a string with the friendship relation of your favorite TV series as follows:
’’’
Jon :
Tyrion :
Arya :
Jaime :
Brienne :
Pod :
Ramsay :
’’’
Arya , Tyrion
Jon , Jaime , Pod
Jon
Tyrion , Brienne
Jaime , Pod
Tyrion , Brienne , Jaime
That means that Jaime’s friends are Tyrion and Brienne, for example. Given these friendships,
we are interested in finding out a person’s friends of friends. The friends of friends of person A
are those who are friends with A’s friends, but are not A’s friends directly.
Implement the function friendsOfFriends(s) that takes as input a string as above, and returns
a dictionary mapping people to a list with their friends of friends. The list could be in any
order. You were exhaustive, so all persons have an entry.
For example, if got is the string above, then friendsOfFriends(got) should return:
{
’ Jon ’: [ ’ Jaime ’ , ’ Pod ’] ,
’ Tyrion ’: [ ’ Arya ’ , ’ Brienne ’] ,
’ Arya ’: [ ’ Tyrion ’] ,
’ Jaime ’: [ ’ Jon ’ , ’ Pod ’] ,
’ Brienne ’: [ ’ Tyrion ’] ,
’ Pod ’: [ ’ Jon ’] ,
’ Ramsay ’: []
}
Since Jon is a friend of Tyrion, and Tyrion is a friend of Pod, Jon is a friend-of-friend of Pod.
Note that you should exclude any direct friend, so Jaime does not count as a friend-of-friend of
Pod (since he is simply a friend of Pod) despite also being a friend of Tyrion’s.
Variation. What if we want friends of friends of friends?
7
8. Possible Friends
Social networks like to suggest possible friends by looking at friends of our friends. For this
task, assume that possible friends of a person p are those people who:
1. are not p’s friends;
2. are friends with at least 20% of p’s friends.
The friend connection is described in a string were each line is a pair of friends person1 person2,
separated by spaces. Note that friendship is reciprocal, so a pair Omar Yasir means that Omar
is Yasir’s friend and vice-versa.
Implement the function possibleFriends(pairs, person) that receives as a parameter a string
containing pairs of friends (as described above) and the name of a person, and returns the list
of possible friends of person in alphabetical order.
For example, suppose the string S is:
’’’
Omar Yasir
Yasir Maimoon
Ashwini Sameer
Sameer Omar
’’’
then possibleFriends(S, “Sameer”) should return the list [’Yasir’].
Note that Sameer’s friends are Ashwini and Omar (2 friends). People that are not friends with
Sameer are Maimoon and Yasir. Maimoon is only friends with Yasir, who is not Sameer’s friend.
So Maimoon is friends with 0% of Sameer’s friend and thus is not a possible friend. Yasir is
friends with Omar, and thus friends with 50% of Sameer’s friends, and thus a possible friend.
Variation. What if we change the threshold?
8
9. Quiz Average
Professor Saquib keeps the quiz scores for his students in a python string like the following
example:
’’’
nour : 9 ,8.5 ,6.7 ,8
mohammed : 7 ,6.8 , – ,7
salma : 6 ,8 , ,7.6
claire : 8 ,8.7 ,6 ,9
’’’
Each line corresponds to a student, and their scores are separated by commas. If a student had
a medical excuse for the quiz, it is marked with a dash -, and if a student has missed a quiz, it
is left blank ,,.
Implement the function quizAvg(s) that takes a string as the one above as a parameter, and
returns a dictionary where the keys are students’ names, and values are their quiz averages.
But note that:
• Professor Saquib has the policy of dropping the lowest quiz, so it should not be considered
for the average.
• If a student has an excuse, that quiz should not be considered for the average.
• If a student missed a quiz, it is considered that they got score 0 and it still counts for the
average.
For example, if scores is the string above, then quizAvg(scores) should return the dictionary
(floating point numbers are truncated to three decimals for the sake of readability, but your
solution can have the numbers with all decimals):
{
’ nour ’: 8.5 ,
’ mohammed ’: 7.0 ,
’ salma ’: 7.2 ,
’ claire ’: 8.567
}
Variation. What if a student only has medical excuses, or took only one quiz? Do we still
drop the lowest? What would change if professor Saquib wanted to get the class average for
each quiz?
9
10. Diagnose Symptoms
As a diligent doctor, you keep a list of diseases and their symptoms for quick consultation, like
this:
common cold: sore throat, sneezing, cough, runny nose
flu: fever, headache, weakness, body aches, cough
asthma: wheezing , shortness of breath, tight chest, cough
allergies: sneezing, runny nose, cough, wheezing, rash
bronchitis: sore throat, headache, runny nose, body aches
However, most of the times patients have multiple symptoms, and trying to find which diseases
match all of their symptoms is confusing and takes a long time (not to mention, it is much
easier to make mistakes).
As a diligent programmer, you realize that you can write a program to compute the most likely
diseases for you.
Implement the function diagnoseSymptoms(s, sym) that takes as input a string s with diseases
and symptoms like the one above, and a list of symptoms sym; and returns a list of the most
likely diseases in alphabetical order.
The most likely diseases are those that match the greatest amount of symptoms of the patient.
For example, if diseases is the string above, then diagnoseSymptoms(diseases,[’wheezing’,’cough’])
should return the list: [’allergies’,’asthma’]. That is because all of the patient’s symptoms
are symptoms of these two conditions.
On the other hand, diagnoseSymptoms(diseases,[’wheezing’,’cough’,’headache’]) should return the list: [’allergies’,’asthma’,’flu’]. That is because all these three conditions match
two out of the patient’s three symptoms.
Variation. What if we want to take into account the “frequency” of symptoms? For example,
if a disease has 5 symptoms and it matched 3, it should be more likely than a disease that has
10 symptoms and matched 3.
10
11. Age Buckets
You have a dictionary with peoples names and their date of birth as follows:
{
’ Sofia ’: ’ 27/1/1997 ’ ,
’ Maria ’: ’ 5/3/1996 ’ ,
’ Lucia ’: ’ 7/6/1997 ’ ,
’ Martina ’: ’ 15/12/1997 ’ ,
’ Catalina ’: ’ 14/1/1998 ’ ,
’ Elena ’: ’ 17/6/1995 ’ ,
’ Emilia ’: ’ 17/4/1999 ’ ,
’ Valentina ’: ’ 23/9/1998 ’ ,
’ Paula ’: ’ 9/2/1994 ’ ,
’ Zoe ’: ’ 29/10/1999 ’
}
Given this dictionary and today’s date, you would like to split the people into b age buckets.
Each bucket will contain the names of people whose age is within a certain range. For example,
suppose today is April 7, 2020 and you would like to split the set of people above into 3 buckets.
Their ages range from 20 to 26 years old, and we want to split this interval into 3 parts. The
split should be at an integer to make things easier, so the size of each bucket should be computed
as: ceil( (26-20) / 3). The size of the buckets in this case is 2, and this results in:
• Bucket 1: people aged 20 to 22 (not inclusive) years old
• Bucket 2: people aged 22 to 24 (not inclusive) years old
• Bucket 3: people aged 24 to 26 (inclusive) years old
Therefore, people are distributed in the following manner:
• Bucket 1: Emilia, Zoe, Valentina
• Bucket 2: Catalina, Lucia, Martina, Sofia
• Bucket 3: Elena, Maria, Paula
Implement the function ageBuckets(d, t, b) that takes as input a dictionary d as the one
above, today’s date as a string in the format d/m/y, and the number of buckets b as an integer.
The function should return another dictionary, where the keys are the beginning of each bucket’s
range, and the value is a list of names of people in that bucket (in any order).
For example, if bdict is the dictionary above, ageBuckets(bdict, “7/4/2020”, 3) should return
the dictionary:
{
20: [ ’ Emilia ’ , ’ Zoe ’ , ’ Valentina ’] ,
22: [ ’ Catalina ’ , ’ Lucia ’ , ’ Martina ’ , ’ Sofia ’] ,
24: [ ’ Elena ’ , ’ Maria ’ , ’ Paula ’]
}
11
changes depending on the data type of .
If is a mutable object, and
will now point to the same memory area,
such as any further changes to the values of
will result in changing the values of and vice versa.
In other words, and become aliases
(for referring to the same memory area where the numeric
content is stored).
Notes
Notes
Notes
Numeric operators
• Addition: +
• x //= a
• Subtraction: –
• x %= a
• Multiplication: *
• x **= a
• Real division: /; given that x÷y = y·n+r, the operator
returns y · n + r as a float
Notes
• Integer division: //; the operator returns n
• Module: %; the operator returns r
• Power: **
All numeric (arithmetic) operators, except power, apply to
two operands in expressions of the form:
numeric_operator
The resulting type of the expression depends both on the
operator and on the type of the operands.
Arithmetic operators can be used with numeric data types
int, float, complex, as well as with bool object types
based on the convention that True is automatically converted to int 1 and False to int 0.
+ and * are also overloaded operators for operations on object types str, where + requires two string operands and *
requires one string and one integer operand.
All the arithmetic operators also allow for augmented assignment forms to update (in-place) the value of an existing
variable x, where a is the literal/variable value used for updating x:
Relational operators
• x is equal to y: x == y
• x is not equal to y: x != y
• x is greater than y: x > y
• x is greater than or equal to y: x >= y
• x += a
• x is less than y: x < y
• x -= a
• x is less than or equal to y: x
not
and
or
– string_var = input(msg)
Notes
Useful standard library functions
• Type checking, casting and conversion:
– type(x)
3
• Mathematical operations:
• Comparison: comparisons between strings using the relational operators are based on the UTF-8 encoding,
that assigns an integer to each character.
– val = min(values, )
– val = max(values, )
• Indexing: [index] operator, where for a string of length
n i is an integer taking values in the range from 0 to
n 1 or from n to 1.
– val = sum(values)
– seq_generator = range(from, to, step)
• Slicing: [from:to], where for a string of length n from
and to are integers taking values in the same range as
above.
– val = abs(v)
– val = pow(x, y)
Notes
• Slicing with a stride: [from:to:step], where for a
string of length n from, to and step are integers taking
values in the same range as above.
• Membership: in, not in, E.g., part_of = s1 in s2,
where s1 and s2 are strings and part_of is a boolean.
Notes
• Operations on sequences or sets:
– length = len(s)
– new_seq = sorted(seq, , )
• Evaluation of strings as python expressions:
– expr_result = eval(expr)
String methods
• Character to/from integer code conversions:
• Case conversions:
– character = chr(utf_numeric_code)
– s_new = s.capitalize()
– utf_numeric_code = ord(character)
– s_new = s.swapcase()
Notes
– s_new = s.title()
– s_new = s.lower()
– s_new = s.upper()
Notes
String operators
Strings are ordered sequences of characters, that can
be defined using single, double, or triple quotes:
s = ’Hello’, s = ‘‘Hello’’, s = ’’’Hello’’’. Strings are
non-scalar, immutable types.
• Concatenation: +, += operators (overloaded)
• Count, Find, and Replace:
• Duplication: *, *= operators (overloaded)
– occurrences = s.count(substring, from, to)
4
– bool_var = s.endswith(suffix, from, to)
Notes
– bool_var = s.startswith(prefix, from, to)
– index = s.find(substring, from, to)
– index_rev = s.rfind(substring, from, to)
– s_new = s.replace(old, new)
– s_new = s.replace(old, new, max_times)
Notes
List/tuple definition
Tuples and lists are non-scalar types representing ordered
sequences of objects (any type). Tuples are immutable, lists
are mutable.
– tuple examples: (1,2,3); 1,’a’,(2,3); (2,)
– list examples: [1,’h’]; [[2,3],(2,5),’h’]; [2]
– definition of an empty tuple: t = ()
– definition of an empty list: l = []
– definition of an empty list of n elements all set to 0:
l = [0]*n
• Manipulate strings and lists:
– definition of an empty list of n elements all set to None:
l = [None]*n
– string_joining_strings_in_list = s.join(seq)
– list_of_substrings = s.split(=’ ’, )
– definition of an empty list of n (empty) lists:
l = [[]]*n
– list_of_substrings = s.rsplit(=’ ’, )
– definition of a list of n lists each with one element of
value 1: l = [[1]]*n
Notes
– definition of a new list as an alias of an existing list:
l_new = l_exist
– definition of a new list as a clone of an existing list:
l_new = l_exist[:]
– definition of a new list as a clone of an existing list:
l_new = l_exist.copy()
– definition of a new list as a clone of an existing list:
l_new = []; l_new += l_exist
• String classification by characters:
– definition of a new list as a clone of an existing list:
l_new = []; l_new.extend(l_exist)
– bool_var = s.isalpha()
– bool_var = s.isalnum()
Notes
– bool_var = s.isdigit()
– bool_var = s.isidentifier()
– bool_var = s.islower()
– bool_var = s.isupper()
– bool_var = s.isprintable()
– bool_var = s.isspace()
– bool_var = s.istitle()
5
List/tuple operators
Notes
• Indexing: [index] operator, where for a list/tuple of
length n index is an integer taking values in the range
from 0 to n 1 or from n to 1.
• Slicing: [from:to], where for a list/tuple of length n
from and to are integers taking values in the same range
as above.
• Slicing with a stride: [from:to:step], where for a tuple/list of length n from, to and step are integers taking values in the same range as above.
• Nested indexing: [i][j][k]...[n], when a list/tuple l
contains elements l[i] that are in turn lists/tuples, the
j-th element of the list/tuple l[i] can be accessed using
the notation l[i][j]. The notation can be iterated if
there are multiple nested lists/tuples. E.g., l[i][j][k]
accesses the k-th element of the j-th list element of the
i-th list element of list l.
x = [ [1,2,3], [4,5,6] ]; x[0][1] is 2, while
x[1][1] is 5
x = [ [ [1, ’a’], [2, ’c’] ], [4,5,6] ];
x[0][1] is [2, ’c’], x[0][1][1] is ’c’,
x[1][1][1] doesn’t exist
List/tuple methods
• l.append(item)
• Concatenation: +, += operators (overloaded), where for
lists += is an in-place operator while + is not
• l.insert(index)
• l.extend(existing_list)
• Duplication: *, *= operators (overloaded), where for
lists *= is an in-place operator while * is not
• l.remove(item)
• removed_item = l.pop(index)
• Comparison: comparisons between two tuples/lists can
be done using the relational operators; two tuples/lists
are equal (==) if they have the same content, while they
are di↵erent (!=) if their content is di↵erent; the comparison for greater/less than is performed between the
elements at position index 0 of the two tuples/list based
on their data type, that must be either the same or allow for comparison (e.g., both numeric types); if the
two elements at position 0 are the same, the elements
at position 1 of the two tuples/list are considered, and
so on until the comparison can be precisely assessed.
• occurrences = l.count(item)
• index_of_first_occurrence = l.index(item)
• l.sort(, )
• l.reverse()
• l_new = l.copy()
Notes
[0,1] == [0,1] returns True
[0,1] < [1,3,7,8] returns True
[0,’a’] < [0,’b’] returns True
[[1,2],’a’] > [[0,1],’b’] returns True
• Membership: in, not in, where l1 in l2, evaluates to
True if l1 is a sub-list of l2.
[4,5] in [[1,2,3],[4,5]] returns True
[4] in [1,2,3,4,5] returns False
4 in [1,2,3,4,5] returns True
6
Constructs for conditional decisions
string is ’abd’ at the end of the loop
• if boolean_expression_is_true:
do_something
– add_odd = 0
for i in range(1,12,2):
add_odd += i
• if boolean_expression_is_true:
do_something
else:
do_something_else
add_odd is 25 at the end of the loop
– for i in range(1,10):
print(‘‘Hello!’’)
“Hello!” is output for 10 times
• if boolean_expression_1_is_true:
do_something_1
elif boolean_expression_2_is_true:
do_something_else_2
elif boolean_expression_3_is_true:
do_something_else_3
…
– cars = [[’Cor’, 2015],[’Sen’, 2014],[’Cam’, 2016]]
years = [2015, 2016, 2018]
count = 0
for c in cars:
for y in years:
if c[1] == y:
count += 1
• if boolean_expression_1_is_true:
do_something_1
elif boolean_expression_2_is_true:
do_something_else_2
elif boolean_expression_3_is_true:
do_something_else_3
else:
do_something_else
count is 2 at the end of the two nested loops
– m = [[]]*2
m[0] = [1,2,3]
m[1] = [4,5,6,7]
add = 0
for i in range(len(m)):
for j in range(len(m[i])):
add += m[i][j]
add is 28 at the end of the two nested loops
Notes
Notes
Constructs for iteration: for loops
Constructs for iteration: while loops
Definite loops invoked with the following syntax:
for variable in sequence:
do_actions
Indefinite loops invoked with the following syntax:
while boolean_condition_is_true:
do_actions
– x = [1,4,5]
prod = 1
for i in x:
prod *= i
prod is 20 at the end of the loop
– v = 5
discounts = []
while v > 1:
v *= 0.95
discounts.append(v)
– x = [’a’,’b’,’d’]
string = ’’
for s in x:
string += s
discounts contains 32 values between 1 and 5 at the
end of the loop.
7
– add = 0
while True:
v = input(‘‘Give a positive integer number:’’)
if v.isdigit():
if int(v) == 0:
break
else
add += int(v)
Notes
a potentially infinite loop, it ends when input is 0.
Notes
Functions: definition, args, returns
A function is a named procedure that can be invoked anywhere in the program. It can have or not input arguments,
and always returns something by means of the return statement. If no return statement is included in the function definition, the statement return None is executed by default.
The general syntax for defining a function is:
def function_name(arguments):
function_body
return something
Statements for iteration:continue,break
• Variables defined in the function body have a local
scope, they exist in the program only for the time of
execution of the function. As such, they are not accessible outside the function, as shown in the example:
• continue: Conditionally skip an iteration body
numbers = [3, -1, 4, 0, 5]
percent = []
for n in numbers:
if n max_val:
max_val = f(x)
x_max = x
x += delta
return (x_max, max_val)
• Keyword arguments: arguments are matched by the
name given in the function definition.
The call quadratic_roots(a=1, b=3, c=2)
produces the same e↵ect as the calls
quadratic_roots(b=3, c=2, a=1),
quadratic_roots(c=3, a=1, b=3).
• Mixed arguments: Positional and keyword arguments
can be used together, but the positional ones must precede the keyword ones.
find_max_over_interval(parabola, -2, 2, 0.1)
find_max_over_interval(cubic, -3, 1, 0.1)
the function find_max_over_interval can be
called with any existing function passed by reference as the argument f, in turn f can be used
to regularly invoke the input function inside the
function body.
quadratic_roots(1, c=3, b=2) has the same effects of quadratic_roots(c=3, a=1, b=2) and
of quadratic_roots(1, 3, 2), while calling
quadratic_roots(b=2, a=1, 3) is not allowed.
• Default values for arguments: if the value for an argument is not given explicitly when the function is called,
the argument takes its default value; the use of default
values makes an argument optional in practice.
Docstrings and inline comments
For sharing and reusing purposes, functions need to have a
specification, which is a string constant placed right below
def discount(values, d = 0.5):
for i in range(len(values)):
9
Import statements
Notes
• import module_name: load the entire module, need to
refer to module’s functions as methods using the dot
notation, module_name.function_name().
• import module_name as alias_name: define a name
alias for module_name, such as module’s functions have
to be referred to as methods using the dot notation and
the alias, alias_name.function_name().
• from module_name import function_name: instead
of loading the entire module only the specified function from the module is being loaded (copied) into the
current program, no need to use dot notation to refer
to the function.
• from module_name import f_1, f_2, f_3: instead
of loading the entire module only the specified functions
from the module are being loaded (copied) into the current program, no need to use dot notation to refer to
the functions.
the def statement of the function. This string constant is
called a docstring. It is common practice to use triple single
quotes ’’’ to write the string constant with the specification
text since this allows to write a multi-line string.
• from module_name import *: all functions from the
module are copied into the current program, no need to
use dot notation to refer to any of the functions; possible
issues with variable/function names clashing with those
of the calling program.
A specification needs to include a description of the input
parameters, their type and accepted values, any other actions that need to be in place before calling the function,
the e↵ects of the function, describing the returned values
and possibly modifications through the parameters. A simplified example is shown below.
def add(x, y):
’’’Sum two objects x and y.
The sum is returned. Type depends on x and y.
An error is thrown if the + operator
cannot be used between the two passed objects.’’’
return x + y
The help(f) function, when invoked with the name of another function f as an argument, returns the description of
the function and of its parameters as given by the function
developer through the specification in the docstring.
In addition to the specification, it is good practice to provide
inline additional comments to document the text. This can
be done by using either # for single-line comments or string
constants for multi-line comments.
Notes
10
Notes
changes depending on the data type of .
If is a mutable object, and
will now point to the same memory area,
such as any further changes to the values of
will result in changing the values of and vice versa.
In other words, and become aliases
(for referring to the same memory area where the numeric
content is stored).
Notes
Notes
Notes
Numeric operators
• Addition: +
• x //= a
• Subtraction: –
• x %= a
• Multiplication: *
• x **= a
• Real division: /; given that x÷y = y·n+r, the operator
returns y · n + r as a float
Notes
• Integer division: //; the operator returns n
• Module: %; the operator returns r
• Power: **
All numeric (arithmetic) operators, except power, apply to
two operands in expressions of the form:
numeric_operator
The resulting type of the expression depends both on the
operator and on the type of the operands.
Arithmetic operators can be used with numeric data types
int, float, complex, as well as with bool object types
based on the convention that True is automatically converted to int 1 and False to int 0.
+ and * are also overloaded operators for operations on object types str, where + requires two string operands and *
requires one string and one integer operand.
All the arithmetic operators also allow for augmented assignment forms to update (in-place) the value of an existing
variable x, where a is the literal/variable value used for updating x:
Relational operators
• x is equal to y: x == y
• x is not equal to y: x != y
• x is greater than y: x > y
• x is greater than or equal to y: x >= y
• x += a
• x is less than y: x < y
• x -= a
• x is less than or equal to y: x
not
and
or
– string_var = input(msg)
Notes
Useful standard library functions
• Type checking, casting and conversion:
– type(x)
3
• Mathematical operations:
• Comparison: comparisons between strings using the relational operators are based on the UTF-8 encoding,
that assigns an integer to each character.
– val = min(values, )
– val = max(values, )
• Indexing: [index] operator, where for a string of length
n i is an integer taking values in the range from 0 to
n 1 or from n to 1.
– val = sum(values)
– seq_generator = range(from, to, step)
• Slicing: [from:to], where for a string of length n from
and to are integers taking values in the same range as
above.
– val = abs(v)
– val = pow(x, y)
Notes
• Slicing with a stride: [from:to:step], where for a
string of length n from, to and step are integers taking
values in the same range as above.
• Membership: in, not in, E.g., part_of = s1 in s2,
where s1 and s2 are strings and part_of is a boolean.
Notes
• Operations on sequences or sets:
– length = len(s)
– new_seq = sorted(seq, , )
• Evaluation of strings as python expressions:
– expr_result = eval(expr)
String methods
• Character to/from integer code conversions:
• Case conversions:
– character = chr(utf_numeric_code)
– s_new = s.capitalize()
– utf_numeric_code = ord(character)
– s_new = s.swapcase()
Notes
– s_new = s.title()
– s_new = s.lower()
– s_new = s.upper()
Notes
String operators
Strings are ordered sequences of characters, that can
be defined using single, double, or triple quotes:
s = ’Hello’, s = ‘‘Hello’’, s = ’’’Hello’’’. Strings are
non-scalar, immutable types.
• Concatenation: +, += operators (overloaded)
• Count, Find, and Replace:
• Duplication: *, *= operators (overloaded)
– occurrences = s.count(substring, from, to)
4
– bool_var = s.endswith(suffix, from, to)
Notes
– bool_var = s.startswith(prefix, from, to)
– index = s.find(substring, from, to)
– index_rev = s.rfind(substring, from, to)
– s_new = s.replace(old, new)
– s_new = s.replace(old, new, max_times)
Notes
List/tuple definition
Tuples and lists are non-scalar types representing ordered
sequences of objects (any type). Tuples are immutable, lists
are mutable.
– tuple examples: (1,2,3); 1,’a’,(2,3); (2,)
– list examples: [1,’h’]; [[2,3],(2,5),’h’]; [2]
– definition of an empty tuple: t = ()
– definition of an empty list: l = []
– definition of an empty list of n elements all set to 0:
l = [0]*n
• Manipulate strings and lists:
– definition of an empty list of n elements all set to None:
l = [None]*n
– string_joining_strings_in_list = s.join(seq)
– list_of_substrings = s.split(=’ ’, )
– definition of an empty list of n (empty) lists:
l = [[]]*n
– list_of_substrings = s.rsplit(=’ ’, )
– definition of a list of n lists each with one element of
value 1: l = [[1]]*n
Notes
– definition of a new list as an alias of an existing list:
l_new = l_exist
– definition of a new list as a clone of an existing list:
l_new = l_exist[:]
– definition of a new list as a clone of an existing list:
l_new = l_exist.copy()
– definition of a new list as a clone of an existing list:
l_new = []; l_new += l_exist
• String classification by characters:
– definition of a new list as a clone of an existing list:
l_new = []; l_new.extend(l_exist)
– bool_var = s.isalpha()
– bool_var = s.isalnum()
Notes
– bool_var = s.isdigit()
– bool_var = s.isidentifier()
– bool_var = s.islower()
– bool_var = s.isupper()
– bool_var = s.isprintable()
– bool_var = s.isspace()
– bool_var = s.istitle()
5
List/tuple operators
Notes
• Indexing: [index] operator, where for a list/tuple of
length n index is an integer taking values in the range
from 0 to n 1 or from n to 1.
• Slicing: [from:to], where for a list/tuple of length n
from and to are integers taking values in the same range
as above.
• Slicing with a stride: [from:to:step], where for a tuple/list of length n from, to and step are integers taking values in the same range as above.
• Nested indexing: [i][j][k]...[n], when a list/tuple l
contains elements l[i] that are in turn lists/tuples, the
j-th element of the list/tuple l[i] can be accessed using
the notation l[i][j]. The notation can be iterated if
there are multiple nested lists/tuples. E.g., l[i][j][k]
accesses the k-th element of the j-th list element of the
i-th list element of list l.
x = [ [1,2,3], [4,5,6] ]; x[0][1] is 2, while
x[1][1] is 5
x = [ [ [1, ’a’], [2, ’c’] ], [4,5,6] ];
x[0][1] is [2, ’c’], x[0][1][1] is ’c’,
x[1][1][1] doesn’t exist
List/tuple methods
• l.append(item)
• Concatenation: +, += operators (overloaded), where for
lists += is an in-place operator while + is not
• l.insert(index)
• l.extend(existing_list)
• Duplication: *, *= operators (overloaded), where for
lists *= is an in-place operator while * is not
• l.remove(item)
• removed_item = l.pop(index)
• Comparison: comparisons between two tuples/lists can
be done using the relational operators; two tuples/lists
are equal (==) if they have the same content, while they
are di↵erent (!=) if their content is di↵erent; the comparison for greater/less than is performed between the
elements at position index 0 of the two tuples/list based
on their data type, that must be either the same or allow for comparison (e.g., both numeric types); if the
two elements at position 0 are the same, the elements
at position 1 of the two tuples/list are considered, and
so on until the comparison can be precisely assessed.
• occurrences = l.count(item)
• index_of_first_occurrence = l.index(item)
• l.sort(, )
• l.reverse()
• l_new = l.copy()
Notes
[0,1] == [0,1] returns True
[0,1] < [1,3,7,8] returns True
[0,’a’] < [0,’b’] returns True
[[1,2],’a’] > [[0,1],’b’] returns True
• Membership: in, not in, where l1 in l2, evaluates to
True if l1 is a sub-list of l2.
[4,5] in [[1,2,3],[4,5]] returns True
[4] in [1,2,3,4,5] returns False
4 in [1,2,3,4,5] returns True
6
Constructs for conditional decisions
string is ’abd’ at the end of the loop
• if boolean_expression_is_true:
do_something
– add_odd = 0
for i in range(1,12,2):
add_odd += i
• if boolean_expression_is_true:
do_something
else:
do_something_else
add_odd is 25 at the end of the loop
– for i in range(1,10):
print(‘‘Hello!’’)
“Hello!” is output for 10 times
• if boolean_expression_1_is_true:
do_something_1
elif boolean_expression_2_is_true:
do_something_else_2
elif boolean_expression_3_is_true:
do_something_else_3
…
– cars = [[’Cor’, 2015],[’Sen’, 2014],[’Cam’, 2016]]
years = [2015, 2016, 2018]
count = 0
for c in cars:
for y in years:
if c[1] == y:
count += 1
• if boolean_expression_1_is_true:
do_something_1
elif boolean_expression_2_is_true:
do_something_else_2
elif boolean_expression_3_is_true:
do_something_else_3
else:
do_something_else
count is 2 at the end of the two nested loops
– m = [[]]*2
m[0] = [1,2,3]
m[1] = [4,5,6,7]
add = 0
for i in range(len(m)):
for j in range(len(m[i])):
add += m[i][j]
add is 28 at the end of the two nested loops
Notes
Notes
Constructs for iteration: for loops
Constructs for iteration: while loops
Definite loops invoked with the following syntax:
for variable in sequence:
do_actions
Indefinite loops invoked with the following syntax:
while boolean_condition_is_true:
do_actions
– x = [1,4,5]
prod = 1
for i in x:
prod *= i
prod is 20 at the end of the loop
– v = 5
discounts = []
while v > 1:
v *= 0.95
discounts.append(v)
– x = [’a’,’b’,’d’]
string = ’’
for s in x:
string += s
discounts contains 32 values between 1 and 5 at the
end of the loop.
7
– add = 0
while True:
v = input(‘‘Give a positive integer number:’’)
if v.isdigit():
if int(v) == 0:
break
else
add += int(v)
Notes
a potentially infinite loop, it ends when input is 0.
Notes
Functions: definition, args, returns
A function is a named procedure that can be invoked anywhere in the program. It can have or not input arguments,
and always returns something by means of the return statement. If no return statement is included in the function definition, the statement return None is executed by default.
The general syntax for defining a function is:
def function_name(arguments):
function_body
return something
Statements for iteration:continue,break
• Variables defined in the function body have a local
scope, they exist in the program only for the time of
execution of the function. As such, they are not accessible outside the function, as shown in the example:
• continue: Conditionally skip an iteration body
numbers = [3, -1, 4, 0, 5]
percent = []
for n in numbers:
if n max_val:
max_val = f(x)
x_max = x
x += delta
return (x_max, max_val)
• Keyword arguments: arguments are matched by the
name given in the function definition.
The call quadratic_roots(a=1, b=3, c=2)
produces the same e↵ect as the calls
quadratic_roots(b=3, c=2, a=1),
quadratic_roots(c=3, a=1, b=3).
• Mixed arguments: Positional and keyword arguments
can be used together, but the positional ones must precede the keyword ones.
find_max_over_interval(parabola, -2, 2, 0.1)
find_max_over_interval(cubic, -3, 1, 0.1)
the function find_max_over_interval can be
called with any existing function passed by reference as the argument f, in turn f can be used
to regularly invoke the input function inside the
function body.
quadratic_roots(1, c=3, b=2) has the same effects of quadratic_roots(c=3, a=1, b=2) and
of quadratic_roots(1, 3, 2), while calling
quadratic_roots(b=2, a=1, 3) is not allowed.
• Default values for arguments: if the value for an argument is not given explicitly when the function is called,
the argument takes its default value; the use of default
values makes an argument optional in practice.
Docstrings and inline comments
For sharing and reusing purposes, functions need to have a
specification, which is a string constant placed right below
def discount(values, d = 0.5):
for i in range(len(values)):
9
Import statements
Notes
• import module_name: load the entire module, need to
refer to module’s functions as methods using the dot
notation, module_name.function_name().
• import module_name as alias_name: define a name
alias for module_name, such as module’s functions have
to be referred to as methods using the dot notation and
the alias, alias_name.function_name().
• from module_name import function_name: instead
of loading the entire module only the specified function from the module is being loaded (copied) into the
current program, no need to use dot notation to refer
to the function.
• from module_name import f_1, f_2, f_3: instead
of loading the entire module only the specified functions
from the module are being loaded (copied) into the current program, no need to use dot notation to refer to
the functions.
the def statement of the function. This string constant is
called a docstring. It is common practice to use triple single
quotes ’’’ to write the string constant with the specification
text since this allows to write a multi-line string.
• from module_name import *: all functions from the
module are copied into the current program, no need to
use dot notation to refer to any of the functions; possible
issues with variable/function names clashing with those
of the calling program.
A specification needs to include a description of the input
parameters, their type and accepted values, any other actions that need to be in place before calling the function,
the e↵ects of the function, describing the returned values
and possibly modifications through the parameters. A simplified example is shown below.
def add(x, y):
’’’Sum two objects x and y.
The sum is returned. Type depends on x and y.
An error is thrown if the + operator
cannot be used between the two passed objects.’’’
return x + y
The help(f) function, when invoked with the name of another function f as an argument, returns the description of
the function and of its parameters as given by the function
developer through the specification in the docstring.
In addition to the specification, it is good practice to provide
inline additional comments to document the text. This can
be done by using either # for single-line comments or string
constants for multi-line comments.
Notes
10
Notes
• Reading: [key] operator, that returns the values associated to key, if key is in the dictionary, error otherwise.
intensity = d[’red’]
Notes
• Modifying: [key] operator that allows to to modify the
value associated to an existing key. d[’red’] = 245
• Comparison: comparisons of equality between two dictionaries can be done using the relational operator ==
that returns True if the dictionaries have exactly the
same content (keys and values), False otherwise. Opposite for the operator !=. Other relational operators
do not apply to dictionaries.
• Membership: in, not in, where key in d, evaluates to
True if key key is a one of the keys of dictionary d.
Notes
Files
Files are custom, permanent data structures that, in general, reside on a physical support other than the RAM. Files
come with a number of class methods for opening, reading,
writing file contents. Files can be of binary or text type.
Binary files requires a specific encoding and possibly a specific program to read/write them. Text files are organized
in multiple records of data, separated by newline characters,
where each record is composed of one or more fields. Record
composition doesn’t need to be uniform across the file. The
size of a file is measured in bytes, where a byte is 8 bits.
An ASCII character is encoded in a byte. More complex
encodings (UTF) require in general more bytes.
Dictionary methods
File methods
• l = d.keys()
• f_handler = open(filename, ),
where
mode
can
include
combinations
of:
’r’, ’r+’, ’w’, ’w+’, ’a’, ’a+’, ’x’, ’b’, ’t’
• l = d.values()
• list_of_key_val_pairs = d.items()
• string_with_data = f.read()
• v = d.get(key, )
• position = f.seek(()
• v = d.pop(key, )
• position = f.tell(()
• (key,val) = d.popitem()
• record = f.readline()
• d.clear()
• remaining_records = f.readlines()
• d.update(iterable), where iterable is an iterable
of (key, value) such as a dictionary or a sequence
[(’r’,10), (’b’, 90), (’g’, 122)]
• written_bytes = f.write(string_to_write)
• read_mode = f.readable()
• d.setdefault(key, )
• write_mode = f.writable()
• d_new = d.copy()
• f.flush()
• d.fromkeys(key_list, )
• f.close()
2
• Header is needed if the file will be read in dictionary
mode:
Notes
names = [’name’,’dept’,’since’,’score’]
csv_writer = csv.DictWriter(f_csv, fieldnames=names)
csv_writer.writeheader()
• next(csv_data), this is a function, not a method, that
makes an iterator to execute one step, for a file means
that the reading/writing position is moved one record
down.
Notes
CSV files
CSV files (comma-separated files), are commonly used formats for data storing and sharing. CSV files are text data
files where the records shares the same field structure across
the file, and are separated by newlines. In spite of the name,
in CSV files it is possible to select the field separator, quoting and escape characters, as well as conveniently treat the
records as a sequence of ordered dictionaries.
Handling exceptions
The csv module (import csv) o↵ers a number of methods
for the e↵ective manipulation of CSV files both in reading
and writing modes. A CSV file handler is constructed that
allows a flexible access to the file. The file must be first
opened in the appropriate mode using the usual open call:
f_csv = open(file_path).
When an error occurs during the program, Python generates
an exception: it generates an error type that identifies the
exception and then stops the execution. Exceptions can be
handled using the try statement to avoid that the program
stops when an error occurs during the execution.
try-except-else-finally blocks:
• The try block let executing a block of code that can
potentially generate an exception
CSV file methods
• csv_data = csv.reader(f_csv, ,
)
• The finally block let executing the code, regardless of
the result of the try- and except blocks.
• csv_writer.writerow(list_of_data_fields)
• Example of use:
• csv_writer.writerows(list_of_lists_of_fields)
y =1 try:
x /= 10
y += x except:
print(“x doesn’t exist”)
else:
print(’x:’, x)
• Header is not needed (but still useful) if the file will
not be read in dictionary mode:
header = [’name’,’dept’,’since’,’score’];
csv_writer.writerow(header)
3
Graphical elements can be added to subplot (i, j) by
using the notation: subplots[1, 0].hist(my_data)
that for instance adds a histogram plot to the subplot
in row 1 and column 0.
del x
finally:
print(’y:’, y)
Notes
If only one row of subplots is used, then the notation
subplots[i] should be used.
• plt.title(title) uses the string title as a
title for the plot.
The optional parameter
fontsize can be used to specify the size of
the text:
plt.title(’My title’, fontsize=20).
The parameter fontsize can be also be used in
plt.xlabel(), plt.ylabel().
• plt.xlabel(label), plt.ylabel(label) use the
string label as the label for the selected x, y axis.
• plt.xlim(a, b), plt.ylim(a, b) set the limits for
the values displayed on the x and y axis.
• plt.xticks(ticks_pos, ),
plt.yticks(ticks_pos, ) control the
appearance of the ticks on the x and y axis, where
ticks_pos is a sequence defining where the tick marks
should be placed, the optional my_labels sets explicit
labels to be placed at the given ticks_pos.
Matplotlib and Pyplot
Module matplotlib provides an extensive set of tools for the
graphical display of data. We have focused on the use of submodule pyplot, which is quite handy to use and is based on
the popular Matlab software. pyplot can be imported using
the following statement:
• plt.plot(y_seq) plots the data in the sequence y_seq; since x coordinates are unspecified, the point data are plotted in the same
way as in plt.plot(x_seq, y_seq),
where
x_seq = range(0,len(y_seq)):
data points are
plotted at equally spaced integer x coordinates. The
default behavior is to plot the data as a 2D solid line,
such that plot() should be seen as a line plot.
import matplotlib.pyplot as plt
In matplotlib, once a new figure is created, multiple graphical elements can be added and/or specified (to have a behavior di↵erent from the default). This means that a graphical
figure can include, for instance, multiple datasets displayed
according to di↵erent formats (e.g., a scatter plot, a histogram, a plot, a box plot, etc.).
• plt.plot(x_seq, y_seq) plots the given pairs
(xseq , yseq )i , i = 0, . . . , n, where n is the length of the
sequences. Again, the default behavior is to plot the
data as a 2D solid line.
In the following a list of useful methods from pyplot and
matplotlib are described.
• plot() can be customized by setting many positional
and keyword-passed parameters, a few examples are
given below, di↵erent combinations of the parameters
can be used to get di↵erent e↵ects:
• plt.figure() creates a new figure; it is not strictly
necessary (but highly recommended) to invoke it, since
a new figure will be created implicitly when invoking
any plotting method.
– plt.plot(x, y, marker=’.’, markersize=4)
– plt.plot(x, y, linestyle=’None’, marker=’v’,
• plt.figure(figsize(xsize, ysize)) allows to specify the dimensions of the figure along x and y.
color=’b’)
– plt.plot(x, y, linestyle=’–’, linewidth=2,
• plt.figure()
color=’r’)
fig, subplots = plt.subplots(nrows, ncols,
figsize=(xsize, ysize))
– plt.plot(x, y, linestyle=’-’, linewidth=1,
marker=’s’, markersize=8,
color=(0.1, 0.4, 0.3))
allows to place multiple plots (subplots) in the same figure; the subplots(nrows, ncols, figsize) method
defines a grid (a matrix) of nrows ⇥ ncols locations
where the di↵erent plots will be placed. Overall, the
figure will have the size defined by figsize.
– plt.plot(x, y, ’ro’, linestyle=’:’)
4
• plt.scatter(x_seq, y_seq) makes a scatter plot of
the pairs (xseq , yseq )i , i = 0, . . . , n: no lines are drawn
between points. A scatter plot needs two input sequences to create the point pairs.
Notes
• plt.scatter(x, y, marker=’.’, s=12, color=’r’)
makes a scatter plot using the selected marker, defining
its size with the keyword parameter s, and setting the
color. color and marker arguments follow the same
options of the plot() method.
• plt.hist(values, n_intervals) plots a histogram
for the data in values by considering their distribution in n_intervals bins/intervals of the same size.
The color of the histogram can be specified by using
the keyword argument color, a normalized histogram
is obtained by setting the option density=True.
• plt.bar(x_pos, heights) makes a bar plot where
x_pos are the x coordinates of the bars, and heights
are the heights of the bars. The optional argument
width can be used to control the width of the bars
(default is 0.8). Filled color can be set by the optional argument color. Tick labels on the x axis
can be set with the argument tick_label, for instance tick_label = [’1998’, ’2010’, ’2015’], or
tick_label= [100, 200, 1000].
• plt.pie(values) makes a pie chart of data values
where the fractional area of each wedge i is given by
values[i]/sum(values). The labels optional parameter allows to pass a list of strings for the labels of
each wedge. The optional parameter colors allows to
specify a sequence of colors for the wedges (matplotlib
will cycle the sequence if it is less than the number of
wedges).
Numpy module
• plt.legend(handles=list_of_label_references)
allows to place a legend for each element in the plot:
The numpy module is the main module providing mathematical and numerical tools. We haven’t really explored
the potentialities of the module apart from using the basic method arange(from, to, step) that generalizes the
built-in function range to float numbers. Below a few methods and examples from the library are listed:
plt.figure()
y, = plt.plot(x, y, label=’y’)
xx, = plt.plot(x, x**2, label=’$x^2$’)
xs = plt.scatter(x, x, label=’x’)
plt.legend(handles=[y, xx, xs])
plt.show()
• import numpy as np is the typical way to import the
module.
Note the commas after y and xx, as well as the use of
$ $ to enclose and expression using the LaTeX syntax
to generate a nice math-like formatting of the output.
• seq = np.arange(from, to, step)
where from, to, step are floats, for the rest it follows
the same rules as range().
• plt.show() completes the figure and shows it on the
screen. It is not strictly necessary, but it’s better to
include it.
• If x and y are created as numpy arrays, then arithmetic
operators can be applied to them (as long as the arrays
have the same length):
• plt.savefig(filename) saves the figure in the given
image file name (the extension sets the image type).
The optional integer argument dpi sets the resolution.
If the transparent options is set to True, the image
backgorund is transparent. Othe options are available.
x = np.arange(0, 1, 0.1)
y = np.arange(2, 3, 0.1)
z = x + y
zz = x * y
5
• numpy provides most of the mathematical functions
provided by math, with the same names, such
np.sqrt(x), np.sin(x), etc.
• islower(): Returns True if all characters in the string
are lower case
• isnumeric(): Returns True if all characters in the
string are numeric
• np.average(z), np.median(z)
• isprintable(): Returns True if all characters in the
string are printable
Notes
• isspace(): Returns True if all characters in the string
are whitespaces
• istitle(): Returns True if the string follows the rules
of a title
• isupper(): Returns True if all characters in the string
are upper case
• join(): Joins the elements of an iterable to the end of
the string
• ljust(): Returns a left justified version of the string
• lower(): Converts a string into lower case
• lstrip(): Returns a left trim version of the string
• partition(): Returns a tuple where the string is
parted into three parts
• replace(): Returns a string where a specified value is
replaced with a specified value
• rfind(): Searches the string for a specified value and
returns the last position of where it was found
Summary of string methods
• capitalize(): Converts the first character to upper
case
• rindex(): Searches the string for a specified value and
returns the last position of where it was found
• casefold(): Converts string into lower case
• rpartition(): Returns a tuple where the string is
parted into three parts
• center(): Returns a centered string
• rsplit(): Splits the string at the specified separator,
and returns a list
• count(): Returns the number of times a specified value
occurs in a string
• rstrip(): Returns a right trim version of the string
• encode(): Returns an encoded version of the string
• split(): Splits the string at the specified separator,
and returns a list
• endswith(): Returns true if the string ends with the
specified value
• splitlines(): Splits the string at line breaks and returns a list
• expandtabs(): Sets the tab size of the string
• find(): Searches the string for a specified value and
returns the position of where it was found
• startswith(): Returns true if the string starts with
the specified value
• index(): Searches the string for a specified value and
returns the position of where it was found
• swapcase(): Swaps cases, lower case becomes upper
case and vice versa
• isalnum(): Returns True if all characters in the string
are alphanumeric
• title(): Converts the first character of each word to
upper case
• isalpha(): Returns True if all characters in the string
are in the alphabet
• upper(): Converts a string into upper case
• zfill(): Fills the string with specified number of 0
values at the beginning
• isdecimal(): Returns True if all characters in the
string are decimals
• isdigit(): Returns True if all characters in the string
are digits
• isidentifier(): Returns True if the string is an identifier
6
2. 14 points Make a chocolate package
We want make a package of total kilos of chocolate. We have small bars that are small (1 kilo
each) and big bars that are big (5 kilos each).
Implement the function chocolate-package (small, big, total) that takes as inputs the num-
ber of small bars that are available, small, the number of big bars that are available, big, and
the total number of kilos of chocolate that must be in the package, total. All the input argu-
ments are integers. The function must return the integer number of small bars to use, under
the constraint that big bars must be used before small bars, if feasible. If isn’t possible to create
the package, the function must return -1.
For instance:
• chocolate-package(4, 1, 4) returns 4,
• chocolate-package (3, 1, 9) returns -1,
• chocolate-package (6, 1, 11) returns 6.
Expected number of lines in the solution code: 12
3
1. 11 points Understand the solution and complete the code
The function list_merge(x, y) takes as input two sorted lists, x and y, and merges them,
returning one single sorted list of length equal to len(x) + len(y). Sorting is performed in
ascending order
The lists x and y can have duplicate entries, can have entries in common, can have different
lengths. The elements of the two lists can be either all numeric or all strings.
In any case, they are passed as input already sorted (in ascending order), such we want to exploit
this fact for creating the sorted list to return without using neither the sorted() function nor
the sort() method (which are useful but are also computationally expensive for large lists).
For example:
• list_merge([56, 22, 22, 56, 12, 77], [9, 99, 13, 12, 22]) returns
[9, 12, 12, 13, 22, 22, 22, 56, 56, 77, 99]
• list_merge([‘v’, ‘d’, ‘e’, ‘e’], [‘i’, ‘i’, ‘O’]) returns
[‘d’, ‘e’, ‘e’, ‘i’, ‘i’, ‘o’, ‘V’]
The algorithmic solution implemented in the function works as follows. We use an index i to
go over the elements of x, and another index, j, for the elements of y. We start both the indices
from zero, then use a while loop, and iteratively compare element x[i] to y[j]. If x[i] < y[j],
we append x[i] to the output list (which is called merge) and we increment i, otherwise we
append y(j) and increment j
If either i or j reach the end of their list range, then we simply copy the remainder of the other
list to the merge list and that's it! More in general, we stop when merge has the desired size,
which corresponds to len(x) + len(y) (which means that all the elements from the two input
lists have been added).
Based on the given problem and algorithm descriptions, complete the code of the function
list_merge() (i.e., fill in the 8 blank / missing code parts!)
def list_merge(x, y):
merge -
i
i
total - len(x) + len(y)
while
! = total:
if x[i] < y[j]:
merge.append(x[i])
i
if i >= len (x):
else:
merge
j+- 1
if i >= len(y):
merge
return merge
2
3. 20 points Longest increasing subsequence
In many practical applications, it is important to spot the presence of a monothonically increas-
ing trend in a sequence of numbers (e.g., performance of an athlete, growth of a title, evolution
of the biochemical levels indicating a disease).
Implement the function longest increasing-subseq(x) that takes as input a sequence of num-
bers, x, and finds the longest subsequence x[i:]] of x, such that consecutive numbers are
monotonically increasing, i.e., x[k] = len (x):
else:
merge
j+- 1
if i >= len(y):
merge
return merge
2
rome
1. 25 points Process and display the data
Implement the function compute_statistics(temperature_dict) that takes as input a dictio-
nary temperature_dict with the same structure of the dictionary data_by_city returned by the
function read_temperatures (filename) from the Part 1 of the exam. The function computes
some basic statistics about the temperature data and show them in a graphical format.!
More precisely, the function compute_statistics() writes in a file summary.dat the following
data, in multiline format (note that the specific numbers refer to the example data above):
doha – min: 30.08, max: 36.09, median: 33.79, mean: 33.10
– min: 22.52, max: 29.89, median: 28.38, mean: 26.94
paris – min: 21.36, max: 28.60, median: 24.80, mean: 24.13
where min and max refer to, respectively, the minimum and the maximum value of the recorded
temperatures for the city, while median and mean are the median and the mean value of the
temperatures. Note that in order to write the file, you need to compute all these values, by city.
All values must be written with two decimal digits. Remember to close the file after writing.
The function returns a tuple of three floats, (all_min, all_max, all_mean), which correspond,
respectively, to the min, max, and mean values computed out of the combined data of the three
cities.
For instance, in the case of the example data above, the function returns the tuple:
(21.36, 36.09, 28.06).
In addition to writing to a file, the function also makes a histogram of all the temperature data.
The histogram uses 15 bins for value ranges. Bar values are in red color. Remember to add
meanigful axis labels and plot title.
Expected number of lines in the solution code: ~ 32