Exercise 1.1. Write a function startStop
which retrieves the elements of a list from within bounds. Use patterns in your implementation. Define an object Main
as shown below.
Any code within the object can be directly executed. (Hint: use a simply-recursive function)/
object Main extends App { def startStop[A] (l: List[A] ,start: Int, stop: Int): List[A] = ??? println(startStop(List(1,2,3,4,5,6),1,4)) // = List(2,3,4) }
Exercise 1.2. Write a function which determines the number of occurrences of each character in a string. (Hint: use a tail-recursive function)
def countChars (s:String): Map[Char,Int] = { def aux(l: List[Char], acc: Map[Char,Int]): Map[Char,Int] = ??? ??? }
Exercise 1.3 Write a function which takes a list of records first name, last name, CNP (encoded as tuples), and returns a list of the last names and ages of all females which are younger than the average of the entire list. E.g. List( (“Mary”, “2030694123456”), (“Anne”,“2121092123456”), (“Matei”, “5121202123456”), (“Maggie”, “2121078123456”) )
yields List( (“Mary”,28), (“Anne”,30) )
. Maggie was born in '78, whereas Mary, Anne and Matei were born in '94, '92 and 2002, respectively. (Hint: use combinations of map with filter)
val example = List(("Mary", "2030694123456"), ("Anne", "2121092123456"), ("Matei", "5121202123456"), ("Maggie", "2121078123456")) def youngerThanAverage(l: List[(String,String)]): List[(String,Int)] = { def getAge(s:String):Int = ??? // female gender = True def getGender(s:String):Boolean = ??? ??? }
Exercise 1.4
A labelled graph is encoded as a String text where each line is an edge <from> <label> <to>
Example:
0 r 1 0 r 2 0 g 1 1 g 2 1 b 3 1 r 4 4 g 1 3 b 2 2 r 2 2 g 3
rrg
, the destination node are 1
(0 red to 1 red to 4 green to 1) and 3
(0 red to 2, red to 2, red to 3)val example = """0 r 1 |0 r 2 |0 g 1 |1 g 2 |1 b 3 |1 r 4 |4 g 1 |3 b 2 |2 r 2 |2 g 3""".stripMargin type Streets = Map[(Int,Char),Set[Int]] def readStreets(s: String): Streets = ??? def findDestination(start: Int, colors: String, streets: Streets): Set[Int] = ???
Python3 is a multi-paradigm language, that combines the imperative style with the functional style. It also supports Object-Oriented programming, albeit in a limited way.
Python3 offers a few programming constructs that:
This lab will introduce some of these constructs.
Exercise 2.1. Write a function f(l)
which determines the maximum of a list l
of integers.
Exercise 2.2. Modify the previous function to f(l,start,stop)
and determine the maximum between positions start
and stop
.
Exercise 2.3. Find the longest sequence of positive integers from a list. E.g. for the list [1,3,-1,2,0,1,5,4,-2,4,5,-3,0,1,2]
the answer is [2,0,1,5,4]
.
Exercise 2.4. Write a pythonic function to check if a list is palindrome.
The most widely used datatypes in Python are lists and dictionaries. Additionally, at LFA, we will also use: sets, stacks.
In Python, lists are also used as stacks:
l = [] l.append(x) # add x at the TOP of the stack (this will be the last element of the list) l[-1] # this is the top of the stack x = l.pop() # removes and returns an element from the top of the stack.
Exercise 2.5. Write a function which determines (and returns) the longest sequence of consecutive integers from a list.
Python dictionaries are actually hash maps (or hash tables). The keys k
are dispersed using a hash-function into buckets. Each bucket will hold its respective values. Some examples of dictionary usage:
#create an empty dictionary: d = {} #add or modify a key-value: d[k]=v #search if a key k is defined in a dictionary d: if k in d: # do something
Exercise 1.6. Write a function which determines the number of occurrences of each character in a string.
Sets are collections where each element is unique. Sets can be traversed and indexed exactly as lists. They are initialised using the constructor set
:
# the empty set: s = set() # set constructed from a list: s = set([1,2,3]) # adding a new element to the set: s.add(4)
Exercise 1.7. Determine the list of characters which occur in a string. E.g. for “limbajeformale” we have: “limbajefor”. (Hint 1: in Python there is no difference between a character and a singleton string and strings are just lists; Hint 2: to create a list from another object, use list()
).
Pairs are very similar to lists and can be substituted by the latter in many cases:
p = (x, y) # a pair where the first element is x and the second is y t = (x, y, z) # a tuple fst = p[0] snd = p[1] for k in t: # do something with element k of the tuple
The most used higher-order functions in Python are map and reduce:
from functools import reduce # adds 1 to each element of a list def allplus1(l): return map(lambda x:x+1,l) # computes the sum of elements of a list def sum_l (l): # inner functions are very useful for defining local, reusable functionality def plus(x,y): return x + y return reduce(plus,l) # reduce is a little different from Haskell folds: it does not use an initial value def short_sum(l): return reduce(lambda x,y:x+y,l) # observe the syntax for lambdas
List comprehensions are widely used programming tools in Python. Usage examples:
# adding 1 to each element of a list l1 = [x+1 for x in [1,2,3]] # [2,3,4] # packing elements into pairs l2 = [(x,x+1) for x in [1,2,3]] # [(1,2), (2,3), (3,4)] # unpacking pairs in the for notation l3 = [x+y for (x,y) in [(1,2), (2,3), (3,4)]] # [3,5,7] # combined list comprehensions l4 = [(x,y) for x in [1,2,3] for y in [4,5,6]] # [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)] # filters l5 = [x for x in [1,2,3,4] if x>2] # [3,4]
Exercise 1.8. Write a function which takes a list of records first name, last name, CNP (encoded as tuples), and returns a list of the last names and ages of all females which are younger than the average of the entire list. E.g. [ (“Mary”, “Smith”, “2030602123456”), (“Anne”, “Doe”, “2121092123456”), (“Matei”, “Dan”, “1121202123456”), (“Maggie”, “Byrne”, “2121078123456”)]
yields [(“Smith”,19), (“Doe”,29)]
. Maggie was born in '78, whereas Mary, Anne and Matei were born in '94, '92 and 2002, respectively.
A labelled graph is encoded as a file where:
<from> <label> <to>
Example:
5 0 r 1 0 r 2 0 g 1 1 g 2 1 b 3 1 r 4 4 g 1 3 b 2 2 r 2 2 g 3
rrg
, the destination node are 1
(0 red to 1 red to 4 green to 1) and 3
(0 red to 2, red to 2, red to 3)split
in Python)Newer versions of python support type annotations and pre-runtime type checking (supported by some code editors). The typing module allows programmers to provide hints regarding the types of different objects, the signature (parameters and return value types) of functions and methods, and create generic classes.
To create such hints the syntax is as follows:
<var_name>: <type> [= expr]
:x: int y: int = 5 z: str = 'hello world' t: MyCustomType
def <func_name>([<param>: <type>, …]) → <return_type>
:def hello() -> str: ... def get_item_at(index: int) -> Any: ... class MyCustomType(): def method(self, param1: Any, param2: int) -> str ...
from typing import TypeVar, Generic StateType = TypeVar("StateType") # !!! important: type variables must be declared and initialised before they are used class DFA(Generic[StateType]): def next_state(self, from_state: StateType, token: str) -> StateType: ... ... dfa: DFA[int] = DFA[int](...) A = TypeVar("A") B = TypeVar("B") class TupleLinkedList(Generic[A,B]): value: tuple[A,B] next: 'TupleLinkedList[A,B]' | None # !!! important: in most python versions, if you need to use the # type of the class within its own definition, you # need to quote its name (this delays the evaluation # of the hint until after the class is fully defined) ... class IntList(list[int]): ...
Useful type hints:
int, str, bool, float etc.
: the basic datatypes (charaters are hinted as strings, as python does not make the distinction)list[type], set[type], frozenset[type], dict[key_type, val_type]
: basic data collections (items introduced in set
s and frozenset
s and the keys of dictionaries need to be hashable: see the appendix for python hashing)Any
: a type is compatible with any other type (if no type hint is specified, this is what type checkers usually default to)Callable[ [<param_types>…], <return_type>]
: this defines a function with a given signature<type1> | <type2>
: the |
operator allows us to indicate that a given object can be one of two(or more) typesNone
: represents the lack of a value (or an explicit None value); useful to mark functions which have no return value, or that a value may be purposefully missing (in combination with the |
operator), and a None check may be necessaryfull documentation of the python typing module: https://docs.python.org/3/library/typing.html