#!/usr/bin/env python # coding: utf-8 #

cs1001.py , Tel Aviv University, Spring 2019

# # # Recitation 2 # We tested if a positive integer (or a range of integers) satisfies the Collatz conjecture (using "while" and "for" loops). # We discussed the basics of lists, the efficiency of list operations and how to efficiently concatenate a list to another. We also demonstrated list comprehension. # Finally, we discussed functions, short circuit evaluation and analyzed the efficiency of the functions we saw. # # #### Takeaways: # #
    #
  1. Lists can be a highly modular and useful data structure. Make sure that you understand their functionality and also their limits (figuratively and literally).
  2. #
  3. Avoid using the + operator for extending a given list. Use += or list.extend() instead. #
  4. Functions can be used in one another (max2 in max3_v3) and can be composed together.
  5. #
  6. When analyzing a function's performance, think about the input that will cause the largest amount of work and then measure how many operations the function does.
  7. #
  8. Using short circuit evaluation, if e.g. you have a long "and" condition, place the part that is most easy to compute first since if it is false, all other parts of the condition will not be computed.
  9. #
# # Code for printing several outputs in one cell (not part of the recitation): # In[13]: from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity = "all" # ## Collatz Conjecture # # The Collatz Conjecture, from Wikipedia: # # Start with any positive integer $n$. Each term in the Collatz sequence is obtained from the previous term as follows: # * If the previous term is even, the next term is one half the previous term: $n \to n // 2$ # * If the previous term is odd, the next term is 3 times the previous term plus 1: $n \to 3\cdot n + 1$ # # The conjecture is that no matter what value of $n$ we start with, the sequence will always reach 1. # ### Check conjecture for a single number: # In[1]: orig_num = int(input("Enter a positive integer to apply Collatz algorithm: ")) num = orig_num while num > 1: print(num, end=" ") if num % 2 == 0: num = num // 2 else: num = 3*num + 1 print(num) print(orig_num, "is OK!") # ### Check conjecture for a range of numbers: # In[2]: limit = int(input("Check Collatz algorithm for 1 ... ")) orig_num = 1 while orig_num <= limit: num = orig_num while num > 1: print(num, end=" ") if num % 2 == 0: num = num // 2 else: num = 3*num + 1 print(num) print(orig_num, "is OK!") orig_num += 1 # ### range examples # In[63]: for i in range(10): print(i) # In[64]: for i in range(1, 7, 2): print(i) # In[71]: for i in range(7, 1, -2): print(i) # ### Check conjecture for a range of numbers (using "for") # In[72]: limit = int(input("Check Collatz algorithm for 1 ... ")) for orig_num in range(1, limit + 1): num = orig_num while num > 1: print(num, end=" ") if num % 2 == 0: num = num // 2 else: num = 3*num + 1 print(num) print(orig_num, "is OK!") # ## Lists - Basics # # A Python list is a collection of **ordered** elements. The elements can be of different types, they can include repetitions and they can even include lists. # # Python allows us to check how many elements a list contains using the $len(lst)$ function, and access an element at index $i$ using the command $lst[i]$ # # In[9]: x = 10 lst = [x, 1, 2, 3, "name", print, True, [3.14, 2.5]] len(lst) lst[4] lst[5] lst[5]("hello") #lst[100] lst[-1] lst[-1][0] lst[1] = 1000 lst lst[8] = 40 # In[10]: empty_lst = [] len(empty_lst) empty_lst[0] # In[11]: lst = [x, 1, 2, 3, "name", print, True, [3.14, 2.5]] lst[3: 8: 2] # In[15]: lst1 = [1, 2, 3] lst2 = [10, 20, 30] lst_new = lst1 + lst2 lst_new lst1 lst2 print("Bad coding:") lst1 = lst1 + lst2 lst1 print("Good coding:") lst1 = [1, 2, 3] lst2 = [10, 20, 30] lst1.extend(lst2) lst1 lst1.append(10) lst1 lst1.append(lst2) lst1 lst1 = [1,2,3] lst2 = [10,20,30] lst1 += lst2 #invokes extend!! # ### Common List functions # # We've seen the $len(\cdot)$ function, and in a sense, the indexing call $lst[i]$ is also a function. What other builtin functions does Python supply for lists? # In[85]: lst = [10, -40.5, 6] sum(lst) # In[86]: lst = [10, -40.5, 6] slst = sorted(lst) slst lst lst.sort() lst # ### Iterating over lists # Using while loop # In[16]: lst = [1, 2, 3, 4, "hi", "bye", 100] i = 0 while i < len(lst): print(lst[i]) i += 1 # Using for loop with range # In[17]: lst = [1, 2, 3, 4, "hi", "bye", 100] for i in range(len(lst)): print(lst[i]) # Using for loop over elements # In[18]: lst = [1, 2, 3, 4, "hi", "bye", 100] for item in lst: print(item) # ## Exercise: given grades, how many are there above average? # #### solution 1: using loops # In[87]: count = int(input("How many grades? ")) above = 0 grades = [] for i in range(count): grade = float(input("enter a grade: ")) #grades[i] = grade #wrong #grades.append(grade) #grades.extend([grade]) grades += [grade] #invokes extend #grades = grades + [grade] #bad coding! s = sum(grades) avg = s/count for grade in grades: if grade > avg: above += 1 print(above, "grades are above the average", avg) # #### list comprehension example: # In[22]: lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lst1 = [x for x in lst if x % 3 == 0] lst1 lst2 = [x**2 for x in lst if x % 3 == 0] lst2 lst3 = ["!" for x in lst if 2*x > 10] lst3 lst4 = [1 for x in lst] lst4 # A list comprehension command has the following structure: # # lst = [x for y in object if cond] # # And is equivalent to the following piece of code: # # In[19]: lst = [] for y in object: if cond: lst.append(x) # #### Solution 2: using list comprehension # In[90]: count = int(input("How many grades? ")) above = 0 grades = [] #try to replace this loop by list comprehension exp for i in range(count): grade = float(input("enter a grade: ")) #grades[i] = grade #wrong #grades.append(grade) #grades.extend([grade]) grades += [grade] #invokes extend #grades = grades + [grade] #bad coding! s = sum(grades) avg = s/count above = len([grade for grade in grades if grade > avg]) print(above, "grades are above the average", avg) # ## Functions: max2, max3 # In[52]: def max2(a,b): ''' max2(float,float) ---> float return the maximum od a and b ''' if a>=b: return a #else: # return b return b x = max2(10,30) x y = max2(10) # ### max3 # #### at most 4 comparisons # In[23]: def max3_v1(a,b,c): if a >= b and a >= c: return a elif b >= a and b >= c: return b else: return c # #### at most 2 comparisons # In[ ]: def max3_v2(a,b,c): if a>=b: if a>=c: return a else: return c else: if b>=c: return b else: return c # #### at most 2 comparisons # In[3]: def max3_v3(a,b,c): ## max_ab = max2(a,b) ## total_max = max2(max_ab,c) ## return total_max return max2(max2(a,b), c) # #### Collatz over range, with functions # In[4]: def collatz(orig_num): num = orig_num while num > 1: print(num, end=" ") if num%2 == 0: num = num//2 else: num = 3*num+1 print(num) print(orig_num, "is OK!") def collatz_range(limit): for num in range(1, limit + 1): collatz(num) collatz_range(6) # ## Short circuit evaluation # In[27]: x = True or 3/0 x x = 3/0 or True x # In[26]: x = False and 3/0 x x = True and 3/0 x # In[ ]: