Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
lfa:lab01-python-intro [2021/09/08 09:42]
pdmatei
lfa:lab01-python-intro [2021/10/07 11:32] (current)
ioana.georgescu [List comprehensions]
Line 12: Line 12:
 ==== List traversal ==== ==== List traversal ====
  
-1.1. Write a function ''​f(l)''​ which determines the maximum of a list ''​l''​ of integers.+**Exercise ​1.1.** Write a function ''​f(l)''​ which determines the maximum of a list ''​l''​ of integers.
  
 <hidden The pythonic way> ​ <hidden The pythonic way> ​
Line 23: Line 23:
 </​hidden>​ </​hidden>​
  
-1.2. Modify the previous function to ''​f(l,​start,​stop)''​ and determine the maximum between positions ''​start''​ and ''​stop''​.+**Exercise ​1.2.** Modify the previous function to ''​f(l,​start,​stop)''​ and determine the maximum between positions ''​start''​ and ''​stop''​.
  
 <hidden The pythonic way> ​ <hidden The pythonic way> ​
 When we care about the indices of a list, we can use the function ''​range(x,​y)''​ which returns **a list of integers** starting from ''​x''​ until ''​y-1''​. When we care about the indices of a list, we can use the function ''​range(x,​y)''​ which returns **a list of integers** starting from ''​x''​ until ''​y-1''​.
 <code python> <code python>
-for elem in collection:​ +for in range(0,​len(collection))
-    # do something+    # do something ​with collection[i]
 </​code>​ </​code>​
-This idiom can be used for any collection not just lists, as you will discover during the lab. 
 </​hidden>​ </​hidden>​
  
-Loops (for … in …) +==== Slicing ​lists ====
-Accessing (elements of an array, as well as slicing) +
-Inner functions +
-List comprehensions,​ filters +
-Stacks +
-Dictionaries +
-Pairs +
-Classes and inheritance,​ instance-of +
-toString +
-Higher-order functions and lambdas +
-Unpacking (for tuples, ​lists)+
  
 +**Exercise 1.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]''​.
  
-<hidden The Pythonic ​way> ​This text will be hidden ​<code python> ​solution ​</​code>​ </​hidden>​+<hidden The pythonic ​way> ​ 
 +Python supports various list slicing operations, as well as "​overloaded"​ indexing: 
 +<code python> 
 +# the sublist from positions 0 to x of l: 
 +l[0:x] 
 +# the very same list: 
 +l[:x] 
 +# the last element of a list: 
 +l[-1] 
 +# the last three elements of a list: 
 +l[-3:] 
 +# the slice from n-3 to n-1, where n is the number of elements from the list 
 +l[-3:-1] 
 +</​code>​ 
 +</​hidden>​
  
 +**Exercise 1.4.** Write a pythonic function to check if a list is palindrome.
  
-Python is an interpreted,​ dynamically typed language which is easy to use for scripting and prototyping applications.+===== Other datatypes =====
  
-C and Java programmers quickly adjust to the Python syntax. Unlike C, in Python, lists are predefined ​and usually more used than arrays:+The most widely used datatypes ​in Python are lists and dictionaries. Additionally,​ at LFA, we will also use**sets**, **stacks**.
  
 +==== Stacks ====
 +
 +In Python, **lists** are also used as stacks:
 <code python> <code python>
-# Comments begin with a '#'​ and end at the end of the line +l = [] 
-l = []  # comment +l.append(x  # add x at the TOP of the stack (this will be the last element of the list
-l.append("​1"​) +l[-1        # this is the top of the stack 
-l.append(0+x = l.pop(  # removes and returns an element from the top of the stack. 
-l.append([])+</​code>  ​
  
-print(l) +**Exercise 1.5.** Write a function which determines ​(and returnsthe **longest** sequence of consecutive integers from a list. 
-</​code>​ + 
-**Remarks** +==== Dictionaries ==== 
-  * Although ​Python ​is strongly-typed ​(the interpreter keeps track and verifies the type of objects), lists may have different ​'types' ​of elements. + 
-  ​There exist two different major versions of Python: Python2 and Python3Although similar, there are some incompatible differences between them. We will use Python3, so take care when researching documentation.+Python ​dictionaries are actually **hash maps** ​(or **hash tables**). The keys ''​k''​ are **dispersed** using a hash-function into bucketsEach bucket ​will hold its respective valuesSome examples of dictionary usage:
  
 <code python> <code python>
-for i in range(0,​len(l))+#create an empty dictionary
-    ​print(l[i])+d = {}
  
-print(range(0,​len(l)))+#add or modify a key-value:​ 
 +d[k]=v
  
-for elem in l+#search if a key k is defined ​in a dictionary d
-    ​print(elem)+if k in d: 
 +  # do something
 </​code>​ </​code>​
-**Remarks** 
-  * List traversal may be achieved using indexing. Indexes are integers taken from a range. ''​range(0,​len(l))''​ is a list in itself. 
-  * Lists (and other data structures) can be iterated using ''​in''​ 
- 
-**Syntax** 
-  * unlike C or Java where we often use ''​{...}''​ for scoping, in Python we use indentation levels (either a tab or 4 spaces) ​ 
-  * control instructions such as ''​for'',​ ''​while'',​ ''​if''​ do not require ''​(...)''​ for conditions but they must end with '':''​ 
  
 +**Exercise 1.6.** Write a function which determines the number of occurrences of each character in a string. ​
 +<hidden The pythonic way> ​
 <code python> <code python>
-def func(l1, l2): +def count(l): 
-    ​l1.append(3) +   d = {} 
-    ​return l1 + l2 +   for x in l: 
-     +      if x in d: 
-x = [1] +         d[x] += 1 
-y = [2+      ​else:​ 
-print(func(x,​y)) +         d[x= 1 
-print(x)+   return d
 </​code>​ </​code>​
 +</​hidden>​
  
-**Remarks** +==== Sets ====
-  * although it is possible to add type annotations,​ in Python a function'​s signature only consists of the number of parameters and their names +
-  * objects are generally passed as reference (hence, when printing ''​x'',​ we see the list ''​[1,​3]''​) (for details see: [[https://​docs.python.org/​3/​reference/​datamodel.html | Python data model]]) +
-  * ''​+''​ denotes list concatenation+
  
-**Exercise 1** +Sets are collections where each element is unique. Sets can be traversed and indexed exactly as lists. ​They are initialised using the constructor ''​set'':​ 
-Write a function which prints EACH repeating character from a string. (Hint: strings ​are lists of characters).+<code python>​ 
 +# the empty set: 
 +s = set()
  
-==== Useful data structuresdictionaries and sets ====+# set constructed from a list: 
 +set([1,​2,​3])
  
-Dictionaries are another useful data structure. A dictionary is ''<​key> ​<​value>''​ mappingUnlike lists, keys may be of any type (integers, strings, or any other datatype).+# adding ​new element to the set: 
 +s.add(4) 
 +</​code>​
  
 +**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 ====
 +
 +Pairs are very similar to lists and can be substituted by the latter in many cases:
 <code python> <code python>
-{} +(x, y)     # a pair where the first element is x and the second is y 
-d["​X"​] ​["​X"​]+(x, y, z)  # a tuple
  
-if "​X"​ in d: +fst = p[0] 
-    ​print("​d[Xis defined in the dictionary"​) +snd = p[1
-     + 
-if not "​Y" ​in d+for k in t
-    ​print("​d[Y] is not defined in the dictionary"​)+  # do something with element k of the tuple 
 +  ​
 </​code>​ </​code>​
  
-**Exercise 2** Write a function returns the number of repetitions of each character from a text. (Hint: use dictionaries to store the number of repetitions.)+===== The functional style =====
  
-**Exercise 3** Write a function returns the number of unique characters from a list.+==== Higher-order functions and lambdas ====
  
-Remark: +The most used higher-order functions in Python are **map** and **reduce**: 
-  ​a simpler way to ensure uniqueness is to use sets. +<code python>​ 
-  ​a set may be created from a list:  ''​s = set([1,​2,​3,​1])''​ +from functools import reduce
-  ​* and in turn, a list may be created from a set''​l = list(s)''​+
  
-**Exercise 4** Write function which takes a pattern and a text and prints all indexes where an occurrence of pattern in text are found.+# adds 1 to each element of list 
 +def allplus1(l):​ 
 +   ​return map(lambda x:x+1,l)
  
-Remark+# computes the sum of elements of a list 
-  * lists can be sliced in Python using the following syntax''​l[start_index:end_index]''​ Test it to see how slicing is performed.+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 
 +</​code>​
  
-**Exercise 5** Modify the previous implementation to use slicing.+==== List comprehensions ====
  
-Remark: +List comprehensions are widely used programming tools in Python. Usage examples:
-  * in Python ​we can use arbitrarily nested functions+
  
-**Exercise 6** Write a function which searches for a list of patterns in a text. 
 <code python> <code python>
-def find_patterns ​(pattern_listtext): +# adding 1 to each element of a list 
-    checks if pattern is found at position index in text +l1 = [x+1 for x in [1,2,3]] 
-    def inner_search ​(pattern,index):+# [2,3,4] 
 + 
 +# packing elements into pairs  
 +l2 = [(x,x+1for x in [1,2,3]] 
 +[(1,2), (2,3), (3,4)] 
 + 
 +# unpacking pairs in the for notation 
 +l3 = [x+y for (x,yin [(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]
 </​code>​ </​code>​
  
-Remark: +**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.  
-  ​Python supports functional-style programming to some extent.+ 
 +<hidden The pythonic way> ​
 <code python> <code python>
-def plus1(x): +from functools import reduce 
-    return ​1+ 
 +def getYouth(l): 
 + # this function computes the age of a given CNP 
 +    ​def age(cnp): 
 +        # conversion to integer of the two-character year code 
 +        if int(cnp[5:​8]) <= 21: 
 +            ​return ​2021 - int("​20"​+cnp[5:7]) 
 +        else: 
 +            return 2021 - int("​19"​+cnp[5:​7])
     ​     ​
-print(map(plus1,[1,2,3])) +    # computing the average ages (map could have also been used) 
-print(map(lambda x:x+1[1,2,3]))+    avg = reduce(lambda a,b:a+b, [age(x[-1]) for x in l]) / len(l
 +     
 +    # we return the last name and the age of the filtered list l 
 +    return [(ln,age(cnp)) for (fn,ln,cnp) in l if cnp[0]=='​2'​ and age(cnp<= avg]
 </​code>​ </​code>​
 +</​hidden>​
  
  
-**Exercise 8** Modify the previous implementation and instead of ''​for'',​ use ''​map''​ (cast the return of ''​map''​ to ''​list'':​ ''​list(map(...))''​) 
  
-However, it is more common in Python to employ //list comprehensions//​ instead of ''​map'':​ 
  
-<code python> 
-def plus1(x): 
-    return x + 1 
-    ​ 
-print([plus1(x) for x in [1,2,3]]) 
-print([(x + 1) for x in [1,2,3]])) 
-</​code>​ 
  
-List comprehensions also support the functionality of ''​filter'':​ 
  
-<code python> 
-print([(x+1) for x in [1,​2,​3,​4,​5,​6] if (x % 2 == 0)]) 
-</​code>​ 
  
-**Exercise 9** Modify the previous implementation and instead of ''​for'',​ use list comprehensions.+ 
 + 
 + 
 +/*
  
 ==== Classes and inheritance ==== ==== Classes and inheritance ====
Line 239: Line 279:
   * Extend the class example shown previously to include class ''​Node''​ which models non-empty trees. Implement methods ''​size''​ and ''​contains''​.   * Extend the class example shown previously to include class ''​Node''​ which models non-empty trees. Implement methods ''​size''​ and ''​contains''​.
  
 +
 +*/
 +
 +===== Practice =====
 +
 +A labelled graph is encoded as a file where:
 +  * **the first line** consists of the number of nodes
 +  * **each subsequent line** is an edge ''<​from>​ <​label>​ <​to>''​
 +Example:
 +<​code>​
 +5
 +0 X 1
 +1 O 2 
 +1 X 3
 +1 O 4
 +4 X 1
 +3 O 2
 +</​code>​
 +
 +  * Suppose we encode streets as labelled graphs, where each label '​X'​ or '​O'​ denotes if a street is closed or open. 
 +  * Compute the set of accessible nodes from a given **source**, via open streets.
 +  * (Hint1: google //Python read lines// to see how to read from a file; also, google ''​split''​ in Python)
 +  * (Hint2: you will need a dictionary to store, for each node and label l, the list of its l-successors)
 +
 +
 +===== Haskell practice =====
 +
 +Solve the same exercise, only build your own input as a string, instead of a file.