Recursion, Search

79 Views

Download Presentation
## Recursion, Search

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -

**Recursion – the Easy Solution**• Recursion is a technique for reducing a complex problem to repeated solution of easy problems. • The book has some examples. I will do some different ones.**Recursion and Induction**• Induction is a form of proof that relates a simple base case and an iterative process that proceeds from that base case. • Recursion and induction are closely related ideas. • Both are important tools for turning something apparently hard into something simple – that gets repeated.**Towers of Hanoi**• My favorite example of recursion. • Puzzle invented by the French mathematician Edouard Lucas in 1883 • Given three pegs, one with a set of disks(8 in the original puzzle) of graduated sizes, • move all the disks to a different peg • never put a larger disk on top of a smaller disk. • See http://www.mazeworks.com/hanoi/ or http://www.mathsisfun.com/games/towerofhanoi.html • Solve the puzzle with three disks, then with four disks. • How would you describe the algorithm for solving this puzzle?**Consider this solution**• If the pegs are numbered 1, 2, 3 and you want to move the n disks from peg 1 to peg 3 (destination peg), using peg 2 as an extra peg: • If n = 1, move it to the destination peg • Otherwise • Move the top n-1 disks to the extra peg • Move the bottom disk to the destination peg • Move the n-1 disks from the extra peg to the destination peg • Be careful about the naming. Sometimes the extra peg is the destination at a step. • Try this for n = 3, n = 4.**A really bad example**• Factorial (it is in the chapter, sadly) • Recursion involves overhead. Don’t force it on problems better solved other ways. • Factorial is inherently iterative: • n! = n*n-1*n-2*n-3..*1 def factorial(n): fact = 1 if n == 0: fact = n else: for i in range(1,n): fact = fact * i return fact result = factorial(5) print result ======= 24**Spot check**• Trace this code. Convert 43 Convert 21 Convert 10 Convert 5 Convert 2 Convert 1 print 1 (n<2) print 0 (2%2) print 1 (5%2) print 0 (10%2) print 1 (21%2) print 1 (43%2) print 0 (86%2) def convertBinary(n): if (n<2): print n, return else: convertBinary(n/2) print n%2, convertBinary(86) ====== 1 0 1 0 1 1 0 Adapted from an example at http://www.cs.cornell.edu/courses/cs211/2006fa/Sections/S2/recursion.txt**Further examples and explanations**• Really good presentation of recursion: • http://inventwithpython.com/blog/2011/08/11/recursion-explained-with-the-flood-fill-algorithm-and-zombies-and-cats/ • Examples of flood fill, more**Stacks**• A stack is a data structure with strict rules about access: • An item is always placed on the top of the stack • An item is always removed from the top of the stack. • No other access to the stack is permitted • May seem restrictive, but supports important activities**Recursion and Stacks**• Recursion works because there are stacks for implementation. • Reexamine the convertBinary example, for instance: def convertBinary(n): if (n<2): print n, return else: convertBinary(n/2) print n%2, convertBinary(86) On each call, we want to have the most recent results available. A stack is a first in – last out data structure -- FILO**Implementing a Stack**• A stack is just a collection of items with rules about access. It does not look any different from other collections of items. The thing that makes it a stack is the way it is used. • A list can be used as a stack, if we restrict the operations allowed to append and pop.**Push and Pop**• The two operations allowed on stacks are called push and pop. Push onto the top of the stack, pop off from the top of the stack. • In python push = append, pop = pop**Application of stacks**• Arithmetic without parentheses: • Reverse Polish notation • Named for Jan Łukasiewicz, who invented Polish notation • Widely used for compuations • Familiar form: infix notation – requires parentheses to determine order of operation: (3+4)*2 • Prefix notation – operator first: * + 3 4 2 • Postfix notation – operator last: 3 4 + 2 ***Evaluating Postfix**• 3 4 + 2 * • Push 3 on stack • Push 4 on stack • Encounter an operator, pop stack twice and apply the operator. • Push the value onto the stack • now have 7 on the stack • push 2 on stack • Encounter operator, *. pop stack twice and apply the operator • 7 * 2 = 14 • Push value on the stack. • Stack now contains just the value of the expression.**Binary Search**• Search = find a particular value in a sequence of values. • Much easier if the sequence is sorted. • Assume we have a sorted list. How to find the value (or determine that it is not there) • Consider the common puzzle – guess the number I am thinking of. The number is between 1 and 100. What is the maximum number of guesses that you need?**Try it**• What is my number? How will you proceed?**Efficient way**• Guess 50 • Then guess the midpoint of the interval that remains eligible • Then the midpoint of that • Then the midpoint of that • Say the number is 87 • Guess 50. Answer: no, higher • now the interval is 51 to 100 • Midpoint is 75. Guess 75. No, higher • Interval is 76 to 100. Guess 88. No, lower • Interval is 76 to 87. Guess 81. No higher • Interval is 82 to 87. Guess 84. No, higher • Interval is 85 to 87. Guess 86. No, higher • Interval is 87 to 87. Guess 87 If the result of the size / 2 is a not a whole number, round up or down.**Binary search**• At each iteration, cut the interval in half and search in the smaller interval. • Naturally recursive. • What is the base case: • Only one value in the interval. Either it matches or the value sought is not there. • Recursive part • Call the search with a smaller interval (half the size of the previous interval)**Spot check**• Given a list with values: • [“Ashley”, “Emma”, “Heather”, “Madeline”, “Max”, “Sydney”, “Will”] • Answer the question: Is there an entry for “Susan” • Using words, not numbers, but the principle is the same. Show the steps.**Spot check again**• Work together and work out the basic structure of the binary search. • Don’t worry about getting all the details right, just get the general ideas. • Examine the book version**Introduction: What is Covered in Chapter 12**• Lists and Tuples. • Dictionaries. • Containers of Containers. • Sets. • Arrays**Aspects of Containers**• order: ordered sequence (list, tuple, array). • mutability: list is mutable. tuple is immutable. • associativity: dict (dictionary) • heterogeneity: most Python containers allow different types. Some containers in other languages and one that will be introduced in this chapter only allow one type for the individual components. This is called homogeneous • Storage – Python uses referential containers meaning that rather than the elements in the actual container, there are references (addresses) to the actual items.**lists and tuples**• Use indexes that are sequential. • Can add or subtract values to make index values start at 0 as these containers require (example months 1 – 12 : subtract 1). • Limitations: • Lack of permanency: employee id’s – what happens when an employee leaves. • Using Social Security Numbers for employees. SSN's are not sequential. • Maybe the index values are not numeric.**Dictionaries**• Can use non-numeric index values. • director['Star Wars'] 'George Lucas' • director['The Godfather'] 'Francis Ford Coppola' • director['American Graffiti'] 'George Lucas' • Index values are called keys. • Keys must be immutable (int, str, tuple) • Dictionaries point to items such as 'George Lucas' and are called values. • No limits on values.**Python’s Dictionary Class**director = { } # can also use director = dict() director['Star Wars'] = 'George Lucas' director['The Godfather']='Francis Ford Coppola' director[‘American Graffiti'] = 'George Lucas' director['Princess Bride'] = 'Rob Reiner' #can also do the following director ={'Star Wars': 'George Lucas', 'The Godfather': 'Francis Ford Coppola‘, 'American Graffiti' : 'George Lucas' , 'Princess Bride' : 'Rob Reiner' }**Iterating Through Entries of a Dictionary**#display a dictionary in sorted order on keys titles = director.keys() titles.sort() for movie in titles: print movie, 'was direct by', director[movie] #can streamline this syntax for movie in sorted(director): print movie, 'was directed by', director[movie] #can iterate over both keys and values formovie,person in director.items(): print movie, 'was directed by', person**list, tuple and dict can have values of any type including**containers. Modeling a two dimensional table (a list of lists): game = [['X','X','O'], ['O','O','X'], ['X','O','X ']] bottomLeft = game[2][0] Containers of Containers**Modeling Many-to-Many Relationships**• Dictionary is a many-to-one relationship. Many keys may map to the same value. • Modeling many-to-many relationship. For example a single movie may have many actors. cast['The Princess Bride '] = ('Cary Elwes', 'Robin Wright Penn', 'Chris Sarandon', 'Mandy Patinkin', 'Andre the Giant',. . .)**Modeling Many-to-Many Relationships (continued)**>>> #Tuple used since immutable and cast for >>> #movies is also. >>> 'Andre the Giant' in cast False #must refer to specific key value in cast >>> 'Andre the Giant' in cast.values() False #must refer to results not keys >>> 'Andre the Giant' in cast['The Princess Bride'] True**Reverse Dictionary**• What if we want to know the keys that are associated with an item? • Can do this one at a time or build a complete reverse dictionary. original = {'A':1, 'B':3, 'C':3, 'D':4, 'E': 1, 'F': 3} reverse = {1: ['A', 'E'], 3: ['C', 'B', 'F'], 4: ['D'] }**Reverse Dictionary Code**#can build a reverse dictionary def buildReverse(dictionary): reverse = { } for key,value in dictionary.items(): if value in reverse: reverse[value].append(key) else: reverse[value] = [key] return reverse**Sets and Frozensets**• Originally programmers created a mathematical set class using a list or dictionary. • Python now contains a set class that is mutable and a frozenset class that is immutable. • Elements within the set are in arbitrary order. • Elements added to set must be immutable. • Elements of the set only occur once. • set constructor can be: • myset = set( ) • mysetb = set(container) #container can be any #immutable container**Set Operation Examples**>>> set ([3, 2]) < set([1,2,3]) True >>> set ([3, 2]) < set([2,3]) False >>> set ([7]) < set([1,2,3]) False >>> set ([3, 2]) <= set([2,3]) True**Frozensets**• A frozenset is immutable. • A frozenset can perform all accessor methods previously listed for a set but none of the mutator methods. • All elements of a set or frozenset must be immutable. Therefore a set can not consist of a set of sets but it could be a set of frozensets. • Dictionary keys recall can only be immutable therefore a frozenset can be a key of a dictionary.**Sets and Frozensets**• Two sets operated on results in a set. • Two frozensets operated on results in a frozenset. • A set and a frozenset results in the type that occurs first in the operation.**Illustrating Set and Frozenset Operations**>>> colors = set(['red', 'green', 'blue']) >>> stoplight = frozenset(['green', 'yellow', 'red']) >>> print colors & stoplight set(['green', 'red']) >>> print stoplight & colors frozenset(['green', 'red'])**Lists Versus Arrays**• A list consists of a list of references to items. • Advantage is that a list can consist of different types. This is called a heterogeneous type. • Disadvantage is slightly slower access since it requires two accesses to retrieve an item (once to get the reference and once to retrieve the value from the reference).**Lists Versus Arrays (continued)**• The array type consists of the actual items. • Homogenous data structure. • Slightly faster access than a list since only one access is required to retrieve a value.**Illustrating Differences In How Information is Stored in**Arrays and Lists**Using Arrays**• array('i') - stores integers. • array('f') – stores floats. • Other codes are possible. • Array is not part of built-in types in Python so must import it using: from array import array. • Can also initialize array at same time as creating. >>> from array import array >>> yearArray = array('i', [1776, 1789, 1917, 1979])