Recur Documentation Release 1.0

Recur Documentation Release 1.0

recur Documentation Release 1.0 panopticonopolis Oct 16, 2019 Contents: 1 Getting Started 3 1.1 Introduction: Another Guide To Recursion? And Why Is It So Long?.................3 1.2 Scope, Frame and Stack.........................................4 1.3 Recursion in Light of Frames...................................... 10 1.4 Counting In Recursion.......................................... 14 1.5 Recursion and Swapped Arguments................................... 18 1.6 Palindromes and Recursion-as-Evaluation................................ 21 1.7 Summing a List of Lists......................................... 26 1.8 Using Recursion to Make More: The Power Set............................. 35 1.9 Expanding a Series: Pascal’s Triangle.................................. 41 1.10 Multiple Recursive Calls: Fibonacci Sequence, Part 1......................... 49 1.11 Memoization: Fibonacci Sequence, Part 2................................ 55 1.12 Recursive Approaches To Searching And Sorting............................ 62 1.13 Recursion and Self-Similarity: Koch Curves.............................. 71 1.14 The Sierpinski Triangle......................................... 81 1.15 Lindenmayer Systems.......................................... 92 1.16 Solving L-System Recursion....................................... 96 1.17 Boss Level: The Tower of Hanoi..................................... 104 2 Indices and tables 117 i ii recur Documentation, Release 1.0 A shamelessly verbose guide to the wonders of recursion Contents: 1 recur Documentation, Release 1.0 2 Contents: CHAPTER 1 Getting Started For a lot of people, learning recursion for the first time pretty much sucks. It doesn’t have to be that way. This guide is intended to help beginning (and perhaps even intermediate) programmers learn to think recursively. It’s not math-heavy, so there are no proofs, and very little discussion of time/space complexity. But I do take a text-heavy approach, because I think patient explanation is a key ingredient in helping people understand this crucial technique. Although the code is presented in Python, recursion is a fairly universal concept, so the material should be accessible to non-Python developers. Sometimes I’ll present the code immediately and then unpack it. Other times, we’ll work towards the final recursive solution, starting only from first principles. At the end of each section I deduce a few heuristics, and include an exercise or two that will apply the material and push comprehension a bit further. I hope the end result is a critical framework developers can use to identify, analyze and solve problems that demand (or simply favor) recursive solutions. 1.1 Introduction: Another Guide To Recursion? And Why Is It So Long? Oftentimes algorithms are presented to beginning programmers as recipes or to-do lists. You may have a to-do list that starts with ‘pick up the kids from school’, then realize that, you first must put gas in the car. But first of all, you need to find your car keys. You can’t do the last step unless you’ve done all the other ones. If you’re baking a cake, the final step may be to frost the cake, but not before you have taken the cake out of the oven, which of course requires you to make the cake in the first place, in addition to preparing the frosting, etc. Of course, there is nothing particularly recursive about this. Breaking a problem down into more manageable sub- problems is true of algorithmic design in general. What makes recursion unique in algorithmic thinking is the fact that it’s about designing a solution in such a way that, simply by running the same function over and over with slightly modified inputs, you can have your cake and eat it too. The following guide to recursion is undoubtedly long. But that is because most material currently available online is simply too short. Recursion is an extremely compact method. While this allows for a presentation that is usually considered ‘elegant’, the practical consequence is that much of the program execution takes place implicitly. 3 recur Documentation, Release 1.0 For example, it’s not terribly difficult to understand the principle of recursive action, whether generally or for a specific piece of code. But, as with any algorithm, the ability to write out the actual process of computation on a line-by-line basis is where the rubber meets the road. As a result, much of the length of this document is due to the fact that I have annotated what actually happens when a function undergoes recursive computation, using print statements to trace inputs, transformations and outputs. It’s also long because the usual ways of presenting problems and their recursive solutions is inadequate. Usually, the code is simply given ex cathedra, or perhaps accompanied with a brief commentary on its salient aspects. With recursion, there is an abiding mystery of just how we got to that solution. Although it’s not true for every algorithm I’ve chosen to present here, in this guide I prefer to describe how to think about the problem, and then how to convert that critical thinking into code. If you understand recursion on an intuitive level, this guide is most likely not for you. It will be boring and obvious. But for many others, it’s my hope that the explanations of how recursive calls and returns work will be time well spent. The following text uses Python 3.6 but the concepts should be broadly applicable to many languages. A solid work- ing knowledge of Python is preferred, including the basic data types and their associated methods. (Virtually) no familiarity with object-oriented techniques is needed. 1.2 Scope, Frame and Stack The most common way of introducing recursion to programmers involves two seemingly simple steps. Given a programming language that allows a function to call itself, we construct a recursive function once we do two things: 1) Identify the base case 2) Identify the recursive case We formulate these two cases by successfully reducing the problem at hand to ‘its simplest possible solution’, whatever that means. This, as the saying goes, is necessary but not sufficient, and there’s much that still needs to be unpacked. The purpose of this guide is to provide the reader with a toolbox of heuristics that can be used to quickly analyze a recursive algorithm. Once the reader is comfortable with analysis, the same set of heuristics can be applied to thinking about a problem recursively, and constructing a solution. 1.2.1 Understanding how functions work Recursion is commonly introduced to students within the context of iterative procedures, especially for loops, ‘but with functions’. This is the first source of misunderstanding. Recursion is better considered as a consequence of func- tional scope, frames and the call stack. Put differently, we understand recursion when we understand how functions prioritize, quarantine, and share values bound to variables and the evaluation of expressions (scope), and the way those spaces are created and then discarded (frames added to and subtracted from the stack). This may make little sense in the abstract, so let’s look at some code. Just about the simplest program we can write is: hello="Hello, World!" print(hello) >>> Hello, World! In this program, there is only one frame in the stack, known as the global frame. We could add a few more variables and statements and what not, and everything would still belong to this global frame. All variables and their associated values would be just as available to any further statement we chose to write (although variables used for iterating over loops don’t have this sort of permanence). 4 Chapter 1. Getting Started recur Documentation, Release 1.0 This changes when we introduce functions. Every time we call (as opposed to merely define) a function, a new frame is created, and is added to the stack. At the same time, the flow of control passes to that frame. The usual analogy is a stack of cafeteria trays: the global frame is the first tray. When we call a function from the global frame, the new frame is placed on top of it. When that function completes its computation, it returns its results, and the frame is discarded. In terms of our analogy, we can put what we want on the tray, then remove it from the top of the stack. The tray beneath it is now available for plating food, or whatever it is we want to do with it. This kind of ordering is commonly known as LIFO, or Last In First Out. Of course, if the function calls another function and is waiting for results, then its frame remains open or ‘on the stack’. But as mentioned, while there may be numerous frames open at any given point during a program’s runtime, the Python interpreter is always executing the current computation within the context of a specific frame. This will be extremely important to keep in mind as we begin to understand recursion. Part of what makes frames valuable is that they regulate the accessibility of a function’s variables, otherwise known as scope. For example, consider this trivial function: def foo(x): return x x= 12 print(foo(x)) >>> 12 Easy enough. But consider that we also get 12 if we write: def foo(y): return y x= 12 print(foo(x)) Or even if we write: def foo(y): return x x= 12 print(foo(x)) This is scope at work. When we first specify x = 12 we do in at the global frame of the program. When we pass x to foo(), the function’s parameter doesn’t care if the argument in print(foo(_)) is x or q or whatever, but only that it is of the correct type. Otherwise the function can’t perform its computation. But once the argument is passed to the function, we must refer to it within the function as it was named in the function definition, ie, foo(y).

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    121 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us