0% found this document useful (0 votes)
50 views39 pages

Unit 6

The document discusses tuples, lists, and dictionaries in Python. Tuples are immutable while lists are mutable, allowing side effects from changes. Dictionaries provide a mapping of unique keys to values, allowing direct access via keys rather than integer indexes. Dictionaries allow storing related data together more cleanly than separate lists.

Uploaded by

Sudarshan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views39 pages

Unit 6

The document discusses tuples, lists, and dictionaries in Python. Tuples are immutable while lists are mutable, allowing side effects from changes. Dictionaries provide a mapping of unique keys to values, allowing direct access via keys rather than integer indexes. Dictionaries allow storing related data together more cleanly than separate lists.

Uploaded by

Sudarshan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

UNIT

6
▪ tuples (immutable)
▪ lists (mutable)
▪ mutability side effects
▪ aliasing
▪ cloning

2
6
▪ recursion – divide and conquer algorithm
▪ Dictionaries – another mutable object type
▪ Reference side effect like LIST

3
RECURSION
PROCESS REPEATING
SELF SIMILAR

4
§ reduce a problem to simpler versions of the same
problem

§ a way to design solution to problems by divide-and-


conquer or decrease-and-conquer
§ must have 1 or more base cases (stop condition) that are
easy to solve

§ a programming technique where a function calls itself


§ must solve the same problem on some other input with the goal of
simplifying the larger problem input
5
▪ looping constructs
▪ while
▪ For

▪ Do computation with a set of state variables ( counter,


sum, avg,… ) that update on each iteration.

6
▪ a * b” is equivalent to “add a to itself b times
a + a + a + a + … + a
▪ capture state by
◦ Iteration number (i)
◦ starts at b
◦ stop when 0
◦ Step i = i - 1
◦ result = result + a

def mult_iter(a,b):
result = 0
while b > 0:
result += a
b -= 1
return result
7
MULTIPLICATION –
RECURSIVE SOLUTION
▪ recursive step a*b = a + a + a + a + … + a
▪ reduce problem to a
simpler version of same = a + a + a + a + … + a
problem.
▪ keep reducing problem
= a + a * (b-1)
until reach a simple
case(stop case) def mult(a, b):
if b == 1:
• stop/base case
• solved directly return a
• when b = 1,the solution of else:
a*b is a return a + mult(a, b-1)

8
n! = n*(n-1)*(n-2)*(n-3)* … * 1

Base case / stop condition

• !1=1
• !0=1

Recursive step
n! = n * (n-1)!

9
def fact (x) :
if x<=1 :
return 1
else :
return x*fact(x-1)

print(fact(4))

10
▪each recursive call to a function creates its own scope.

▪It uses the same variable names but in separate


scopes.

▪bindings of variables in a scope are not changed by


recursive call.

▪flow of control passes back to previous scope once


function call returns value

11
def factorial_iter(n): def factorial(n):
prod = 1 if n == 1:
for i in range(1,n+1): return 1
prod *= i else:
return prod
return n*factorial(n-1)

▪ Which more intuitive ?


▪ Which more simpler for the programmer to
develop?
▪ Which is more efficient ?
▪ Which is more simple to debug?
12
§ I0 = 1

§ I1 = 1

§ IK= IK-1 + IK-2

§ That will generates

§ 1,1,2,3,5,8,13,21,…..

13
§ Two base cases
§ K=0 return 1
def fib(x):
§ K=1 rerun 1
"""x should be positive no """
if x == 0 or x == 1:
§ Recursive step return 1
§ Return fibo(k-1)+ fibo(k-2)
else:
return fib(x-1) + fib(x-2)

print(fib(4))

14
§ A palindrome string is a sequence of characters which reads
the same backward as forward.
§ Example

§ "Was it a car or a cat I saw”


§ "No 'x' in Nixon”

15
§ First remove spaces , commas , or any characters that is not in
the alphabet.

§ Make all the string in lower case format

§ Now the string ready for palindrome check !

def toChars(s):
s=s.lower()
ans = ''
for c in s:
if c in 'abcdefghijklmnopqrstuvwxyz':
ans = ans + c
return ans

print(toChars("Was it a car or a cat I saw")) 16


wasitacaroracatisaw

def pal(s):
for i in range(0,len(s),1):
if s[i]!=s[len(s)-1-i]:
return 0
return 1

print(pal(toChars("Was it a car or a cat I saw")))

17
wasitacaroracatisaw

base caes:
• String is empty
• String length is 1

Recursive step
• Check string[0] and string[-1]
• Slice string[1:-1]
• Call pal function with the new slice

18
wasitacaroracatisaw

def pal(s):
if len(s) <= 1:
return True
else:
return s[0] == s[-1] and pal(s[1:-1])
W
ha
ti
st
he
print(pal(toChars("Was it a car or a cat I saw"))) ou
tp
ut

19
▪an example of a“divide and conquer”algorithm.

▪solve a hard problem by breaking it into a set of sub-


problems such that:

◦sub-problems are easier to solve than the original


◦solutions of the sub-problems can be combined to solve
the original

6.0001 LECTURE6
20
21
▪so far, can store using separate lists for every info
names = [‘John’, ‘Mike', ‘Adam’, ‘Cathrine']
grade = ['B', 'A+', 'A', 'A']
course = [ECE117, ECE119, ECE116, ECE113]

▪ a separate list for each item


▪ each list must have the same length
▪info stored across lists at same index, each index
refers to info for a different person

22
def get_grade(student, name_list, grade_list, course_list):
i = name_list.index(student)
grade = grade_list[i]
course = course_list[i]
return (course, grade)

▪ must maintain many lists and pass them as arguments


▪ must always index using integers

23
student=[[1,'khal',’ECE210'],[2,'ed','ECE13'],[3,'ED','ECE130']]
print (student[0])
student=((1,'khal’,’ECE10'),(2,'ed','ECE101'),(3,'ED','ECE102'))
print (student[0])

▪ Tuples immutable
▪ must always index using integers

24
▪ nice to index item of interest directly (not always int)
▪ nice to use one data structure,no separate lists
Alist Adictionary

0 Elem 1 Key 1 Val 1

1 Elem 2 Key 2 Val 2

2 Elem 3 Key 3 Val 3

3 Elem 4 Key 4 Val 4

… … … …
25
▪ store pairs of data A
• key
• value

my_dict = {}
grades = {‘KHA':'B', 'ED':'A+', ‘FAT':'A', 'KYLE':'A'}

key1 val1 key2 val2 key3 val3 key4 val4

26
'DANA' 'B'
▪ similar to indexing into a list
'DEN' 'A'
▪ looks up the key
'ED' 'A+'
▪ returns the value associated
'KYLE' 'A'
with the key
▪ if key isn’t found, get an error

grades = {'DANA':'B', 'ED':'A+', 'DEN':'A', 'KYLE':'A'}

grades['ED'] evaluates to 'A+'


grades[‘SYLVIA'] gives a KeyError

27
'DANA' 'B'

'DEN' 'A'

'ED' 'A+'

'KYLE' 'A'

'SYLVIA' 'A'

grades = {'DANA':'B', 'ED':'A+', 'DEN':'A', 'KYLE':'A'}

▪ add an entry
grades['SYLVIA'] = 'A'

▪ test if key in dictionary


'ED' in grades à returns True
‘DAN' in grades à returns False
▪ delete entry
del(grades['DANA'])

28
'DANA' 'B'

'DEN' 'A'

'ED' 'A+'

'KYLE' 'A'

grades = {'DANA':'B', 'ED':'A+', 'DEN':'A', 'KYLE':'A'}

▪ get an iterable that acts like a tuple of all keys


grades.keys() returns (['DEN','KYLE','ED','DANA'])

▪ get an iterable that acts like a tuple of all values


grades.values() returns (['A', 'A', 'A+', 'B'])

29
▪ values
• any type (immutable and mutable)
• can be duplicates
• Dictionary values can be lists, even other dictionaries
▪ keys
• must be unique
• immutable type (int, float, string, tuple,bool)
• actually need an object that is hashable, but think of
as immutable as all immutable types are hashable
• careful with float type as a key
• no order to keys or values!
d = {4:{1:0}, (1,3):"twelve", 'const':[3.14,2.7,8.44]}
30
▪ordered sequence of ▪ matches “keys” to
elements “values”
▪look up elements by an ▪ look up one item by
integer index another item
▪ indices have an order ▪ no order is guaranteed
▪ index is an integer ▪ key can be any
immutable type

31
1. create a frequency dictionarymapping str:int

2. find word that occurs the most and how many times
A. use a list, in case there is more than one word
B. return a tuple (list,int) for (words_list,highest_freq)

3. find the words that occur at least X times


• let user choose “at least X times”, so allow as parameter
• return a list of tuples, each tuple is a (list, int)
containing the list of words ordered by their frequency
• IDEA: From song dictionary, find most frequent word. Delete
most common word. Repeat.
32
def lyrics_to_frequencies(lyrics):
myDict = {}
for word in lyrics:
if word in myDict:
myDict[word] += 1
else:
myDict[word] = 1
return myDict

lyrics=["love","love","love","happy","happy","happy","happy","smile","see
","see","see","see","smile","oh"]

freqs=lyrics_to_frequencies(lyrics)
print(freqs)

{'love': 3, 'happy': 4, 'smile': 2, 'see': 4, 'oh': 1}


33
def most_common_words(freqs):
values = freqs.values()
best = max(values)
words = []
for k in freqs:
if freqs[k] == best:
words.append(k)
return (words, best)

lyrics=["love","love","love","happy","happy","happy","happy","smile","see
","see","see","see","smile","oh"]

freqs=lyrics_to_frequencies(lyrics)
print(most_common_words(freqs))

(['happy', 'see'], 4)
34
MINTIMES def words_often(freqs, minTimes):
result = []
done = False
while not done:
temp = most_common_words(freqs)
if temp[1] >= minTimes:
result.append(temp)
for w in temp[0]:
del(freqs[w])
else:
done = True
return result

lyrics=["love","love","love","happy","happy","happy","happy","smile","see
","see","see","see","smile","oh"]

freqs=lyrics_to_frequencies(lyrics)
print(words_often(freqs, 2))

(['happy', 'see'], 4), (['love'], 3), (['smile'], 2)]


35
def fib(n):
if n == 1:
return 1
elif n == 2:
return 2
else:
return fib(n-1) + fib(n-2)
▪ two base cases
▪ calls itself twice
▪ this code is ineffcient?why

36
fib(n) = fib(n-1) + fib(n-2)
fib(5)

fib(4) fib(3)

fib(3) fib(2) fib(2) fib(1)

fib(2) fib(1)

▪ recalculates the same values many times


▪ could keep track of already calculated values

37
def fib_efficient(n, d):
if n in d:
return d[n]
else:
ans = fib_efficient(n-1, d) + fib_efficient(n-2, d)
d[n] = ans
return ans

d = {1:1, 2:2}
print(fib_efficient(6, d))

▪ do a lookup first in case already calculated the value


▪ modify dictionary as progress through function calls

38
def fib(n):
fib.count+=1
if n <=1:
return 1
else:
return fib(n-1) + fib(n-2)

def fib_efficient(n, d):


fib_efficient.count+=1
if n in d:
return d[n]
else:
ans = fib_efficient(n-1, d) + fib_efficient(n-2, d)
d[n] = ans
return ans • While the efficient one makes just
fib_efficient.count=0
57 call
fib.count=0 • Calling in efficient fib (30) makes
print(fib_efficient(30,{1:1, 2:2})) 1346269 more than two millions recursive
print(fib(30)) call
1346269
print(fib_efficient.count) 57
print(fib.count) 2692537
39

You might also like