From 84e08d06f49e57d8bed6b4630bb2e56067d421c4 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Wed, 25 Sep 2019 14:27:03 +0200 Subject: [PATCH 1/5] Move FizzBuzz exercise from chapter 01 to 03 --- 01_elements_review_and_exercises.ipynb | 72 ------------------ 03_conditionals_review_and_exercises.ipynb | 88 +++++++++++++++------- 2 files changed, 61 insertions(+), 99 deletions(-) diff --git a/01_elements_review_and_exercises.ipynb b/01_elements_review_and_exercises.ipynb index 2207ccc..7e43b77 100644 --- a/01_elements_review_and_exercises.ipynb +++ b/01_elements_review_and_exercises.ipynb @@ -275,78 +275,6 @@ "for number in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:\n", " print(...)" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Fizz Buzz" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The kids game [Fizz Buzz](https://en.wikipedia.org/wiki/Fizz_buzz) is said to be often used in job interviews for entry level positions. However, opinions vary as to how good of a test it actually is ([source](https://news.ycombinator.com/item?id=16446774)).\n", - "\n", - "In its simplest form, a group of people start counting upwards in an alternating fashion. Whenever a number is divisible by $3$, the person must say \"Fizz\" instead of the number. The same holds for numbers divisible by $5$ when the person must say \"Buzz\". If a number is divisible by both numbers, one must say \"FizzBuzz\". Probably, this game would also make a good drinking game with the \"right\" beverages.\n", - "\n", - "With just Chapter 1, we actually do not yet know all of Python's language constructs we need to write an implementation of Fizz Buzz in a Pythonic way. Yet, we will tweak what we know a bit and make it work." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Q11.1**: First, create a list `numbers` with the numbers from 1 through 100. You could type all numbers manually but there is of course a smarter way. The built-in [range()](https://docs.python.org/3/library/functions.html#func-range) may be useful here. Read how it works in the documentation. To make the output of [range()](https://docs.python.org/3/library/functions.html#func-range) a `list` object, you have to \"wrap\" it with the [list()](https://docs.python.org/3/library/functions.html#func-list) built-in (i.e., `list(range(...))`)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "numbers = ..." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Q11.2**: Loop over the `numbers` list and replace numbers for which one of the two (or both) conditions apply with text strings `\"Fizz\"`, `\"Buzz\"`, or `\"FizzBuzz\"` using the indexing operator `[...]` and the assignment statement `=`. In the chapter we saw that Python starts indexing with `0` as the first element. So in each iteration of the `for`-loop you have to determine the *index* as well as checking the actual `number`.\n", - "\n", - "Also note that for numbers divisible by both $3$ and $5$ we need some sort of a \"third\" condition check: As we only know about the `if` statement so far (and have not heard about `elif` and `else` from Chapter 3), there will be three `if` statements in total within the loop. And the order of them matters!\n", - "\n", - "Hint: Is there a single condition that checks for both $3$ and $5$?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for number in numbers:\n", - " ..." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Q11.3**: Create a loop that prints out either the number or any of the Fizz Buzz substitutes. Do it in such a way that we do not end up with 100 lines of output here." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for number in numbers:\n", - " ..." - ] } ], "metadata": { diff --git a/03_conditionals_review_and_exercises.ipynb b/03_conditionals_review_and_exercises.ipynb index f60bc2b..f152b30 100644 --- a/03_conditionals_review_and_exercises.ipynb +++ b/03_conditionals_review_and_exercises.ipynb @@ -211,11 +211,6 @@ "\n", "\n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", "\n" ] }, @@ -235,28 +230,36 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "markdown", @@ -270,14 +273,18 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "discounted_price(...)" + ] }, { "cell_type": "markdown", @@ -304,14 +311,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Fizz Buzz revisited" + "### Fizz Buzz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "When you worked on the Fizz Buzz exercise in Chapter 1, you actually did not know about the `elif` and `else` keywords yet. Well, now you do." + "The kids game [Fizz Buzz](https://en.wikipedia.org/wiki/Fizz_buzz) is said to be often used in job interviews for entry level positions. However, opinions vary as to how good of a test it actually is ([source](https://news.ycombinator.com/item?id=16446774)).\n", + "\n", + "In its simplest form, a group of people start counting upwards in an alternating fashion. Whenever a number is divisible by $3$, the person must say \"Fizz\" instead of the number. The same holds for numbers divisible by $5$ when the person must say \"Buzz\". If a number is divisible by both numbers, one must say \"FizzBuzz\". Probably, this game would also make a good drinking game with the \"right\" beverages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9.1**: First, create a list `numbers` with the numbers from 1 through 100. You could type all numbers manually but there is of course a smarter way. The built-in [range()](https://docs.python.org/3/library/functions.html#func-range) may be useful here. Read how it works in the documentation. To make the output of [range()](https://docs.python.org/3/library/functions.html#func-range) a `list` object, you have to wrap it with the [list()](https://docs.python.org/3/library/functions.html#func-list) built-in (i.e., `list(range(...))`)." ] }, { @@ -320,16 +336,20 @@ "metadata": {}, "outputs": [], "source": [ - "numbers = list(range(1, 101))" + "numbers = ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**Q9**: Copy and paste your answer to **Q11.2** in Chapter 1 here and instead of three consecutive `if` statements re-write it with *one* compound `if` statement.\n", + "**Q9.2**: Loop over the `numbers` list and replace numbers for which one of the two (or both) conditions apply with text strings `\"Fizz\"`, `\"Buzz\"`, or `\"FizzBuzz\"` using the indexing operator `[]` and the assignment statement `=`.\n", "\n", - "This code will then be a lot more robust as the order of the three `if` statements cannot be screwed up." + "In Chapter 1 we saw that Python starts indexing with `0` as the first element. Keep that in mind.\n", + "\n", + "So in each iteration of the `for`-loop you have to determine an `index` variable as well as checking the actual `number` for its divisors.\n", + "\n", + "Hint: the order of the conditions is important!" ] }, { @@ -338,17 +358,31 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n" + "for number in numbers:\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9.3**: Create a loop that prints out either the number or any of the Fizz Buzz substitutes. Do it in such a way that we do not end up with 100 lines of output here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for number in numbers:\n", + " print(...)" ] } ], From 250aa092093402f89f5ef564b56134d18cfb7a7f Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 1 Oct 2019 17:47:45 +0200 Subject: [PATCH 2/5] Streamline previous content --- 00_start_up_review_and_exercises.ipynb | 2 +- 01_elements.ipynb | 143 +++++++++++++-------- 01_elements_review_and_exercises.ipynb | 2 +- 02_functions.ipynb | 96 ++++++++++---- 02_functions_review_and_exercises.ipynb | 2 +- 03_conditionals.ipynb | 38 +++--- 03_conditionals_review_and_exercises.ipynb | 2 +- 7 files changed, 181 insertions(+), 104 deletions(-) diff --git a/00_start_up_review_and_exercises.ipynb b/00_start_up_review_and_exercises.ipynb index e1a435f..2f4c334 100644 --- a/00_start_up_review_and_exercises.ipynb +++ b/00_start_up_review_and_exercises.ipynb @@ -18,7 +18,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Read Chapter 0 of the book. Then work through the ten review questions." + "Read [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb) of the book. Then work through the ten review questions." ] }, { diff --git a/01_elements.ipynb b/01_elements.ipynb index e1d8b09..382d757 100644 --- a/01_elements.ipynb +++ b/01_elements.ipynb @@ -24,7 +24,7 @@ "\n", "It is intuitively best to take the very mindset of a small child when learing a foreign language and we do so for learning the Python language as well. This first chapter introduces simplistic examples and we better just accept them as they are without knowing any of the \"grammar\" rules yet. Then, we analyze them in parts and slowly build up our understanding.\n", "\n", - "Consequently, if parts of this chapter do not make sense right away, let's not worry too much. Besides introducing some basics (that we need to understand), it also serves as an outlook for what is to come. So, many terms and concepts referenced here will be covered in great detail in following chapters." + "Consequently, if parts of this chapter do not make sense right away, let's not worry too much. Besides introducing some basics that we need to understand, it also serves as an outlook for what is to come. So, many terms and concepts used here will be covered in great detail in following chapters." ] }, { @@ -46,7 +46,7 @@ } }, "source": [ - "As our introductory example, we want to calculate the average of all even numbers from one through ten.\n", + "As our introductory example, we want to calculate the *average* of all *even* numbers from *one* through *ten*.\n", "\n", "While we could come up with an [analytical solution](https://math.stackexchange.com/questions/935405/what-s-the-difference-between-analytical-and-numerical-approaches-to-problems/935446#935446) (i.e., derive some equation with \"pen and paper\" from, e.g., one of [Faulhaber's formulas](https://en.wikipedia.org/wiki/Faulhaber%27s_formula)), we instead solve the task programmatically.\n", "\n", @@ -75,7 +75,7 @@ } }, "source": [ - "To verify that something happened in our computer's memory, we simply **reference** `numbers` and observe that Python indeed knows about." + "To verify that something happened in our computer's memory, we simply **reference** `numbers` and observe that Python indeed knows about it." ] }, { @@ -110,17 +110,17 @@ } }, "source": [ - "So far, so good. Let's see how the desired result could be expressed as a **sequence of instructions** in Python.\n", + "So far, so good. Let's see how the desired **computation** could be expressed as a **sequence of instructions** in Python.\n", "\n", "Intuitively, the line `for number in numbers` describes a \"loop\" over all the numbers in the `numbers` list, one at a time.\n", "\n", "The `if number % 2 == 0` may look disturbing at first sight. Both the `%` and `==` must have an unintuitive meaning here. Luckily, the **comment** in the same line after the `#` symbol has the answer: The program only does something if the current `number` is even.\n", "\n", - "In particular, it increases `count` by $1$ and adds the current `number` onto the [running](https://en.wikipedia.org/wiki/Running_total) `total`. Both `count` and `number` were initially set to $0$ and the single `=` reads as \"... is *set* equal to ...\". It could not indicate a mathematical equation as, for example, `count` is generally not equal to `count + 1`.\n", + "In particular, it increases `count` by $1$ and adds the current `number` onto the [running](https://en.wikipedia.org/wiki/Running_total) `total`. Both `count` and `number` were initially set to $0$ and the single `=` symbol reads as \"... is *set* equal to ...\". It could not indicate a mathematical equation as, for example, `count` is generally not equal to `count + 1`.\n", "\n", "Lastly, the `average` is calculated as the ratio of the final **values** of `total` and `count`. Overall, we divide the sum of all even numbers by the count of all even numbers, which is exactly what we are looking for.\n", "\n", - "We also observe how the lines of code \"within\" the `for` and `if` **statements** are *indented* and *aligned* with multiples of **four spaces**: This shows immediately how the lines relate to each other." + "We also observe how the lines of code \"within\" the `for` and `if` **statements** are **indented** and *aligned* with multiples of **four spaces**: This shows immediately how the lines relate to each other." ] }, { @@ -200,7 +200,7 @@ "source": [ "Note how only two of the previous four code cells generate an **output** while two remained \"silent\" (i.e., there is no \"**Out[...]**\" after running the cell).\n", "\n", - "By default, Jupyter notebooks show the value of a cell's last so-called **expression**. This output can be suppressed by ending the last line with a semicolon `;`." + "By default, Jupyter notebooks show the value of a cell's last **expression**. This output can be suppressed by ending the last line with a semicolon `;`." ] }, { @@ -249,7 +249,7 @@ } }, "source": [ - "To visualize something before the end of the cell, we can use the [print()](https://docs.python.org/3/library/functions.html#print) built-in **function**." + "To visualize something before the end of the cell, we use the [print()](https://docs.python.org/3/library/functions.html#print) built-in **function**." ] }, { @@ -327,11 +327,13 @@ } }, "source": [ - "Python comes with basic mathematical operators built in. **[Operators](https://docs.python.org/3/reference/lexical_analysis.html#operators)** are built-in **tokens** that have a special meaning to the Python interpreter. Most operators either \"operate\" with the object immediately following them (= **unary** operators; e.g., negation) or somehow \"process\" the two objects \"around\" them (= **binary** operators; e.g., addition). But we will see some exceptions from that as well.\n", + "Python comes with many **[operators](https://docs.python.org/3/reference/lexical_analysis.html#operators)** built in: They are **tokens** (i.e., \"symbols\") that have a special meaning to the Python interpreter.\n", "\n", - "By definition, operators have **no** permanent **side effects** in the computer's memory. Although the code cells in this section do indeed lead to *new* objects being created in memory, they are immediately \"forgotten\" as they are not stored in a **variable** (like `numbers` above). We will revisit this idea further below when we compare **expressions** with **statements**.\n", + "The arithmetic operators either \"operate\" with the number immediately following them (= **unary** operators; e.g., negation) or \"process\" the two numbers \"around\" them (= **binary** operators; e.g., addition). But we will see many exceptions from that as well.\n", "\n", - "Let's see some examples of operators. We start with the binary `+` and the `-` operators for addition and subtraction. Binary operators resemble what mathematicians call [infix notation](https://en.wikipedia.org/wiki/Infix_notation) and have the expected meaning." + "By definition, operators have **no** permanent **side effects** in the computer's memory. Although the code cells in this section do indeed create *new* numbers in memory (e.g., `77 + 13` creates `90`), they are immediately \"forgotten\" as they are not stored in a **variable** like `numbers` or `average` above. We will continue this thought further below when we compare **expressions** with **statements**.\n", + "\n", + "Let's see some examples of operators. We start with the binary `+` and the `-` operators for addition and subtraction. Binary operators are designed to resemble what mathematicians call [infix notation](https://en.wikipedia.org/wiki/Infix_notation) and have the expected meaning." ] }, { @@ -425,7 +427,7 @@ } }, "source": [ - "When we compare the output of the `*` and `/` operators for multiplication and division, we note the subtle difference between the $42$ and the $42.0$. This is a first illustration of the concept of a **data type**." + "When we compare the output of the `*` and `/` operators for multiplication and division, we note the subtle *difference* between the $42$ and the $42.0$. This is a first illustration of the concept of a **data type**." ] }, { @@ -543,7 +545,7 @@ } }, "source": [ - "To obtain the remainder of a division, we can use the **modulo operator** `%`." + "To obtain the remainder of a division, we use the **modulo operator** `%`." ] }, { @@ -613,7 +615,7 @@ } }, "source": [ - "Modulo division can be useful if we, for example, need to get the last couple of digits of a large integer." + "Modulo division is also useful if we, for example, need to get the last couple of digits of a large integer." ] }, { @@ -672,7 +674,7 @@ } }, "source": [ - "The [divmod()](https://docs.python.org/3/library/functions.html#divmod) built-in function combines the integer and modulo divisions into one operation. However, this is not an operator any more (but a function). Also observe that [divmod()](https://docs.python.org/3/library/functions.html#divmod) returns a \"pair\" of integers." + "The [divmod()](https://docs.python.org/3/library/functions.html#divmod) built-in function combines the integer and modulo divisions into one operation. However, this is not an operator but a function. Also observe that [divmod()](https://docs.python.org/3/library/functions.html#divmod) returns a \"pair\" of integers." ] }, { @@ -707,7 +709,7 @@ } }, "source": [ - "Raising a number to a power is performed with the **exponentiation operator** `**`. Note that this is different from the `^` operator many other programming languages might use and that also exists in Python with a *different* meaning." + "Raising a number to a power is performed with the **exponentiation operator** `**`. This is different from the `^` operator many other programming languages use and that also exists in Python with a *different* meaning." ] }, { @@ -742,7 +744,7 @@ } }, "source": [ - "The normal [order of precedence](https://docs.python.org/3/reference/expressions.html#operator-precedence) from mathematics applies (i.e., \"PEMDAS\" rule) but parentheses help avoid confusion." + "The normal [order of precedence](https://docs.python.org/3/reference/expressions.html#operator-precedence) from mathematics applies (i.e., \"PEMDAS\" rule)." ] }, { @@ -777,7 +779,7 @@ } }, "source": [ - "The parentheses here serve as a **delimiter**." + "Parentheses help avoid confusion and take the role of a **delimiter** here." ] }, { @@ -871,7 +873,7 @@ } }, "source": [ - "There are plenty more mathematical and non-mathematical operators that are introduced throughout this book together with the concepts they implement or support. Some of these are already shown in the next section." + "There are many more non-mathematical operators that are introduced throughout this book together with the concepts they implement. Some of these are already shown in the next section." ] }, { @@ -949,7 +951,7 @@ { "data": { "text/plain": [ - "139940106427216" + "140658972730512" ] }, "execution_count": 27, @@ -973,7 +975,7 @@ { "data": { "text/plain": [ - "139940106602344" + "140658972907392" ] }, "execution_count": 28, @@ -997,7 +999,7 @@ { "data": { "text/plain": [ - "139940105769456" + "140658972586992" ] }, "execution_count": 29, @@ -1017,7 +1019,7 @@ } }, "source": [ - "These addresses are really not that meaningful for anything other than checking if two variables actually **point** at the same object. This may be helpful as different objects can of course have the same value." + "These addresses are really not that meaningful for anything other than checking if two variables actually **point** at the same object. This may be helpful as, for example, different objects in memory may of course have the same value." ] }, { @@ -1041,7 +1043,7 @@ } }, "source": [ - "`a` and `d` indeed have the same value as can be checked with the **equality operator** `==`. The resulting `True` (and the `False` below) is yet another data type, a so-called **boolean**. We will look into that closely in Chapter 3." + "`a` and `d` indeed have the same value as can be checked with the **equality operator** `==`. The resulting `True` (and the `False` below) is yet another data type, a so-called **boolean**. We will look into that closely in [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb)." ] }, { @@ -1780,7 +1782,7 @@ " " ], "text/plain": [ - "" + "" ] }, "execution_count": 50, @@ -1801,7 +1803,7 @@ } }, "source": [ - "For example, while the above code to calculate the average of the even numbers from 1 through 10 is correct, a Pythonista would re-write it in a more \"Pythonic\" way and use the [sum()](https://docs.python.org/3/library/functions.html#sum) and [len()](https://docs.python.org/3/library/functions.html#len) (= \"length\") built-in functions (cf., Chapter 2) as well as a so-called **list comprehension** (cf., Chapter 7). Pythonic code runs faster in many cases and is less error prone." + "For example, while the above code to calculate the average of the even numbers from 1 through 10 is correct, a Pythonista would re-write it in a more \"Pythonic\" way and use the [sum()](https://docs.python.org/3/library/functions.html#sum) and [len()](https://docs.python.org/3/library/functions.html#len) (= \"length\") built-in functions (cf., [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb)) as well as a so-called **list comprehension** (cf., Chapter 7). Pythonic code runs faster in many cases and is less error prone." ] }, { @@ -2003,7 +2005,7 @@ "\n", "At the same time, for a beginner's course it is often easier to just code in a linear fashion.\n", "\n", - "In real data science projects one would probably employ a mixed approach and put re-usable code into so-called Python modules (i.e., *.py* files; cf., Chapter 2) and then use Jupyter notebooks to built up a linear report or story line for a business argument to be made." + "In real data science projects one would probably employ a mixed approach and put re-usable code into so-called Python modules (i.e., *.py* files; cf., [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb)) and then use Jupyter notebooks to built up a linear report or story line for a business argument to be made." ] }, { @@ -2868,7 +2870,7 @@ "\n", "In general, the assignment statement creates (or overwrites) a variable and makes it point to whatever object is on the right-hand side *only if* the left-hand side is a *pure* name (i.e., it contains no operators like the indexing operator in the example). Otherwise, it mutates some already existing object. And we always have to expect that the latter might have more than one variable pointing at it.\n", "\n", - "In the beginning, visualizing the memory with a tool like [PythonTutor](http://pythontutor.com/visualize.html#code=x%20%3D%20%5B1,%202,%203%5D%0Ay%20%3D%20x%0Ax%5B0%5D%20%3D%2099%0Adel%20x,%20y%0Ax%20%3D%20%5B1,%202,%203%5D%0Ay%20%3D%20x.copy%28%29%0Ax%5B0%5D%20%3D%2099&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) will assist in understanding what is going on." + "Visualizing what is going on in the memory with a tool like [PythonTutor](http://pythontutor.com/visualize.html#code=x%20%3D%20%5B1,%202,%203%5D%0Ay%20%3D%20x%0Ax%5B0%5D%20%3D%2099%0Aprint%28y%5B0%5D%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) might be helpful for a beginner." ] }, { @@ -2903,7 +2905,7 @@ } }, "source": [ - "Variable names may contain upper and lower case letters, numbers, and underscores (\"\\_\") and be as long as we want them to be. However, they must not begin with a number. Also, they must not be any of Python's **[keywords](https://docs.python.org/3/reference/lexical_analysis.html#keywords)**.\n", + "Variable names may contain upper and lower case letters, numbers, and underscores (\"\\_\") and be as long as we want them to be. However, they must not begin with a number. Also, they must not be any of Python's built-in **[keywords](https://docs.python.org/3/reference/lexical_analysis.html#keywords)**.\n", "\n", "Variable names are usually chosen such that they do not need any more documentation and are self-explanatory. A very common convention is to use so-called **[snake\\_case](https://en.wikipedia.org/wiki/Snake_case)**: Keep everything lowercase and use underscores to seperate words.\n", "\n", @@ -3150,7 +3152,7 @@ " " ], "text/plain": [ - "" + "" ] }, "execution_count": 93, @@ -3188,7 +3190,7 @@ "\n", "What we said about individual operators above, namely that they have *no* side effects, should have been put here to begin with. The examples in the section on operators above were actually all expressions!\n", "\n", - "The simplest possible expression contains only one variable (or literal)." + "The simplest possible expressions contain only one variable or literal." ] }, { @@ -3218,6 +3220,33 @@ { "cell_type": "code", "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "42" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "42" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For sure, we need to include operators to achieve something useful." + ] + }, + { + "cell_type": "code", + "execution_count": 96, "metadata": { "slideshow": { "slide_type": "-" @@ -3230,7 +3259,7 @@ "165" ] }, - "execution_count": 95, + "execution_count": 96, "metadata": {}, "output_type": "execute_result" } @@ -3247,12 +3276,12 @@ } }, "source": [ - "The definition of an expression is **recursive**. So here the sub-expression `a + b` is combined with the literal `3` by the operator `**` to form the full expression." + "The definition of an expression is **recursive**. So, here the sub-expression `a + b` is combined with the literal `3` by the operator `**` to form the full expression." ] }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 97, "metadata": { "slideshow": { "slide_type": "-" @@ -3265,7 +3294,7 @@ "4492125" ] }, - "execution_count": 96, + "execution_count": 97, "metadata": {}, "output_type": "execute_result" } @@ -3282,12 +3311,12 @@ } }, "source": [ - "Here, the variable `y` is combined with the literal `2` by the indexing operator `[]`. The resulting expression evaluates to the " + "Here, the variable `y` is combined with the literal `2` by the indexing operator `[]`. The resulting expression evaluates to the third element in the `y` list." ] }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 98, "metadata": { "slideshow": { "slide_type": "-" @@ -3300,7 +3329,7 @@ "3" ] }, - "execution_count": 97, + "execution_count": 98, "metadata": {}, "output_type": "execute_result" } @@ -3317,12 +3346,12 @@ } }, "source": [ - "When not used as a **delimiter**, parentheses also constitute an operator, namely the **call operator** `()`. We have seen this syntax above when we \"called\" (i.e., executed) built-in functions and methods." + "When not used as a delimiter, parentheses also constitute an operator, namely the **call operator** `()`. We have seen this syntax above when we \"called\" (i.e., executed) built-in functions and methods." ] }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 99, "metadata": { "slideshow": { "slide_type": "-" @@ -3335,7 +3364,7 @@ "104" ] }, - "execution_count": 98, + "execution_count": 99, "metadata": {}, "output_type": "execute_result" } @@ -3368,7 +3397,7 @@ }, { "cell_type": "code", - "execution_count": 99, + "execution_count": 100, "metadata": { "slideshow": { "slide_type": "slide" @@ -3382,7 +3411,7 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 101, "metadata": { "slideshow": { "slide_type": "fragment" @@ -3395,7 +3424,7 @@ "'Hi class'" ] }, - "execution_count": 100, + "execution_count": 101, "metadata": {}, "output_type": "execute_result" } @@ -3417,7 +3446,7 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": 102, "metadata": { "slideshow": { "slide_type": "fragment" @@ -3430,7 +3459,7 @@ "'Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi Hi '" ] }, - "execution_count": 101, + "execution_count": 102, "metadata": {}, "output_type": "execute_result" } @@ -3458,14 +3487,14 @@ } }, "source": [ - "A **[statement](https://docs.python.org/3/reference/simple_stmts.html)** is anything that changes the state of the program's memory or has some other side effect. Statements do not just evaluate to a value like expressions; instead, they create or change values.\n", + "A **[statement](https://docs.python.org/3/reference/simple_stmts.html)** is anything that changes the state of a program or has some other side effect. Statements do not just evaluate to a value like expressions; instead, they create or change values.\n", "\n", "Most notably of course are the `=` and `del` statements." ] }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 103, "metadata": { "slideshow": { "slide_type": "slide" @@ -3478,7 +3507,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 104, "metadata": { "slideshow": { "slide_type": "-" @@ -3497,12 +3526,12 @@ } }, "source": [ - "The [print()](https://docs.python.org/3/library/functions.html#print) function is regarded a \"statement\" as well. In fact, it used to be a real statement in Python 2 and has all the necessary properties. It is a bit of a corner case as expressions are also \"printed\" in a Jupyter notebook when evaluated last in a code cell." + "The built-in [print()](https://docs.python.org/3/library/functions.html#print) function is regarded a \"statement\" as well. In fact, it used to be a real statement in Python 2 and has all the necessary properties. It is a bit of a corner case as expressions are also \"printed\" in a Jupyter notebook when evaluated last in a code cell." ] }, { "cell_type": "code", - "execution_count": 104, + "execution_count": 105, "metadata": { "slideshow": { "slide_type": "skip" @@ -3549,7 +3578,7 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": 106, "metadata": { "slideshow": { "slide_type": "slide" @@ -3577,7 +3606,7 @@ }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 107, "metadata": { "slideshow": { "slide_type": "fragment" @@ -3590,7 +3619,7 @@ }, { "cell_type": "code", - "execution_count": 107, + "execution_count": 108, "metadata": { "slideshow": { "slide_type": "-" @@ -3690,14 +3719,14 @@ " - ignored by Python\n", "\n", "\n", - "- functions (cf., Chapter 2)\n", + "- functions (cf., [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb))\n", " - named sequences of instructions\n", " - the smaller parts in a larger program\n", " - make a program more modular and thus easier to understand\n", "\n", "\n", - "- flow control (cf., Chapter 3)\n", - " - expression of **logic** or an **algorithm**\n", + "- flow control (cf., [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb))\n", + " - expression of **business logic** or an **algorithm**\n", " - conditional execution of a small **branch** within a program (i.e., `if` statements)\n", " - repetitive execution of parts of a program (i.e., `for`-loops and `while`-loops)" ] diff --git a/01_elements_review_and_exercises.ipynb b/01_elements_review_and_exercises.ipynb index 7e43b77..8940f24 100644 --- a/01_elements_review_and_exercises.ipynb +++ b/01_elements_review_and_exercises.ipynb @@ -19,7 +19,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Read Chapter 1 of the book. Then work through the ten review questions." + "Read [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) of the book. Then work through the ten review questions." ] }, { diff --git a/02_functions.ipynb b/02_functions.ipynb index 2c284f9..681838a 100644 --- a/02_functions.ipynb +++ b/02_functions.ipynb @@ -19,7 +19,7 @@ } }, "source": [ - "In Chapter 1 we typed the **business logic** of our little program to calculate the mean of a subset of a list of numbers right into the code cells. Then, we executed them one after another. We had no way of **re-using** the code except for either re-executing the cells or copying and pasting their contents into other cells. And whenever we find ourselves doing repetitive manual work, we can be sure that there must be a way of automating what we are doing.\n", + "In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) we typed the **business logic** of our little program to calculate the mean of a subset of a list of numbers right into the code cells. Then, we executed them one after another. We had no way of **re-using** the code except for either re-executing the cells or copying and pasting their contents into other cells. And whenever we find ourselves doing repetitive manual work, we can be sure that there must be a way of automating what we are doing.\n", "\n", "At the same time, we executed built-in functions (e.g., [print()](https://docs.python.org/3/library/functions.html#print), [sum()](https://docs.python.org/3/library/functions.html#sum), [len()](https://docs.python.org/3/library/functions.html#len), [id()](https://docs.python.org/3/library/functions.html#id), or [type()](https://docs.python.org/3/library/functions.html#type)) that obviously must be re-using the same parts inside core Python every time we use them.\n", "\n", @@ -45,7 +45,7 @@ } }, "source": [ - "So-called **[user-defined functions](https://docs.python.org/3/reference/compound_stmts.html#function-definitions)** can be created with the `def` statement. To extend an already familiar example, we re-use the introductory example from Chapter 1 in its final Pythonic version and transform it into the function `average_evens()` below. \n", + "So-called **[user-defined functions](https://docs.python.org/3/reference/compound_stmts.html#function-definitions)** can be created with the `def` statement. To extend an already familiar example, we re-use the introductory example from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) in its final Pythonic version and transform it into the function `average_evens()` below. \n", "\n", "A function's **name** must be chosen according to the same naming rules as for ordinary variables. In fact, Python manages function names just like variables. In this book, we further adopt the convention of ending function names with parentheses \"`()`\" in text cells for faster comprehension when reading (i.e., `average_evens()` vs. `average_evens`). These are not actually part of the name but must always be written out in the `def` statement for syntactic reasons.\n", "\n", @@ -142,7 +142,7 @@ { "data": { "text/plain": [ - "139655430681056" + "140693945143776" ] }, "execution_count": 3, @@ -289,7 +289,7 @@ } }, "source": [ - "Once defined we can **call** (i.e., \"execute\") a function with the **call operator** `()`. The formal parameters are filled in by passing variables or expressions as **arguments** to the function within the parentheses." + "We can **call** (i.e., \"execute\") a function with the **call operator** `()` as often as we wish. The formal parameters are filled in by passing variables or expressions as **arguments** to the function within the parentheses." ] }, { @@ -407,7 +407,7 @@ } }, "source": [ - "Notice how the parameters listed in a function's definition (i.e., `numbers`) and variables created inside it during execution (i.e., `evens` and `average`) are **local** to that function. That means they are only mapped to an object in memory while the function is being executed and de-referenced immediately when the function returns. We say they **go out of scope** once the function terminates." + "Notice how the parameters listed in a function's definition (i.e., `numbers`) and variables created inside it during execution (i.e., `evens` and `average`) are **local** to that function. That means they only point to an object in memory *while* the function is being executed and de-referenced immediately when the function returns. We say they **go out of scope** once the function terminates." ] }, { @@ -485,6 +485,17 @@ "average" ] }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "[PythonTutor](http://pythontutor.com/visualize.html#code=nums%20%3D%20%5B1,%202,%203,%204,%205,%206,%207,%208,%209,%2010%5D%0A%0Adef%20average_evens%28numbers%29%3A%0A%20%20%20%20evens%20%3D%20%5Bn%20for%20n%20in%20numbers%20if%20n%20%25%202%20%3D%3D%200%5D%0A%20%20%20%20average%20%3D%20sum%28evens%29%20/%20len%28evens%29%0A%20%20%20%20return%20average%0A%0Arv%20%3D%20average_evens%28nums%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) visualizes what happens in memory: To be precise, in the exact moment when the function call is initiated and `nums` is passed in as the `numbers` argument, there are *two* pointers to the *same* `list` object (cf., steps 4-5 in the visualization). We also see how Python creates a *new* **frame** that holds the function's local scope (i.e., \"internal names\") in addition to the **global** frame. Frames are nothing but [namespaces](https://en.wikipedia.org/wiki/Namespace) to *isolate* the names of different **scopes** from each other. The list comprehension `[n for n in numbers if n % 2 == 0]` constitutes yet another frame that is in scope as the `list` object assigned to `evens` is *being* created (cf., steps 6-18). When the function returns, only the global frame is left (cf., steps 21-22)." + ] + }, { "cell_type": "markdown", "metadata": { @@ -504,7 +515,7 @@ } }, "source": [ - "On the contrary, while a function is being executed, it can \"see\" the variables of the **enclosing scope** (i.e., \"outside\" of it). This is a common source of *semantic* errors. Consider the following stylized (and incorrect) example `average_wrong()`. The error is hard to spot with eyes: The function never references the `numbers` parameter but the `nums` variable in the **global scope** instead." + "On the contrary, while a function is being executed, it can reference the variables of **enclosing scopes** (i.e., \"outside\" of it). This is a common source of *semantic* errors. Consider the following stylized (and incorrect) example `average_wrong()`. The error is hard to spot with eyes: The function never references the `numbers` parameter but the `nums` variable in the **global scope** instead." ] }, { @@ -526,11 +537,22 @@ " Returns:\n", " float: average\n", " \"\"\"\n", - " evens = [n for n in nums if n % 2 == 0] # should reference numbers, not nums\n", + " evens = [n for n in nums if n % 2 == 0] # should reference numbers not nums\n", " average = sum(evens) / len(evens)\n", " return average" ] }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "`nums` in the global scope is of course unchanged." + ] + }, { "cell_type": "code", "execution_count": 16, @@ -555,6 +577,17 @@ "nums" ] }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Sometimes a function might return a correct solution for *some* inputs ..." + ] + }, { "cell_type": "code", "execution_count": 17, @@ -576,7 +609,18 @@ } ], "source": [ - "average_wrong(nums) # the result is correct by accident!" + "average_wrong(nums) # this is correct by accident" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "... but still be wrong *in general*." ] }, { @@ -611,7 +655,9 @@ } }, "source": [ - "Also, observe how both `average_evens()` and `average_wrong()` use the same names for their respective parameters and variables internally. For sure, Python is smart enough to not mix them up. This is because each function call creates a temporary **[namespace](https://en.wikipedia.org/wiki/Namespace)** that *isolates* the local scope's names for usage only from within the function. As we saw in the [Zen of Python](https://www.python.org/dev/peps/pep-0020/), \"namespaces are one honking great idea\" (cf., `import this`)." + "[PythonTutor](http://pythontutor.com/visualize.html#code=nums%20%3D%20%5B1,%202,%203,%204,%205,%206,%207,%208,%209,%2010%5D%0A%0Adef%20average_wrong%28numbers%29%3A%0A%20%20%20%20evens%20%3D%20%5Bn%20for%20n%20in%20nums%20if%20n%20%25%202%20%3D%3D%200%5D%0A%20%20%20%20average%20%3D%20sum%28evens%29%20/%20len%28evens%29%0A%20%20%20%20return%20average%0A%0Arv%20%3D%20average_wrong%28%5B123,%20456,%20789%5D%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) is again helpful at visualizing the error interactively: Creating the `list` object `evens` eventually points to takes *12* computational steps, namely one for setting up an empty `list` object, *ten* for filling it with elements derived from `nums` in the global scope, and one to make `evens` point at it (cf., steps 6-18).\n", + "\n", + "The frames logic shown by PythonTutor is the mechanism by which Python not only manages the names inside one function call but for potentially many calls occuring simultaneously as we will see in [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb). It is the reason why we may re-use the same names for the parameters and variables inside both `average_evens()` and `average_wrong()` without Python mixing them up. So, as we already read in the [Zen of Python](https://www.python.org/dev/peps/pep-0020/), \"namespaces are one honking great idea\" (cf., `import this`) and a frame is just a special kind of namespace." ] }, { @@ -633,9 +679,9 @@ } }, "source": [ - "Code gets even more confusing when variables by the same name from different scopes collide. In particular, what should we expect to happen if a function changes a globally defined variable internally?\n", + "Code gets even more confusing when variables by the *same* name from *different* scopes collide. In particular, what should we expect to happen if a function \"changes\" a globally defined variable internally?\n", "\n", - "`average_odds()` below works like `average_evens()` above except that it **[casts](https://en.wikipedia.org/wiki/Type_conversion)** (i.e., \"converts\") the elements of `numbers` as objects of type `int` with the [int()](https://docs.python.org/3/library/functions.html#int) built-in first before filtering and averaging them. In doing so, it introduces an *internal* variable `nums` whose name collides with the one in the global scope. The **inequality operator** `!=` is just the **reversed** version of `==`." + "`average_odds()` below works like `average_evens()` above except that it **[casts](https://en.wikipedia.org/wiki/Type_conversion)** (i.e., \"converts\") the elements of `numbers` as objects of type `int` with the [int()](https://docs.python.org/3/library/functions.html#int) built-in first before filtering and averaging them. In doing so, it introduces an *internal* variable `nums` whose name collides with the one in the global scope. To filter for odd numbers, we use the **inequality operator** `!=` that is just the **reversed** version of `==`." ] }, { @@ -652,7 +698,7 @@ " \"\"\"Calculate the average of all odd numbers in a list.\n", "\n", " Args:\n", - " numbers (list): a list of numbers; must be integers\n", + " numbers (list): a list of numbers; must be integer-like\n", "\n", " Returns:\n", " float: average\n", @@ -671,7 +717,7 @@ } }, "source": [ - "`nums` in the global scope is of course the same list from above." + "`nums` in the global scope is still unchanged." ] }, { @@ -706,7 +752,7 @@ } }, "source": [ - "As good practice, let's first use inputs for which we can calculate the answer in our heads to verify that `average_odds()` is correct." + "As good practice, let's first use inputs for which we can calculate the answer in our heads to \"verify\" that `average_odds()` is \"correct\"." ] }, { @@ -730,7 +776,7 @@ } ], "source": [ - "average_odds([1, 100, 3, 100, 5]) # verify the function's correctness with predictable inputs" + "average_odds([1.0, 10.0, 3.0, 10.0, 5.0]) # verify correctness with predictable inputs" ] }, { @@ -776,7 +822,7 @@ } }, "source": [ - "Python, however, is again smart enough to keep the two `nums` variables apart. So the global `nums` is still pointing to the very same list object as before." + "Python, however, is again smart enough to keep all the involved `nums` variables apart. So the global `nums` is still pointing to the very same `list` object as before." ] }, { @@ -811,7 +857,9 @@ } }, "source": [ - "The reason why everything works just fine is that *every time* we (re-)assign an object to a variable inside a function with the `=` statement, this is done in the local scope by default. There are ways to change variables existing in an outer scope from within a function but we save that for a later chapter.\n", + "The reason why everything just works is that *every time* we (re-)assign an object to a variable *inside* a function with the `=` statement, this is done in the *local* scope by default. There are ways to change variables existing in an outer scope from within a function but this is a rather advanced topic on its own.\n", + "\n", + "[PythonTutor](http://pythontutor.com/visualize.html#code=nums%20%3D%20%5B1,%202,%203,%204,%205,%206,%207,%208,%209,%2010%5D%0A%0Adef%20average_odds%28numbers%29%3A%0A%20%20%20%20nums%20%3D%20%5Bint%28n%29%20for%20n%20in%20numbers%5D%0A%20%20%20%20odds%20%3D%20%5Bn%20for%20n%20in%20nums%20if%20n%20%25%202%20!%3D%200%5D%0A%20%20%20%20average%20%3D%20sum%28odds%29%20/%20len%28odds%29%0A%20%20%20%20return%20average%0A%0Arv%20%3D%20average_odds%28%5B1.0,%2010.0,%203.0,%2010.0,%205.0%5D%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows how *two* `nums` variables exist in *different* scopes pointing to *different* objects (cf., steps 14-25) when we execute `average_odds([1.0, 10.0, 3.0, 10.0, 5.0])`.\n", "\n", "Variables whose names collide with the ones of variables in enclosing scopes - and the global scope is just the most enclosing scope - are said to **shadow** them.\n", "\n", @@ -1122,7 +1170,7 @@ } }, "source": [ - "So far we have only specified one parameter in each of our user-defined functions. In Chapter 1, however, we saw the built-in function [divmod()](https://docs.python.org/3/library/functions.html#divmod) taking two arguments. Obviously, the order of the numbers passed in mattered. Whenever we call a function and list its arguments in a comma seperated manner, we say that we pass in the arguments by position or refer to them as **positional arguments**." + "So far we have only specified one parameter in each of our user-defined functions. In [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb), however, we saw the built-in function [divmod()](https://docs.python.org/3/library/functions.html#divmod) taking two arguments. Obviously, the order of the numbers passed in mattered. Whenever we call a function and list its arguments in a comma seperated manner, we say that we pass in the arguments by position or refer to them as **positional arguments**." ] }, { @@ -2036,7 +2084,7 @@ { "data": { "text/plain": [ - "139655519584648" + "140694050824664" ] }, "execution_count": 58, @@ -2308,7 +2356,7 @@ "source": [ "Observe how the arguments passed to functions do not need to be just variables or simple literals. Instead, we can pass in any *expression* that evaluates to a *new* object of the type the function expects.\n", "\n", - "So just as a reminder from the expression vs. statement discussion in Chapter 1: An expression is *any* syntactically correct combination of variables and literals with operators. And the call operator `()` is just ... well another operator. So both of the next two code cells are just expressions! They have no permanent side effect in memory. We can execute them as often as we want *without* changing the state of the program (i.e., this Jupyter notebook).\n", + "So just as a reminder from the expression vs. statement discussion in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb): An expression is *any* syntactically correct combination of variables and literals with operators. And the call operator `()` is just ... well another operator. So both of the next two code cells are just expressions! They have no permanent side effect in memory. We can execute them as often as we want *without* changing the state of the program (i.e., this Jupyter notebook).\n", "\n", "So, regarding the very next cell in particular: Although the `2 ** 2` creates a *new* object `4` in memory that is then immediately passed into the [math.sqrt()](https://docs.python.org/3/library/math.html#math.sqrt) function, once that function call returns, \"all is lost\" and the newly created `4` object is forgotten again, as well as the return value of [math.sqrt()](https://docs.python.org/3/library/math.html#math.sqrt)." ] @@ -2649,7 +2697,7 @@ { "data": { "text/plain": [ - "0.12717011866176486" + "0.15268128055183228" ] }, "execution_count": 75, @@ -2684,7 +2732,7 @@ { "data": { "text/plain": [ - ">" + ">" ] }, "execution_count": 76, @@ -2733,7 +2781,7 @@ { "data": { "text/plain": [ - "8" + "2" ] }, "execution_count": 78, @@ -2881,7 +2929,7 @@ "source": [ "[numpy](http://www.numpy.org/) is the de-facto standard in the Python world for handling **array-like** data. That is a fancy word for data that can be put into a matrix or vector format. We will look at it in depth in Chapter 9.\n", "\n", - "As [numpy](http://www.numpy.org/) is *not* in the [standard library](https://docs.python.org/3/library/index.html), it must be *manually* installed, for example, with the [pip](https://pip.pypa.io/en/stable/) tool. As mentioned in Chapter 0, to execute terminal commands from within a Jupyter notebook, we just need to start a code cell with an exclamation mark.\n", + "As [numpy](http://www.numpy.org/) is *not* in the [standard library](https://docs.python.org/3/library/index.html), it must be *manually* installed, for example, with the [pip](https://pip.pypa.io/en/stable/) tool. As mentioned in [Chapter 0](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/00_start_up.ipynb), to execute terminal commands from within a Jupyter notebook, we just need to start a code cell with an exclamation mark.\n", "\n", "If you are running this notebook with an installation of the [Anaconda Distribution](https://www.anaconda.com/distribution/), then [numpy](http://www.numpy.org/) is probably already installed. Running the cell below, will just confirm that." ] diff --git a/02_functions_review_and_exercises.ipynb b/02_functions_review_and_exercises.ipynb index 647e47f..dcd0a9c 100644 --- a/02_functions_review_and_exercises.ipynb +++ b/02_functions_review_and_exercises.ipynb @@ -18,7 +18,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Read Chapter 2 of the book. Then work through the ten review questions." + "Read [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) of the book. Then work through the ten review questions." ] }, { diff --git a/03_conditionals.ipynb b/03_conditionals.ipynb index acd509d..6d70f07 100644 --- a/03_conditionals.ipynb +++ b/03_conditionals.ipynb @@ -19,7 +19,7 @@ } }, "source": [ - "We analyzed every aspect of the `average_evens()` function in Chapter 2 except for the `if` part. While it seems to intuitively do what we expect it to, there is a whole lot more to be learned from taking it apart. In particular, the `if` can occur within both a **statement** as in our introductory example in Chapter 1 but also an **expression** as in `average_evens()`. This is analogous as to how a noun in a natural language is *either* the subject of *or* an object in a sentence. What is common to both versions of the `if` is that it leads to code being executed for *parts* of the input only. It is our first way of **controlling** the **flow of execution** in a program.\n", + "We analyzed every aspect of the `average_evens()` function in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) except for the `if` part. While it seems to intuitively do what we expect it to, there is a whole lot more to be learned from taking it apart. In particular, the `if` can occur within both a **statement** as in our introductory example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) but also an **expression** as in `average_evens()`. This is analogous as to how a noun in a natural language is *either* the subject of *or* an object in a sentence. What is common to both versions of the `if` is that it leads to code being executed for *parts* of the input only. It is our first way of **controlling** the **flow of execution** in a program.\n", "\n", "After deconstructing `if` in the first part of this chapter, we take a close look at a similar concept, namely handling and raising **exceptions**." ] @@ -139,7 +139,7 @@ } }, "source": [ - "There are, however, cases where even well-behaved Python does not make us happy. Chapter 5 will provide more insights on that." + "There are, however, cases where even well-behaved Python does not make us happy. Chapter 5 will provide more insights on this \"bug\"." ] }, { @@ -189,7 +189,7 @@ { "data": { "text/plain": [ - "94709180875744" + "94163040564192" ] }, "execution_count": 5, @@ -213,7 +213,7 @@ { "data": { "text/plain": [ - "94709180875712" + "94163040564160" ] }, "execution_count": 6, @@ -281,9 +281,9 @@ } }, "source": [ - "Let's not confuse the boolean `False` with `None`, another special built-in object! We saw the latter before in Chapter 2 as the *implicit* return value of a function without a `return` statement.\n", + "Let's not confuse the boolean `False` with `None`, another special built-in object! We saw the latter before in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) as the *implicit* return value of a function without a `return` statement.\n", "\n", - "We might think of `None` in a boolean context indicating a \"maybe\" or even an \"unknown\" answer. But for Python, there are no \"maybe\" or \"unknown\" objects as we will see further below!\n", + "We might think of `None` in a boolean context indicating a \"maybe\" or even an \"unknown\" answer; however, for Python, there are no \"maybe\" or \"unknown\" objects as we will see further below!\n", "\n", "Whereas `False` is of type `bool`, `None` is of type `NoneType`. So, they are totally unrelated. On the contrary, as both `True` and `False` are of the same type, we could call them \"siblings\"." ] @@ -313,7 +313,7 @@ { "data": { "text/plain": [ - "94709180862704" + "94163040551152" ] }, "execution_count": 10, @@ -357,7 +357,7 @@ } }, "source": [ - "`True`, `False`, and `None` have the property that they each exist in memory only *once*. Objects designed this way are so-called **singletons**. This **[design pattern](https://en.wikipedia.org/wiki/Design_Patterns)** was originally developed to keep a program's memory usage at a minimum. It may only be employed in situations where we know that an object will never mutate its value in place (i.e., to re-use the bag analogy from Chapter 1, no flipping of $0$s and $1$s in the bag is allowed). In languages \"closer\" to the memory like C we would have to code this singleton logic ourselves but Python has this already built in for *some* types.\n", + "`True`, `False`, and `None` have the property that they each exist in memory only *once*. Objects designed this way are so-called **singletons**. This **[design pattern](https://en.wikipedia.org/wiki/Design_Patterns)** was originally developed to keep a program's memory usage at a minimum. It may only be employed in situations where we know that an object will *not* mutate its value (i.e., to re-use the bag analogy from [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb), no flipping of $0$s and $1$s in the bag is allowed). In languages \"closer\" to the memory like C we would have to code this singleton logic ourselves but Python has this already built in for *some* types.\n", "\n", "We can verify this with either the `is` operator or by comparing memory addresses." ] @@ -512,7 +512,7 @@ } ], "source": [ - "42 != 123 # = \"not equal to\"; other programming languages sometimes use \"<>\" instead" + "42 != 123 # = \"not equal to\"; other languages may use \"<>\"" ] }, { @@ -672,7 +672,7 @@ } }, "source": [ - "Relational operators have a *higher precedence* over logical operators (cf., the [reference](https://docs.python.org/3/reference/expressions.html#operator-precedence)). So the following expression means what we intuitively think it does." + "Relational operators have a **[higher precedence](https://docs.python.org/3/reference/expressions.html#operator-precedence)** over logical operators. So the following expression means what we intuitively think it does." ] }, { @@ -825,7 +825,7 @@ } }, "source": [ - "For even better readability, [some practitioner](https://llewellynfalco.blogspot.com/2016/02/dont-use-greater-than-sign-in.html) suggest to never use the `>` and `>=` operators (note that the included example is written in [Java](https://en.wikipedia.org/wiki/Java_%28programming_language%29) and `&&` means `and` and `||` means `or`).\n", + "For even better readability, [some practitioners](https://llewellynfalco.blogspot.com/2016/02/dont-use-greater-than-sign-in.html) suggest to *never* use the `>` and `>=` operators (note that the included example is written in [Java](https://en.wikipedia.org/wiki/Java_%28programming_language%29) and `&&` means `and` and `||` means `or`).\n", "\n", "Python allows **chaining** relational operators that are combined with the `and` operator. For example, the following two cells implement the same logic where the second is a lot easier to read." ] @@ -899,7 +899,7 @@ "source": [ "The operands of the logical operators do not actually have to be *boolean* expressions as defined above but may be *any* kind of expression. If a sub-expression does *not* evaluate to an object of type `bool`, Python automatically casts the resulting object as such.\n", "\n", - "For example, any non-zero numeric object effectively becomes `True`. While this behavior allows writing more concise and thus \"beautiful\" code, it is also a common source of confusion." + "For example, any non-zero numeric object becomes `True`. While this behavior allows writing conciser and thus more \"beautiful\" code, it is also a common source of confusion." ] }, { @@ -1028,7 +1028,7 @@ } }, "source": [ - "In a boolean context `None` is casted as `False`. So, `None` is really *not* a \"maybe\" answer but a \"no\"." + "In a boolean context, `None` is casted as `False`! So, `None` is really *not* a \"maybe\" answer but a \"no\"." ] }, { @@ -1144,9 +1144,9 @@ } }, "source": [ - "In order to write useful programs, we need to control the flow of execution, for example, to react to user input.\n", + "In order to write useful programs, we need to control the flow of execution, for example, to react to user input. The logic by which a program does that is referred to as **business logic**.\n", "\n", - "One major language construct to do so is the **conditional statement** or `if` **statement** (cf., the [reference](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement)). It consists of:\n", + "One major language construct to do so is the **[conditional statement](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement)** or `if` statement. It consists of:\n", "\n", "- *one* mandatory `if`-clause,\n", "- an *arbitrary* number of `elif`-clauses (i.e. \"else if\"), and\n", @@ -1350,7 +1350,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "z is positive\n" + "z is odd\n" ] } ], @@ -1602,7 +1602,7 @@ "source": [ "In the previous two chapters we already encountered a couple of *runtime* errors. A natural urge we might have after reading about conditional statements is to write code that somehow reacts to the occurence of such exceptions. All we need for that is a way to formulate a condition for that.\n", "\n", - "For sure, this is such a common thing to do that Python provides its own language construct for it, namely the `try` statement (cf., the [reference](https://docs.python.org/3/reference/compound_stmts.html#the-try-statement)).\n", + "For sure, this is such a common thing to do that Python provides its own language construct for it, namely the `try` [statement](https://docs.python.org/3/reference/compound_stmts.html#the-try-statement).\n", "\n", "In its simplest form, it comes with just two branches: `try` and `except`. The following basically tells Python to execute the code in the `try`-branch and if *anything* goes wrong, continue in the `except`-branch instead of **raising** an error to us. Of course, if nothing goes wrong, the `except`-branch is *not* executed." ] @@ -1711,7 +1711,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Yes, division worked smoothly.\n", + "Oops. Division by 0. How does that work?\n", "I am always printed\n" ] } @@ -1748,7 +1748,7 @@ } }, "source": [ - "- **boolean expressions** evaluate either to `True` or `False`\n", + "- **boolean expressions** evaluate to either `True` or `False`\n", "- **relational operators** compare operands according to \"human\" interpretations\n", "- **logical operators** combine boolean sub-expressions to more \"complex\" expressions\n", "- the **conditional statement** is a *major* concept to **control** the **flow of execution** depending on some **conditions**\n", diff --git a/03_conditionals_review_and_exercises.ipynb b/03_conditionals_review_and_exercises.ipynb index f152b30..d39c551 100644 --- a/03_conditionals_review_and_exercises.ipynb +++ b/03_conditionals_review_and_exercises.ipynb @@ -19,7 +19,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Read Chapter 3 of the book. Then work through the seven review questions." + "Read [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb) of the book. Then work through the seven review questions." ] }, { From a91aea1f3685b2cb118c36fbe450a6f5febc1c2b Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 1 Oct 2019 17:48:22 +0200 Subject: [PATCH 3/5] Add initial version of notebook 04 --- 04_iteration.ipynb | 6529 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6529 insertions(+) create mode 100644 04_iteration.ipynb diff --git a/04_iteration.ipynb b/04_iteration.ipynb new file mode 100644 index 0000000..755b4a5 --- /dev/null +++ b/04_iteration.ipynb @@ -0,0 +1,6529 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Chapter 4: Iteration" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "While controlling the flow of execution with an `if` statement is definitely a must-have building block in any programming language, it alone does not allow us to run a block of code repetitively and we need to be able to do exactly that in order to write useful software.\n", + "\n", + "You might think that the `for` statement shown in some examples before is the missing piece in the puzzle. However, we can actually live without it and postpone its official introduction until the second half of this chapter.\n", + "\n", + "Instead, we dive into the big idea of **iteration** by studying the concept of **recursion** first. This is quite the opposite of many introductory books on programming that only treat the latter as a nice-to-have artifact, if at all. Yet, understanding recursion sharpens one's mind and contributes to seeing problems from a different angle." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Recursion" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A function that calls itself is **recursive** and the process of executing such a function it is called **recursion**.\n", + "\n", + "Recursive functions contain some form of a conditional check (e.g., `if` statement) to identify a **base case** that ends the recursion *when* reached. Otherwise, the function would keep calling itself forever.\n", + "\n", + "The meaning of the word *recursive* is similar to *circular*. However, a truly circular definition is not very helpful and we think of a recursive function as kind of a \"circular function with a way out at the end\"." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Trivial Example: Countdown" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A rather trivial toy example illustrates the important aspects concretely: If called with any positive integer as its `n` argument, `countdown()` just prints that number and calls itself with the *new* `n` being the *old* `n` minus `1`. This continues until `countdown()` is called with `n=0`. Then, the flow of execution hits the base case and the function calls stop." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def countdown(n):\n", + " \"\"\"Print a countdown until the party starts.\n", + "\n", + " Args:\n", + " n (int): seconds until the party begins\n", + " \"\"\"\n", + " if n == 0: # base case\n", + " print(\"Happy new Year!\")\n", + " else:\n", + " print(n)\n", + " countdown(n - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "2\n", + "1\n", + "Happy new Year!\n" + ] + } + ], + "source": [ + "countdown(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As trivial as this seems at first sight, a lot of complexity is hidden in this implementation. In particular, the order in which objects are created and de-referenced in memory might not be obvious right away as [PythonTutor](http://pythontutor.com/visualize.html#code=def%20countdown%28n%29%3A%0A%20%20%20%20if%20n%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20print%28%22Happy%20new%20Year!%22%29%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print%28n%29%0A%20%20%20%20%20%20%20%20countdown%28n%20-%201%29%0A%0Acountdown%283%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows: Each time `countdown()` is called, Python creates a *new* frame in the part of the memory where it manages all the names. This way Python *isolates* all the different `n` variables from each other. As new frames are created until we reach the base case after which the frames are destroyed in the *reversed* order, this is called a **[stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))** of frames in computer science terminology. In simple words, a stack is a last-in-first-out (LIFO) task queue. Each frame has a single parent frame, namely the one whose recursive function call created it." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Recursion in Mathematics" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Recursion plays an important role in mathematics as well and we likely know about it from some introductory course, for example, in [combinatorics](https://en.wikipedia.org/wiki/Combinatorics)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Easy Example: [Factorial](https://en.wikipedia.org/wiki/Factorial)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The factorial function, denoted with the symbol $!$, is defined as follows for all non-negative integers:" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "$$0! = 1$$\n", + "$$n! = n*(n-1)!$$" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Whenever we can find a recursive way of formulating an idea, we can immediately translate it into Python in a *naive* way (i.e., we create a *correct* program that may *not* be an *efficient* implementation yet).\n", + "\n", + "Below is a first version of `factorial()`: The `return` statement does not have to be a function's last code line and we can certainly have several `return` statements as well." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " \"\"\"Calculate the factorial of a number.\n", + "\n", + " Args:\n", + " n (int): number to calculate the factorial for\n", + "\n", + " Returns:\n", + " factorial (int)\n", + " \"\"\"\n", + " if n == 0:\n", + " return 1\n", + " else:\n", + " recurse = factorial(n - 1)\n", + " result = n * recurse\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "When we read such code, it is often easier not to follow every function call (i.e., `factorial(n - 1)` here) in one's mind but assume we receive a return value as specified in the documentation. Some call this approach **[leap of faith](http://greenteapress.com/thinkpython2/html/thinkpython2007.html#sec75)**. In fact, we practice this anyways whenever we call built-in functions (e.g., [print()](https://docs.python.org/3/library/functions.html#print) or [len()](https://docs.python.org/3/library/functions.html#len)) where we would have to read C code in many cases.\n", + "\n", + "To visualize *all* the computational steps of the examplary `factorial(3)`, we use [PythonTutor](http://pythontutor.com/visualize.html#code=def%20factorial%28n%29%3A%0A%20%20%20%20if%20n%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20return%201%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20recurse%20%3D%20factorial%28n%20-%201%29%0A%20%20%20%20%20%20%20%20result%20%3D%20n%20*%20recurse%0A%20%20%20%20%20%20%20%20return%20result%0A%0Asolution%20%3D%20factorial%283%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false): The recursion again creates a stack of frames in memory. In contrast to the previous trivial example, each frame leaves a return value in memory after it is destroyed. This return value is then assigned to the `recurse` variable within the parent frame and used to compute `result`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3628800" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A Pythonista would formulate `factorial()` in a conciser way using the so-called **early exit** pattern: No `else`-clause is needed as reaching a `return` statement immediately ends a function call. Furthermore, we do not really need the temporary variables `recurse` and `result`.\n", + "\n", + "As [PythonTutor](http://pythontutor.com/visualize.html#code=def%20factorial%28n%29%3A%0A%20%20%20%20if%20n%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20return%201%0A%20%20%20%20return%20n%20*%20factorial%28n%20-%201%29%0A%0Asolution%20%3D%20factorial%283%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows, this implementation is more efficient as it only requires 18 computational steps instead of 24 to calculate `factorial(3)`, an improvement of 25 percent! " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " \"\"\"Calculate the factorial of a number.\n", + "\n", + " Args:\n", + " n (int): number to calculate the factorial for\n", + "\n", + " Returns:\n", + " factorial (int)\n", + " \"\"\"\n", + " if n == 0:\n", + " return 1\n", + " return n * factorial(n - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3628800" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Note that the [math](https://docs.python.org/3/library/math.html) module in the standard library provides a [factorial()](https://docs.python.org/3/library/math.html#math.factorial) function as well and we should therefore *never* implement it ourselves in a real code base." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on built-in function factorial in module math:\n", + "\n", + "factorial(x, /)\n", + " Find x!.\n", + " \n", + " Raise a ValueError if x is negative or non-integral.\n", + "\n" + ] + } + ], + "source": [ + "help(math.factorial)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.factorial(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3628800" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.factorial(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### \"Involved\" Example: [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As famous philosopher Euclid already shows in his \"Elements\" (ca. 300 BC), the greatest common divisor of two integers, i.e., the largest number that divides both integers without a remainder, can be efficiently computed with the following code. This example illustrates that a recursive solution to a problem is not always easy to understand." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def gcd(a, b):\n", + " \"\"\"Calculate the greatest common divisor of two numbers.\n", + "\n", + " Args:\n", + " a (int): first number\n", + " b (int): second number\n", + "\n", + " Returns:\n", + " gcd (int)\n", + " \"\"\"\n", + " if b == 0:\n", + " return a \n", + " return gcd(b, a % b)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gcd(12, 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Euclid's algorithm is stunningly fast, even for large numbers. Its speed comes from the use of the modulo operation `%`. However, this is *not* true for recusion in general, which can result in very slow programs if not applied correctly." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gcd(112233445566778899, 987654321)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As expected, for two [prime numbers](https://en.wikipedia.org/wiki/List_of_prime_numbers) the greatest common divisor is of course $1$." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gcd(2, 7919)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The [math](https://docs.python.org/3/library/math.html) module in the standard library provides a [gcd()](https://docs.python.org/3/library/math.html#math.gcd) function as well and therefore we should again *never* implement it on our own." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on built-in function gcd in module math:\n", + "\n", + "gcd(x, y, /)\n", + " greatest common divisor of x and y\n", + "\n" + ] + } + ], + "source": [ + "help(math.gcd)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.gcd(12, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "9" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.gcd(112233445566778899, 987654321)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "math.gcd(2, 7919)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### \"Easy at first Glance\" Example: [Fibonacci Numbers](https://en.wikipedia.org/wiki/Fibonacci_number)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The Fibonacci numbers are an infinite sequence of non-negative integers that are calculated such that every number is the sum of its two predecessors where the first two numbers of the sequence are defined to be $0$ and $1$. For example, the first 13 numbers are:" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144$" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's write a function `fibonacci()` that calculates the $i$th Fibonacci number where $0$ will be the $0$th number. Looking at the numbers in a **backwards** fashion (i.e., from right to left), we realize that the return value for `fibonacci(i)` can be reduced to the sum of the return values for `fibonacci(i - 1)` and `fibonacci(i - 2)` disregarding the *two* base cases." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [], + "source": [ + "def fibonacci(i):\n", + " \"\"\"Calculate the ith Fibonacci number.\n", + "\n", + " Args:\n", + " i (int): index of the Fibonacci number to calculate\n", + "\n", + " Returns:\n", + " ith_fibonacci (int)\n", + " \"\"\"\n", + " if i == 0:\n", + " return 0\n", + " elif i == 1:\n", + " return 1\n", + " return fibonacci(i - 1) + fibonacci(i - 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "144" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fibonacci(12) # = 13th number" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "##### Efficiency of Algorithms" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This implementation is *highly* **inefficient** as small Fibonacci numbers can already take a very long time to compute. The reason for this is **exponential growth** in the number of function calls. As [PythonTutor](http://pythontutor.com/visualize.html#code=def%20fibonacci%28i%29%3A%0A%20%20%20%20if%20i%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20return%200%0A%20%20%20%20elif%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20return%201%0A%20%20%20%20return%20fibonacci%28i%20-%201%29%20%2B%20fibonacci%28i%20-%202%29%0A%0Arv%20%3D%20fibonacci%285%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows, `fibonacci()` is called again and again with the same `i` arguments.\n", + "\n", + "To understand this in detail, we would have to study algorithms and data structures (e.g., with [this book](https://www.amazon.de/Introduction-Algorithms-Press-Thomas-Cormen/dp/0262033844/ref=sr_1_1?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&crid=1JNE8U0VZGU0O&qid=1569837169&s=gateway&sprefix=algorithms+an%2Caps%2C180&sr=8-1)), a discipline within computer science, and dive into the analysis of **[time complexity of algorithms](https://en.wikipedia.org/wiki/Time_complexity)**.\n", + "\n", + "Luckily, in the Fibonacci case the inefficiency can be resolved with a **caching** (i.e., \"re-use\") strategy from the field of **[dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming)**, namely **[memoization](https://en.wikipedia.org/wiki/Memoization)**. We will do so in Chapter 8 after introducing the [dictionaries](https://docs.python.org/3/library/stdtypes.html#dict) data type.\n", + "\n", + "Let's measure the average run times for `fibonacci()` and varying `i` arguments with the `%%timeit` [cell magic](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-timeit) that comes with Jupyter." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The slowest run took 5.01 times longer than the fastest. This could mean that an intermediate result is being cached.\n", + "55 µs ± 44.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%%timeit -n 100\n", + "fibonacci(12)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.63 ms ± 68 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%%timeit -n 100\n", + "fibonacci(20)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "192 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit -n 1 -r 1\n", + "fibonacci(30)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.21 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit -n 1 -r 1\n", + "fibonacci(35)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5.62 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit -n 1 -r 1\n", + "fibonacci(37)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Infinite Recursion" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If a recursion does not reach its base case, it will theoretically run forever. Luckily, Python detects that and saves the computer from crashing by raising a `RecursionError`.\n", + "\n", + "The simplest possible infinite recursion is generated like so." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def run_forever():\n", + " \"\"\"Also a pointless function should have a docstring.\"\"\"\n", + " run_forever()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "RecursionError", + "evalue": "maximum recursion depth exceeded", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mrun_forever\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mrun_forever\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrun_forever\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\"\"\"Also a pointless function should have a docstring.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mrun_forever\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "... last 1 frames repeated, from the frame below ...\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mrun_forever\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mrun_forever\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\"\"\"Also a pointless function should have a docstring.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mrun_forever\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded" + ] + } + ], + "source": [ + "run_forever()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "However, even the trivial `countdown()` function from above is not immune to an infinite recursion. Let's call it with `3.1` instead of `3`. What goes wrong here?" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.1\n", + "2.1\n", + "1.1\n", + "0.10000000000000009\n", + "-0.8999999999999999\n", + "-1.9\n", + "-2.9\n", + "-3.9\n", + "-4.9\n", + "-5.9\n", + "-6.9\n", + "-7.9\n", + "-8.9\n", + "-9.9\n", + "-10.9\n", + "-11.9\n", + "-12.9\n", + "-13.9\n", + "-14.9\n", + "-15.9\n", + "-16.9\n", + "-17.9\n", + "-18.9\n", + "-19.9\n", + "-20.9\n", + "-21.9\n", + "-22.9\n", + "-23.9\n", + "-24.9\n", + "-25.9\n", + "-26.9\n", + "-27.9\n", + "-28.9\n", + "-29.9\n", + "-30.9\n", + "-31.9\n", + "-32.9\n", + "-33.9\n", + "-34.9\n", + "-35.9\n", + "-36.9\n", + "-37.9\n", + "-38.9\n", + "-39.9\n", + "-40.9\n", + "-41.9\n", + "-42.9\n", + "-43.9\n", + "-44.9\n", + "-45.9\n", + "-46.9\n", + "-47.9\n", + "-48.9\n", + "-49.9\n", + "-50.9\n", + "-51.9\n", + "-52.9\n", + "-53.9\n", + "-54.9\n", + "-55.9\n", + "-56.9\n", + "-57.9\n", + "-58.9\n", + "-59.9\n", + "-60.9\n", + "-61.9\n", + "-62.9\n", + "-63.9\n", + "-64.9\n", + "-65.9\n", + "-66.9\n", + "-67.9\n", + "-68.9\n", + "-69.9\n", + "-70.9\n", + "-71.9\n", + "-72.9\n", + "-73.9\n", + "-74.9\n", + "-75.9\n", + "-76.9\n", + "-77.9\n", + "-78.9\n", + "-79.9\n", + "-80.9\n", + "-81.9\n", + "-82.9\n", + "-83.9\n", + "-84.9\n", + "-85.9\n", + "-86.9\n", + "-87.9\n", + "-88.9\n", + "-89.9\n", + "-90.9\n", + "-91.9\n", + "-92.9\n", + "-93.9\n", + "-94.9\n", + "-95.9\n", + "-96.9\n", + "-97.9\n", + "-98.9\n", + "-99.9\n", + "-100.9\n", + "-101.9\n", + "-102.9\n", + "-103.9\n", + "-104.9\n", + "-105.9\n", + "-106.9\n", + "-107.9\n", + "-108.9\n", + "-109.9\n", + "-110.9\n", + "-111.9\n", + "-112.9\n", + "-113.9\n", + "-114.9\n", + "-115.9\n", + "-116.9\n", + "-117.9\n", + "-118.9\n", + "-119.9\n", + "-120.9\n", + "-121.9\n", + "-122.9\n", + "-123.9\n", + "-124.9\n", + "-125.9\n", + "-126.9\n", + "-127.9\n", + "-128.9\n", + "-129.9\n", + "-130.9\n", + "-131.9\n", + "-132.9\n", + "-133.9\n", + "-134.9\n", + "-135.9\n", + "-136.9\n", + "-137.9\n", + "-138.9\n", + "-139.9\n", + "-140.9\n", + "-141.9\n", + "-142.9\n", + "-143.9\n", + "-144.9\n", + "-145.9\n", + "-146.9\n", + "-147.9\n", + "-148.9\n", + "-149.9\n", + "-150.9\n", + "-151.9\n", + "-152.9\n", + "-153.9\n", + "-154.9\n", + "-155.9\n", + "-156.9\n", + "-157.9\n", + "-158.9\n", + "-159.9\n", + "-160.9\n", + "-161.9\n", + "-162.9\n", + "-163.9\n", + "-164.9\n", + "-165.9\n", + "-166.9\n", + "-167.9\n", + "-168.9\n", + "-169.9\n", + "-170.9\n", + "-171.9\n", + "-172.9\n", + "-173.9\n", + "-174.9\n", + "-175.9\n", + "-176.9\n", + "-177.9\n", + "-178.9\n", + "-179.9\n", + "-180.9\n", + "-181.9\n", + "-182.9\n", + "-183.9\n", + "-184.9\n", + "-185.9\n", + "-186.9\n", + "-187.9\n", + "-188.9\n", + "-189.9\n", + "-190.9\n", + "-191.9\n", + "-192.9\n", + "-193.9\n", + "-194.9\n", + "-195.9\n", + "-196.9\n", + "-197.9\n", + "-198.9\n", + "-199.9\n", + "-200.9\n", + "-201.9\n", + "-202.9\n", + "-203.9\n", + "-204.9\n", + "-205.9\n", + "-206.9\n", + "-207.9\n", + "-208.9\n", + "-209.9\n", + "-210.9\n", + "-211.9\n", + "-212.9\n", + "-213.9\n", + "-214.9\n", + "-215.9\n", + "-216.9\n", + "-217.9\n", + "-218.9\n", + "-219.9\n", + "-220.9\n", + "-221.9\n", + "-222.9\n", + "-223.9\n", + "-224.9\n", + "-225.9\n", + "-226.9\n", + "-227.9\n", + "-228.9\n", + "-229.9\n", + "-230.9\n", + "-231.9\n", + "-232.9\n", + "-233.9\n", + "-234.9\n", + "-235.9\n", + "-236.9\n", + "-237.9\n", + "-238.9\n", + "-239.9\n", + "-240.9\n", + "-241.9\n", + "-242.9\n", + "-243.9\n", + "-244.9\n", + "-245.9\n", + "-246.9\n", + "-247.9\n", + "-248.9\n", + "-249.9\n", + "-250.9\n", + "-251.9\n", + "-252.9\n", + "-253.9\n", + "-254.9\n", + "-255.9\n", + "-256.9\n", + "-257.9\n", + "-258.9\n", + "-259.9\n", + "-260.9\n", + "-261.9\n", + "-262.9\n", + "-263.9\n", + "-264.9\n", + "-265.9\n", + "-266.9\n", + "-267.9\n", + "-268.9\n", + "-269.9\n", + "-270.9\n", + "-271.9\n", + "-272.9\n", + "-273.9\n", + "-274.9\n", + "-275.9\n", + "-276.9\n", + "-277.9\n", + "-278.9\n", + "-279.9\n", + "-280.9\n", + "-281.9\n", + "-282.9\n", + "-283.9\n", + "-284.9\n", + "-285.9\n", + "-286.9\n", + "-287.9\n", + "-288.9\n", + "-289.9\n", + "-290.9\n", + "-291.9\n", + "-292.9\n", + "-293.9\n", + "-294.9\n", + "-295.9\n", + "-296.9\n", + "-297.9\n", + "-298.9\n", + "-299.9\n", + "-300.9\n", + "-301.9\n", + "-302.9\n", + "-303.9\n", + "-304.9\n", + "-305.9\n", + "-306.9\n", + "-307.9\n", + "-308.9\n", + "-309.9\n", + "-310.9\n", + "-311.9\n", + "-312.9\n", + "-313.9\n", + "-314.9\n", + "-315.9\n", + "-316.9\n", + "-317.9\n", + "-318.9\n", + "-319.9\n", + "-320.9\n", + "-321.9\n", + "-322.9\n", + "-323.9\n", + "-324.9\n", + "-325.9\n", + "-326.9\n", + "-327.9\n", + "-328.9\n", + "-329.9\n", + "-330.9\n", + "-331.9\n", + "-332.9\n", + "-333.9\n", + "-334.9\n", + "-335.9\n", + "-336.9\n", + "-337.9\n", + "-338.9\n", + "-339.9\n", + "-340.9\n", + "-341.9\n", + "-342.9\n", + "-343.9\n", + "-344.9\n", + "-345.9\n", + "-346.9\n", + "-347.9\n", + "-348.9\n", + "-349.9\n", + "-350.9\n", + "-351.9\n", + "-352.9\n", + "-353.9\n", + "-354.9\n", + "-355.9\n", + "-356.9\n", + "-357.9\n", + "-358.9\n", + "-359.9\n", + "-360.9\n", + "-361.9\n", + "-362.9\n", + "-363.9\n", + "-364.9\n", + "-365.9\n", + "-366.9\n", + "-367.9\n", + "-368.9\n", + "-369.9\n", + "-370.9\n", + "-371.9\n", + "-372.9\n", + "-373.9\n", + "-374.9\n", + "-375.9\n", + "-376.9\n", + "-377.9\n", + "-378.9\n", + "-379.9\n", + "-380.9\n", + "-381.9\n", + "-382.9\n", + "-383.9\n", + "-384.9\n", + "-385.9\n", + "-386.9\n", + "-387.9\n", + "-388.9\n", + "-389.9\n", + "-390.9\n", + "-391.9\n", + "-392.9\n", + "-393.9\n", + "-394.9\n", + "-395.9\n", + "-396.9\n", + "-397.9\n", + "-398.9\n", + "-399.9\n", + "-400.9\n", + "-401.9\n", + "-402.9\n", + "-403.9\n", + "-404.9\n", + "-405.9\n", + "-406.9\n", + "-407.9\n", + "-408.9\n", + "-409.9\n", + "-410.9\n", + "-411.9\n", + "-412.9\n", + "-413.9\n", + "-414.9\n", + "-415.9\n", + "-416.9\n", + "-417.9\n", + "-418.9\n", + "-419.9\n", + "-420.9\n", + "-421.9\n", + "-422.9\n", + "-423.9\n", + "-424.9\n", + "-425.9\n", + "-426.9\n", + "-427.9\n", + "-428.9\n", + "-429.9\n", + "-430.9\n", + "-431.9\n", + "-432.9\n", + "-433.9\n", + "-434.9\n", + "-435.9\n", + "-436.9\n", + "-437.9\n", + "-438.9\n", + "-439.9\n", + "-440.9\n", + "-441.9\n", + "-442.9\n", + "-443.9\n", + "-444.9\n", + "-445.9\n", + "-446.9\n", + "-447.9\n", + "-448.9\n", + "-449.9\n", + "-450.9\n", + "-451.9\n", + "-452.9\n", + "-453.9\n", + "-454.9\n", + "-455.9\n", + "-456.9\n", + "-457.9\n", + "-458.9\n", + "-459.9\n", + "-460.9\n", + "-461.9\n", + "-462.9\n", + "-463.9\n", + "-464.9\n", + "-465.9\n", + "-466.9\n", + "-467.9\n", + "-468.9\n", + "-469.9\n", + "-470.9\n", + "-471.9\n", + "-472.9\n", + "-473.9\n", + "-474.9\n", + "-475.9\n", + "-476.9\n", + "-477.9\n", + "-478.9\n", + "-479.9\n", + "-480.9\n", + "-481.9\n", + "-482.9\n", + "-483.9\n", + "-484.9\n", + "-485.9\n", + "-486.9\n", + "-487.9\n", + "-488.9\n", + "-489.9\n", + "-490.9\n", + "-491.9\n", + "-492.9\n", + "-493.9\n", + "-494.9\n", + "-495.9\n", + "-496.9\n", + "-497.9\n", + "-498.9\n", + "-499.9\n", + "-500.9\n", + "-501.9\n", + "-502.9\n", + "-503.9\n", + "-504.9\n", + "-505.9\n", + "-506.9\n", + "-507.9\n", + "-508.9\n", + "-509.9\n", + "-510.9\n", + "-511.9\n", + "-512.9\n", + "-513.9\n", + "-514.9\n", + "-515.9\n", + "-516.9\n", + "-517.9\n", + "-518.9\n", + "-519.9\n", + "-520.9\n", + "-521.9\n", + "-522.9\n", + "-523.9\n", + "-524.9\n", + "-525.9\n", + "-526.9\n", + "-527.9\n", + "-528.9\n", + "-529.9\n", + "-530.9\n", + "-531.9\n", + "-532.9\n", + "-533.9\n", + "-534.9\n", + "-535.9\n", + "-536.9\n", + "-537.9\n", + "-538.9\n", + "-539.9\n", + "-540.9\n", + "-541.9\n", + "-542.9\n", + "-543.9\n", + "-544.9\n", + "-545.9\n", + "-546.9\n", + "-547.9\n", + "-548.9\n", + "-549.9\n", + "-550.9\n", + "-551.9\n", + "-552.9\n", + "-553.9\n", + "-554.9\n", + "-555.9\n", + "-556.9\n", + "-557.9\n", + "-558.9\n", + "-559.9\n", + "-560.9\n", + "-561.9\n", + "-562.9\n", + "-563.9\n", + "-564.9\n", + "-565.9\n", + "-566.9\n", + "-567.9\n", + "-568.9\n", + "-569.9\n", + "-570.9\n", + "-571.9\n", + "-572.9\n", + "-573.9\n", + "-574.9\n", + "-575.9\n", + "-576.9\n", + "-577.9\n", + "-578.9\n", + "-579.9\n", + "-580.9\n", + "-581.9\n", + "-582.9\n", + "-583.9\n", + "-584.9\n", + "-585.9\n", + "-586.9\n", + "-587.9\n", + "-588.9\n", + "-589.9\n", + "-590.9\n", + "-591.9\n", + "-592.9\n", + "-593.9\n", + "-594.9\n", + "-595.9\n", + "-596.9\n", + "-597.9\n", + "-598.9\n", + "-599.9\n", + "-600.9\n", + "-601.9\n", + "-602.9\n", + "-603.9\n", + "-604.9\n", + "-605.9\n", + "-606.9\n", + "-607.9\n", + "-608.9\n", + "-609.9\n", + "-610.9\n", + "-611.9\n", + "-612.9\n", + "-613.9\n", + "-614.9\n", + "-615.9\n", + "-616.9\n", + "-617.9\n", + "-618.9\n", + "-619.9\n", + "-620.9\n", + "-621.9\n", + "-622.9\n", + "-623.9\n", + "-624.9\n", + "-625.9\n", + "-626.9\n", + "-627.9\n", + "-628.9\n", + "-629.9\n", + "-630.9\n", + "-631.9\n", + "-632.9\n", + "-633.9\n", + "-634.9\n", + "-635.9\n", + "-636.9\n", + "-637.9\n", + "-638.9\n", + "-639.9\n", + "-640.9\n", + "-641.9\n", + "-642.9\n", + "-643.9\n", + "-644.9\n", + "-645.9\n", + "-646.9\n", + "-647.9\n", + "-648.9\n", + "-649.9\n", + "-650.9\n", + "-651.9\n", + "-652.9\n", + "-653.9\n", + "-654.9\n", + "-655.9\n", + "-656.9\n", + "-657.9\n", + "-658.9\n", + "-659.9\n", + "-660.9\n", + "-661.9\n", + "-662.9\n", + "-663.9\n", + "-664.9\n", + "-665.9\n", + "-666.9\n", + "-667.9\n", + "-668.9\n", + "-669.9\n", + "-670.9\n", + "-671.9\n", + "-672.9\n", + "-673.9\n", + "-674.9\n", + "-675.9\n", + "-676.9\n", + "-677.9\n", + "-678.9\n", + "-679.9\n", + "-680.9\n", + "-681.9\n", + "-682.9\n", + "-683.9\n", + "-684.9\n", + "-685.9\n", + "-686.9\n", + "-687.9\n", + "-688.9\n", + "-689.9\n", + "-690.9\n", + "-691.9\n", + "-692.9\n", + "-693.9\n", + "-694.9\n", + "-695.9\n", + "-696.9\n", + "-697.9\n", + "-698.9\n", + "-699.9\n", + "-700.9\n", + "-701.9\n", + "-702.9\n", + "-703.9\n", + "-704.9\n", + "-705.9\n", + "-706.9\n", + "-707.9\n", + "-708.9\n", + "-709.9\n", + "-710.9\n", + "-711.9\n", + "-712.9\n", + "-713.9\n", + "-714.9\n", + "-715.9\n", + "-716.9\n", + "-717.9\n", + "-718.9\n", + "-719.9\n", + "-720.9\n", + "-721.9\n", + "-722.9\n", + "-723.9\n", + "-724.9\n", + "-725.9\n", + "-726.9\n", + "-727.9\n", + "-728.9\n", + "-729.9\n", + "-730.9\n", + "-731.9\n", + "-732.9\n", + "-733.9\n", + "-734.9\n", + "-735.9\n", + "-736.9\n", + "-737.9\n", + "-738.9\n", + "-739.9\n", + "-740.9\n", + "-741.9\n", + "-742.9\n", + "-743.9\n", + "-744.9\n", + "-745.9\n", + "-746.9\n", + "-747.9\n", + "-748.9\n", + "-749.9\n", + "-750.9\n", + "-751.9\n", + "-752.9\n", + "-753.9\n", + "-754.9\n", + "-755.9\n", + "-756.9\n", + "-757.9\n", + "-758.9\n", + "-759.9\n", + "-760.9\n", + "-761.9\n", + "-762.9\n", + "-763.9\n", + "-764.9\n", + "-765.9\n", + "-766.9\n", + "-767.9\n", + "-768.9\n", + "-769.9\n", + "-770.9\n", + "-771.9\n", + "-772.9\n", + "-773.9\n", + "-774.9\n", + "-775.9\n", + "-776.9\n", + "-777.9\n", + "-778.9\n", + "-779.9\n", + "-780.9\n", + "-781.9\n", + "-782.9\n", + "-783.9\n", + "-784.9\n", + "-785.9\n", + "-786.9\n", + "-787.9\n", + "-788.9\n", + "-789.9\n", + "-790.9\n", + "-791.9\n", + "-792.9\n", + "-793.9\n", + "-794.9\n", + "-795.9\n", + "-796.9\n", + "-797.9\n", + "-798.9\n", + "-799.9\n", + "-800.9\n", + "-801.9\n", + "-802.9\n", + "-803.9\n", + "-804.9\n", + "-805.9\n", + "-806.9\n", + "-807.9\n", + "-808.9\n", + "-809.9\n", + "-810.9\n", + "-811.9\n", + "-812.9\n", + "-813.9\n", + "-814.9\n", + "-815.9\n", + "-816.9\n", + "-817.9\n", + "-818.9\n", + "-819.9\n", + "-820.9\n", + "-821.9\n", + "-822.9\n", + "-823.9\n", + "-824.9\n", + "-825.9\n", + "-826.9\n", + "-827.9\n", + "-828.9\n", + "-829.9\n", + "-830.9\n", + "-831.9\n", + "-832.9\n", + "-833.9\n", + "-834.9\n", + "-835.9\n", + "-836.9\n", + "-837.9\n", + "-838.9\n", + "-839.9\n", + "-840.9\n", + "-841.9\n", + "-842.9\n", + "-843.9\n", + "-844.9\n", + "-845.9\n", + "-846.9\n", + "-847.9\n", + "-848.9\n", + "-849.9\n", + "-850.9\n", + "-851.9\n", + "-852.9\n", + "-853.9\n", + "-854.9\n", + "-855.9\n", + "-856.9\n", + "-857.9\n", + "-858.9\n", + "-859.9\n", + "-860.9\n", + "-861.9\n", + "-862.9\n", + "-863.9\n", + "-864.9\n", + "-865.9\n", + "-866.9\n", + "-867.9\n", + "-868.9\n", + "-869.9\n", + "-870.9\n", + "-871.9\n", + "-872.9\n", + "-873.9\n", + "-874.9\n", + "-875.9\n", + "-876.9\n", + "-877.9\n", + "-878.9\n", + "-879.9\n", + "-880.9\n", + "-881.9\n", + "-882.9\n", + "-883.9\n", + "-884.9\n", + "-885.9\n", + "-886.9\n", + "-887.9\n", + "-888.9\n", + "-889.9\n", + "-890.9\n", + "-891.9\n", + "-892.9\n", + "-893.9\n", + "-894.9\n", + "-895.9\n", + "-896.9\n", + "-897.9\n", + "-898.9\n", + "-899.9\n", + "-900.9\n", + "-901.9\n", + "-902.9\n", + "-903.9\n", + "-904.9\n", + "-905.9\n", + "-906.9\n", + "-907.9\n", + "-908.9\n", + "-909.9\n", + "-910.9\n", + "-911.9\n", + "-912.9\n", + "-913.9\n", + "-914.9\n", + "-915.9\n", + "-916.9\n", + "-917.9\n", + "-918.9\n", + "-919.9\n", + "-920.9\n", + "-921.9\n", + "-922.9\n", + "-923.9\n", + "-924.9\n", + "-925.9\n", + "-926.9\n", + "-927.9\n", + "-928.9\n", + "-929.9\n", + "-930.9\n", + "-931.9\n", + "-932.9\n", + "-933.9\n", + "-934.9\n", + "-935.9\n", + "-936.9\n", + "-937.9\n", + "-938.9\n", + "-939.9\n", + "-940.9\n", + "-941.9\n", + "-942.9\n", + "-943.9\n", + "-944.9\n", + "-945.9\n", + "-946.9\n", + "-947.9\n", + "-948.9\n", + "-949.9\n", + "-950.9\n", + "-951.9\n", + "-952.9\n", + "-953.9\n", + "-954.9\n", + "-955.9\n", + "-956.9\n", + "-957.9\n", + "-958.9\n", + "-959.9\n", + "-960.9\n", + "-961.9\n", + "-962.9\n", + "-963.9\n", + "-964.9\n", + "-965.9\n", + "-966.9\n", + "-967.9\n", + "-968.9\n", + "-969.9\n", + "-970.9\n", + "-971.9\n", + "-972.9\n", + "-973.9\n", + "-974.9\n", + "-975.9\n", + "-976.9\n", + "-977.9\n", + "-978.9\n", + "-979.9\n", + "-980.9\n", + "-981.9\n", + "-982.9\n", + "-983.9\n", + "-984.9\n", + "-985.9\n", + "-986.9\n", + "-987.9\n", + "-988.9\n", + "-989.9\n", + "-990.9\n", + "-991.9\n", + "-992.9\n", + "-993.9\n", + "-994.9\n", + "-995.9\n", + "-996.9\n", + "-997.9\n", + "-998.9\n", + "-999.9\n", + "-1000.9\n", + "-1001.9\n", + "-1002.9\n", + "-1003.9\n", + "-1004.9\n", + "-1005.9\n", + "-1006.9\n", + "-1007.9\n", + "-1008.9\n", + "-1009.9\n", + "-1010.9\n", + "-1011.9\n", + "-1012.9\n", + "-1013.9\n", + "-1014.9\n", + "-1015.9\n", + "-1016.9\n", + "-1017.9\n", + "-1018.9\n", + "-1019.9\n", + "-1020.9\n", + "-1021.9\n", + "-1022.9\n", + "-1023.9\n", + "-1024.9\n", + "-1025.9\n", + "-1026.9\n", + "-1027.9\n", + "-1028.9\n", + "-1029.9\n", + "-1030.9\n", + "-1031.9\n", + "-1032.9\n", + "-1033.9\n", + "-1034.9\n", + "-1035.9\n", + "-1036.9\n", + "-1037.9\n", + "-1038.9\n", + "-1039.9\n", + "-1040.9\n", + "-1041.9\n", + "-1042.9\n", + "-1043.9\n", + "-1044.9\n", + "-1045.9\n", + "-1046.9\n", + "-1047.9\n", + "-1048.9\n", + "-1049.9\n", + "-1050.9\n", + "-1051.9\n", + "-1052.9\n", + "-1053.9\n", + "-1054.9\n", + "-1055.9\n", + "-1056.9\n", + "-1057.9\n", + "-1058.9\n", + "-1059.9\n", + "-1060.9\n", + "-1061.9\n", + "-1062.9\n", + "-1063.9\n", + "-1064.9\n", + "-1065.9\n", + "-1066.9\n", + "-1067.9\n", + "-1068.9\n", + "-1069.9\n", + "-1070.9\n", + "-1071.9\n", + "-1072.9\n", + "-1073.9\n", + "-1074.9\n", + "-1075.9\n", + "-1076.9\n", + "-1077.9\n", + "-1078.9\n", + "-1079.9\n", + "-1080.9\n", + "-1081.9\n", + "-1082.9\n", + "-1083.9\n", + "-1084.9\n", + "-1085.9\n", + "-1086.9\n", + "-1087.9\n", + "-1088.9\n", + "-1089.9\n", + "-1090.9\n", + "-1091.9\n", + "-1092.9\n", + "-1093.9\n", + "-1094.9\n", + "-1095.9\n", + "-1096.9\n", + "-1097.9\n", + "-1098.9\n", + "-1099.9\n", + "-1100.9\n", + "-1101.9\n", + "-1102.9\n", + "-1103.9\n", + "-1104.9\n", + "-1105.9\n", + "-1106.9\n", + "-1107.9\n", + "-1108.9\n", + "-1109.9\n", + "-1110.9\n", + "-1111.9\n", + "-1112.9\n", + "-1113.9\n", + "-1114.9\n", + "-1115.9\n", + "-1116.9\n", + "-1117.9\n", + "-1118.9\n", + "-1119.9\n", + "-1120.9\n", + "-1121.9\n", + "-1122.9\n", + "-1123.9\n", + "-1124.9\n", + "-1125.9\n", + "-1126.9\n", + "-1127.9\n", + "-1128.9\n", + "-1129.9\n", + "-1130.9\n", + "-1131.9\n", + "-1132.9\n", + "-1133.9\n", + "-1134.9\n", + "-1135.9\n", + "-1136.9\n", + "-1137.9\n", + "-1138.9\n", + "-1139.9\n", + "-1140.9\n", + "-1141.9\n", + "-1142.9\n", + "-1143.9\n", + "-1144.9\n", + "-1145.9\n", + "-1146.9\n", + "-1147.9\n", + "-1148.9\n", + "-1149.9\n", + "-1150.9\n", + "-1151.9\n", + "-1152.9\n", + "-1153.9\n", + "-1154.9\n", + "-1155.9\n", + "-1156.9\n", + "-1157.9\n", + "-1158.9\n", + "-1159.9\n", + "-1160.9\n", + "-1161.9\n", + "-1162.9\n", + "-1163.9\n", + "-1164.9\n", + "-1165.9\n", + "-1166.9\n", + "-1167.9\n", + "-1168.9\n", + "-1169.9\n", + "-1170.9\n", + "-1171.9\n", + "-1172.9\n", + "-1173.9\n", + "-1174.9\n", + "-1175.9\n", + "-1176.9\n", + "-1177.9\n", + "-1178.9\n", + "-1179.9\n", + "-1180.9\n", + "-1181.9\n", + "-1182.9\n", + "-1183.9\n", + "-1184.9\n", + "-1185.9\n", + "-1186.9\n", + "-1187.9\n", + "-1188.9\n", + "-1189.9\n", + "-1190.9\n", + "-1191.9\n", + "-1192.9\n", + "-1193.9\n", + "-1194.9\n", + "-1195.9\n", + "-1196.9\n", + "-1197.9\n", + "-1198.9\n", + "-1199.9\n", + "-1200.9\n", + "-1201.9\n", + "-1202.9\n", + "-1203.9\n", + "-1204.9\n", + "-1205.9\n", + "-1206.9\n", + "-1207.9\n", + "-1208.9\n", + "-1209.9\n", + "-1210.9\n", + "-1211.9\n", + "-1212.9\n", + "-1213.9\n", + "-1214.9\n", + "-1215.9\n", + "-1216.9\n", + "-1217.9\n", + "-1218.9\n", + "-1219.9\n", + "-1220.9\n", + "-1221.9\n", + "-1222.9\n", + "-1223.9\n", + "-1224.9\n", + "-1225.9\n", + "-1226.9\n", + "-1227.9\n", + "-1228.9\n", + "-1229.9\n", + "-1230.9\n", + "-1231.9\n", + "-1232.9\n", + "-1233.9\n", + "-1234.9\n", + "-1235.9\n", + "-1236.9\n", + "-1237.9\n", + "-1238.9\n", + "-1239.9\n", + "-1240.9\n", + "-1241.9\n", + "-1242.9\n", + "-1243.9\n", + "-1244.9\n", + "-1245.9\n", + "-1246.9\n", + "-1247.9\n", + "-1248.9\n", + "-1249.9\n", + "-1250.9\n", + "-1251.9\n", + "-1252.9\n", + "-1253.9\n", + "-1254.9\n", + "-1255.9\n", + "-1256.9\n", + "-1257.9\n", + "-1258.9\n", + "-1259.9\n", + "-1260.9\n", + "-1261.9\n", + "-1262.9\n", + "-1263.9\n", + "-1264.9\n", + "-1265.9\n", + "-1266.9\n", + "-1267.9\n", + "-1268.9\n", + "-1269.9\n", + "-1270.9\n", + "-1271.9\n", + "-1272.9\n", + "-1273.9\n", + "-1274.9\n", + "-1275.9\n", + "-1276.9\n", + "-1277.9\n", + "-1278.9\n", + "-1279.9\n", + "-1280.9\n", + "-1281.9\n", + "-1282.9\n", + "-1283.9\n", + "-1284.9\n", + "-1285.9\n", + "-1286.9\n", + "-1287.9\n", + "-1288.9\n", + "-1289.9\n", + "-1290.9\n", + "-1291.9\n", + "-1292.9\n", + "-1293.9\n", + "-1294.9\n", + "-1295.9\n", + "-1296.9\n", + "-1297.9\n", + "-1298.9\n", + "-1299.9\n", + "-1300.9\n", + "-1301.9\n", + "-1302.9\n", + "-1303.9\n", + "-1304.9\n", + "-1305.9\n", + "-1306.9\n", + "-1307.9\n", + "-1308.9\n", + "-1309.9\n", + "-1310.9\n", + "-1311.9\n", + "-1312.9\n", + "-1313.9\n", + "-1314.9\n", + "-1315.9\n", + "-1316.9\n", + "-1317.9\n", + "-1318.9\n", + "-1319.9\n", + "-1320.9\n", + "-1321.9\n", + "-1322.9\n", + "-1323.9\n", + "-1324.9\n", + "-1325.9\n", + "-1326.9\n", + "-1327.9\n", + "-1328.9\n", + "-1329.9\n", + "-1330.9\n", + "-1331.9\n", + "-1332.9\n", + "-1333.9\n", + "-1334.9\n", + "-1335.9\n", + "-1336.9\n", + "-1337.9\n", + "-1338.9\n", + "-1339.9\n", + "-1340.9\n", + "-1341.9\n", + "-1342.9\n", + "-1343.9\n", + "-1344.9\n", + "-1345.9\n", + "-1346.9\n", + "-1347.9\n", + "-1348.9\n", + "-1349.9\n", + "-1350.9\n", + "-1351.9\n", + "-1352.9\n", + "-1353.9\n", + "-1354.9\n", + "-1355.9\n", + "-1356.9\n", + "-1357.9\n", + "-1358.9\n", + "-1359.9\n", + "-1360.9\n", + "-1361.9\n", + "-1362.9\n", + "-1363.9\n", + "-1364.9\n", + "-1365.9\n", + "-1366.9\n", + "-1367.9\n", + "-1368.9\n", + "-1369.9\n", + "-1370.9\n", + "-1371.9\n", + "-1372.9\n", + "-1373.9\n", + "-1374.9\n", + "-1375.9\n", + "-1376.9\n", + "-1377.9\n", + "-1378.9\n", + "-1379.9\n", + "-1380.9\n", + "-1381.9\n", + "-1382.9\n", + "-1383.9\n", + "-1384.9\n", + "-1385.9\n", + "-1386.9\n", + "-1387.9\n", + "-1388.9\n", + "-1389.9\n", + "-1390.9\n", + "-1391.9\n", + "-1392.9\n", + "-1393.9\n", + "-1394.9\n", + "-1395.9\n", + "-1396.9\n", + "-1397.9\n", + "-1398.9\n", + "-1399.9\n", + "-1400.9\n", + "-1401.9\n", + "-1402.9\n", + "-1403.9\n", + "-1404.9\n", + "-1405.9\n", + "-1406.9\n", + "-1407.9\n", + "-1408.9\n", + "-1409.9\n", + "-1410.9\n", + "-1411.9\n", + "-1412.9\n", + "-1413.9\n", + "-1414.9\n", + "-1415.9\n", + "-1416.9\n", + "-1417.9\n", + "-1418.9\n", + "-1419.9\n", + "-1420.9\n", + "-1421.9\n", + "-1422.9\n", + "-1423.9\n", + "-1424.9\n", + "-1425.9\n", + "-1426.9\n", + "-1427.9\n", + "-1428.9\n", + "-1429.9\n", + "-1430.9\n", + "-1431.9\n", + "-1432.9\n", + "-1433.9\n", + "-1434.9\n", + "-1435.9\n", + "-1436.9\n", + "-1437.9\n", + "-1438.9\n", + "-1439.9\n", + "-1440.9\n", + "-1441.9\n", + "-1442.9\n", + "-1443.9\n", + "-1444.9\n", + "-1445.9\n", + "-1446.9\n", + "-1447.9\n", + "-1448.9\n", + "-1449.9\n", + "-1450.9\n", + "-1451.9\n", + "-1452.9\n", + "-1453.9\n", + "-1454.9\n", + "-1455.9\n", + "-1456.9\n", + "-1457.9\n", + "-1458.9\n", + "-1459.9\n", + "-1460.9\n", + "-1461.9\n", + "-1462.9\n", + "-1463.9\n", + "-1464.9\n", + "-1465.9\n", + "-1466.9\n", + "-1467.9\n", + "-1468.9\n", + "-1469.9\n", + "-1470.9\n", + "-1471.9\n", + "-1472.9\n", + "-1473.9\n", + "-1474.9\n", + "-1475.9\n", + "-1476.9\n", + "-1477.9\n", + "-1478.9\n", + "-1479.9\n", + "-1480.9\n", + "-1481.9\n", + "-1482.9\n", + "-1483.9\n", + "-1484.9\n", + "-1485.9\n", + "-1486.9\n", + "-1487.9\n", + "-1488.9\n", + "-1489.9\n", + "-1490.9\n", + "-1491.9\n", + "-1492.9\n", + "-1493.9\n", + "-1494.9\n", + "-1495.9\n", + "-1496.9\n", + "-1497.9\n", + "-1498.9\n", + "-1499.9\n", + "-1500.9\n", + "-1501.9\n", + "-1502.9\n", + "-1503.9\n", + "-1504.9\n", + "-1505.9\n", + "-1506.9\n", + "-1507.9\n", + "-1508.9\n", + "-1509.9\n", + "-1510.9\n", + "-1511.9\n", + "-1512.9\n", + "-1513.9\n", + "-1514.9\n", + "-1515.9\n", + "-1516.9\n", + "-1517.9\n", + "-1518.9\n", + "-1519.9\n", + "-1520.9\n", + "-1521.9\n", + "-1522.9\n", + "-1523.9\n", + "-1524.9\n", + "-1525.9\n", + "-1526.9\n", + "-1527.9\n", + "-1528.9\n", + "-1529.9\n", + "-1530.9\n", + "-1531.9\n", + "-1532.9\n", + "-1533.9\n", + "-1534.9\n", + "-1535.9\n", + "-1536.9\n", + "-1537.9\n", + "-1538.9\n", + "-1539.9\n", + "-1540.9\n", + "-1541.9\n", + "-1542.9\n", + "-1543.9\n", + "-1544.9\n", + "-1545.9\n", + "-1546.9\n", + "-1547.9\n", + "-1548.9\n", + "-1549.9\n", + "-1550.9\n", + "-1551.9\n", + "-1552.9\n", + "-1553.9\n", + "-1554.9\n", + "-1555.9\n", + "-1556.9\n", + "-1557.9\n", + "-1558.9\n", + "-1559.9\n", + "-1560.9\n", + "-1561.9\n", + "-1562.9\n", + "-1563.9\n", + "-1564.9\n", + "-1565.9\n", + "-1566.9\n", + "-1567.9\n", + "-1568.9\n", + "-1569.9\n", + "-1570.9\n", + "-1571.9\n", + "-1572.9\n", + "-1573.9\n", + "-1574.9\n", + "-1575.9\n", + "-1576.9\n", + "-1577.9\n", + "-1578.9\n", + "-1579.9\n", + "-1580.9\n", + "-1581.9\n", + "-1582.9\n", + "-1583.9\n", + "-1584.9\n", + "-1585.9\n", + "-1586.9\n", + "-1587.9\n", + "-1588.9\n", + "-1589.9\n", + "-1590.9\n", + "-1591.9\n", + "-1592.9\n", + "-1593.9\n", + "-1594.9\n", + "-1595.9\n", + "-1596.9\n", + "-1597.9\n", + "-1598.9\n", + "-1599.9\n", + "-1600.9\n", + "-1601.9\n", + "-1602.9\n", + "-1603.9\n", + "-1604.9\n", + "-1605.9\n", + "-1606.9\n", + "-1607.9\n", + "-1608.9\n", + "-1609.9\n", + "-1610.9\n", + "-1611.9\n", + "-1612.9\n", + "-1613.9\n", + "-1614.9\n", + "-1615.9\n", + "-1616.9\n", + "-1617.9\n", + "-1618.9\n", + "-1619.9\n", + "-1620.9\n", + "-1621.9\n", + "-1622.9\n", + "-1623.9\n", + "-1624.9\n", + "-1625.9\n", + "-1626.9\n", + "-1627.9\n", + "-1628.9\n", + "-1629.9\n", + "-1630.9\n", + "-1631.9\n", + "-1632.9\n", + "-1633.9\n", + "-1634.9\n", + "-1635.9\n", + "-1636.9\n", + "-1637.9\n", + "-1638.9\n", + "-1639.9\n", + "-1640.9\n", + "-1641.9\n", + "-1642.9\n", + "-1643.9\n", + "-1644.9\n", + "-1645.9\n", + "-1646.9\n", + "-1647.9\n", + "-1648.9\n", + "-1649.9\n", + "-1650.9\n", + "-1651.9\n", + "-1652.9\n", + "-1653.9\n", + "-1654.9\n", + "-1655.9\n", + "-1656.9\n", + "-1657.9\n", + "-1658.9\n", + "-1659.9\n", + "-1660.9\n", + "-1661.9\n", + "-1662.9\n", + "-1663.9\n", + "-1664.9\n", + "-1665.9\n", + "-1666.9\n", + "-1667.9\n", + "-1668.9\n", + "-1669.9\n", + "-1670.9\n", + "-1671.9\n", + "-1672.9\n", + "-1673.9\n", + "-1674.9\n", + "-1675.9\n", + "-1676.9\n", + "-1677.9\n", + "-1678.9\n", + "-1679.9\n", + "-1680.9\n", + "-1681.9\n", + "-1682.9\n", + "-1683.9\n", + "-1684.9\n", + "-1685.9\n", + "-1686.9\n", + "-1687.9\n", + "-1688.9\n", + "-1689.9\n", + "-1690.9\n", + "-1691.9\n", + "-1692.9\n", + "-1693.9\n", + "-1694.9\n", + "-1695.9\n", + "-1696.9\n", + "-1697.9\n", + "-1698.9\n", + "-1699.9\n", + "-1700.9\n", + "-1701.9\n", + "-1702.9\n", + "-1703.9\n", + "-1704.9\n", + "-1705.9\n", + "-1706.9\n", + "-1707.9\n", + "-1708.9\n", + "-1709.9\n", + "-1710.9\n", + "-1711.9\n", + "-1712.9\n", + "-1713.9\n", + "-1714.9\n", + "-1715.9\n", + "-1716.9\n", + "-1717.9\n", + "-1718.9\n", + "-1719.9\n", + "-1720.9\n", + "-1721.9\n", + "-1722.9\n", + "-1723.9\n", + "-1724.9\n", + "-1725.9\n", + "-1726.9\n", + "-1727.9\n", + "-1728.9\n", + "-1729.9\n", + "-1730.9\n", + "-1731.9\n", + "-1732.9\n", + "-1733.9\n", + "-1734.9\n", + "-1735.9\n", + "-1736.9\n", + "-1737.9\n", + "-1738.9\n", + "-1739.9\n", + "-1740.9\n", + "-1741.9\n", + "-1742.9\n", + "-1743.9\n", + "-1744.9\n", + "-1745.9\n", + "-1746.9\n", + "-1747.9\n", + "-1748.9\n", + "-1749.9\n", + "-1750.9\n", + "-1751.9\n", + "-1752.9\n", + "-1753.9\n", + "-1754.9\n", + "-1755.9\n", + "-1756.9\n", + "-1757.9\n", + "-1758.9\n", + "-1759.9\n", + "-1760.9\n", + "-1761.9\n", + "-1762.9\n", + "-1763.9\n", + "-1764.9\n", + "-1765.9\n", + "-1766.9\n", + "-1767.9\n", + "-1768.9\n", + "-1769.9\n", + "-1770.9\n", + "-1771.9\n", + "-1772.9\n", + "-1773.9\n", + "-1774.9\n", + "-1775.9\n", + "-1776.9\n", + "-1777.9\n", + "-1778.9\n", + "-1779.9\n", + "-1780.9\n", + "-1781.9\n", + "-1782.9\n", + "-1783.9\n", + "-1784.9\n", + "-1785.9\n", + "-1786.9\n", + "-1787.9\n", + "-1788.9\n", + "-1789.9\n", + "-1790.9\n", + "-1791.9\n", + "-1792.9\n", + "-1793.9\n", + "-1794.9\n", + "-1795.9\n", + "-1796.9\n", + "-1797.9\n", + "-1798.9\n", + "-1799.9\n", + "-1800.9\n", + "-1801.9\n", + "-1802.9\n", + "-1803.9\n", + "-1804.9\n", + "-1805.9\n", + "-1806.9\n", + "-1807.9\n", + "-1808.9\n", + "-1809.9\n", + "-1810.9\n", + "-1811.9\n", + "-1812.9\n", + "-1813.9\n", + "-1814.9\n", + "-1815.9\n", + "-1816.9\n", + "-1817.9\n", + "-1818.9\n", + "-1819.9\n", + "-1820.9\n", + "-1821.9\n", + "-1822.9\n", + "-1823.9\n", + "-1824.9\n", + "-1825.9\n", + "-1826.9\n", + "-1827.9\n", + "-1828.9\n", + "-1829.9\n", + "-1830.9\n", + "-1831.9\n", + "-1832.9\n", + "-1833.9\n", + "-1834.9\n", + "-1835.9\n", + "-1836.9\n", + "-1837.9\n", + "-1838.9\n", + "-1839.9\n", + "-1840.9\n", + "-1841.9\n", + "-1842.9\n", + "-1843.9\n", + "-1844.9\n", + "-1845.9\n", + "-1846.9\n", + "-1847.9\n", + "-1848.9\n", + "-1849.9\n", + "-1850.9\n", + "-1851.9\n", + "-1852.9\n", + "-1853.9\n", + "-1854.9\n", + "-1855.9\n", + "-1856.9\n", + "-1857.9\n", + "-1858.9\n", + "-1859.9\n", + "-1860.9\n", + "-1861.9\n", + "-1862.9\n", + "-1863.9\n", + "-1864.9\n", + "-1865.9\n", + "-1866.9\n", + "-1867.9\n", + "-1868.9\n", + "-1869.9\n", + "-1870.9\n", + "-1871.9\n", + "-1872.9\n", + "-1873.9\n", + "-1874.9\n", + "-1875.9\n", + "-1876.9\n", + "-1877.9\n", + "-1878.9\n", + "-1879.9\n", + "-1880.9\n", + "-1881.9\n", + "-1882.9\n", + "-1883.9\n", + "-1884.9\n", + "-1885.9\n", + "-1886.9\n", + "-1887.9\n", + "-1888.9\n", + "-1889.9\n", + "-1890.9\n", + "-1891.9\n", + "-1892.9\n", + "-1893.9\n", + "-1894.9\n", + "-1895.9\n", + "-1896.9\n", + "-1897.9\n", + "-1898.9\n", + "-1899.9\n", + "-1900.9\n", + "-1901.9\n", + "-1902.9\n", + "-1903.9\n", + "-1904.9\n", + "-1905.9\n", + "-1906.9\n", + "-1907.9\n", + "-1908.9\n", + "-1909.9\n", + "-1910.9\n", + "-1911.9\n", + "-1912.9\n", + "-1913.9\n", + "-1914.9\n", + "-1915.9\n", + "-1916.9\n", + "-1917.9\n", + "-1918.9\n", + "-1919.9\n", + "-1920.9\n", + "-1921.9\n", + "-1922.9\n", + "-1923.9\n", + "-1924.9\n", + "-1925.9\n", + "-1926.9\n", + "-1927.9\n", + "-1928.9\n", + "-1929.9\n", + "-1930.9\n", + "-1931.9\n", + "-1932.9\n", + "-1933.9\n", + "-1934.9\n", + "-1935.9\n", + "-1936.9\n", + "-1937.9\n", + "-1938.9\n", + "-1939.9\n", + "-1940.9\n", + "-1941.9\n", + "-1942.9\n", + "-1943.9\n", + "-1944.9\n", + "-1945.9\n", + "-1946.9\n", + "-1947.9\n", + "-1948.9\n", + "-1949.9\n", + "-1950.9\n", + "-1951.9\n", + "-1952.9\n", + "-1953.9\n", + "-1954.9\n", + "-1955.9\n", + "-1956.9\n", + "-1957.9\n", + "-1958.9\n", + "-1959.9\n", + "-1960.9\n", + "-1961.9\n", + "-1962.9\n", + "-1963.9\n", + "-1964.9\n", + "-1965.9\n", + "-1966.9\n", + "-1967.9\n", + "-1968.9\n", + "-1969.9\n", + "-1970.9\n", + "-1971.9\n", + "-1972.9\n", + "-1973.9\n", + "-1974.9\n", + "-1975.9\n", + "-1976.9\n", + "-1977.9\n", + "-1978.9\n", + "-1979.9\n", + "-1980.9\n", + "-1981.9\n", + "-1982.9\n", + "-1983.9\n", + "-1984.9\n", + "-1985.9\n", + "-1986.9\n", + "-1987.9\n", + "-1988.9\n", + "-1989.9\n", + "-1990.9\n", + "-1991.9\n", + "-1992.9\n", + "-1993.9\n", + "-1994.9\n", + "-1995.9\n", + "-1996.9\n", + "-1997.9\n", + "-1998.9\n", + "-1999.9\n", + "-2000.9\n", + "-2001.9\n", + "-2002.9\n", + "-2003.9\n", + "-2004.9\n", + "-2005.9\n", + "-2006.9\n", + "-2007.9\n", + "-2008.9\n", + "-2009.9\n", + "-2010.9\n", + "-2011.9\n", + "-2012.9\n", + "-2013.9\n", + "-2014.9\n", + "-2015.9\n", + "-2016.9\n", + "-2017.9\n", + "-2018.9\n", + "-2019.9\n", + "-2020.9\n", + "-2021.9\n", + "-2022.9\n", + "-2023.9\n", + "-2024.9\n", + "-2025.9\n", + "-2026.9\n", + "-2027.9\n", + "-2028.9\n", + "-2029.9\n", + "-2030.9\n", + "-2031.9\n", + "-2032.9\n", + "-2033.9\n", + "-2034.9\n", + "-2035.9\n", + "-2036.9\n", + "-2037.9\n", + "-2038.9\n", + "-2039.9\n", + "-2040.9\n", + "-2041.9\n", + "-2042.9\n", + "-2043.9\n", + "-2044.9\n", + "-2045.9\n", + "-2046.9\n", + "-2047.9\n", + "-2048.9\n", + "-2049.9\n", + "-2050.9\n", + "-2051.9\n", + "-2052.9\n", + "-2053.9\n", + "-2054.9\n", + "-2055.9\n", + "-2056.9\n", + "-2057.9\n", + "-2058.9\n", + "-2059.9\n", + "-2060.9\n", + "-2061.9\n", + "-2062.9\n", + "-2063.9\n", + "-2064.9\n", + "-2065.9\n", + "-2066.9\n", + "-2067.9\n", + "-2068.9\n", + "-2069.9\n", + "-2070.9\n", + "-2071.9\n", + "-2072.9\n", + "-2073.9\n", + "-2074.9\n", + "-2075.9\n", + "-2076.9\n", + "-2077.9\n", + "-2078.9\n", + "-2079.9\n", + "-2080.9\n", + "-2081.9\n", + "-2082.9\n", + "-2083.9\n", + "-2084.9\n", + "-2085.9\n", + "-2086.9\n", + "-2087.9\n", + "-2088.9\n", + "-2089.9\n", + "-2090.9\n", + "-2091.9\n", + "-2092.9\n", + "-2093.9\n", + "-2094.9\n", + "-2095.9\n", + "-2096.9\n", + "-2097.9\n", + "-2098.9\n", + "-2099.9\n", + "-2100.9\n", + "-2101.9\n", + "-2102.9\n", + "-2103.9\n", + "-2104.9\n", + "-2105.9\n", + "-2106.9\n", + "-2107.9\n", + "-2108.9\n", + "-2109.9\n", + "-2110.9\n", + "-2111.9\n", + "-2112.9\n", + "-2113.9\n", + "-2114.9\n", + "-2115.9\n", + "-2116.9\n", + "-2117.9\n", + "-2118.9\n", + "-2119.9\n", + "-2120.9\n", + "-2121.9\n", + "-2122.9\n", + "-2123.9\n", + "-2124.9\n", + "-2125.9\n", + "-2126.9\n", + "-2127.9\n", + "-2128.9\n", + "-2129.9\n", + "-2130.9\n", + "-2131.9\n", + "-2132.9\n", + "-2133.9\n", + "-2134.9\n", + "-2135.9\n", + "-2136.9\n", + "-2137.9\n", + "-2138.9\n", + "-2139.9\n", + "-2140.9\n", + "-2141.9\n", + "-2142.9\n", + "-2143.9\n", + "-2144.9\n", + "-2145.9\n", + "-2146.9\n", + "-2147.9\n", + "-2148.9\n", + "-2149.9\n", + "-2150.9\n", + "-2151.9\n", + "-2152.9\n", + "-2153.9\n", + "-2154.9\n", + "-2155.9\n", + "-2156.9\n", + "-2157.9\n", + "-2158.9\n", + "-2159.9\n", + "-2160.9\n", + "-2161.9\n", + "-2162.9\n", + "-2163.9\n", + "-2164.9\n", + "-2165.9\n", + "-2166.9\n", + "-2167.9\n", + "-2168.9\n", + "-2169.9\n", + "-2170.9\n", + "-2171.9\n", + "-2172.9\n", + "-2173.9\n", + "-2174.9\n", + "-2175.9\n", + "-2176.9\n", + "-2177.9\n", + "-2178.9\n", + "-2179.9\n", + "-2180.9\n", + "-2181.9\n", + "-2182.9\n", + "-2183.9\n", + "-2184.9\n", + "-2185.9\n", + "-2186.9\n", + "-2187.9\n", + "-2188.9\n", + "-2189.9\n", + "-2190.9\n", + "-2191.9\n", + "-2192.9\n", + "-2193.9\n", + "-2194.9\n", + "-2195.9\n", + "-2196.9\n", + "-2197.9\n", + "-2198.9\n", + "-2199.9\n", + "-2200.9\n", + "-2201.9\n", + "-2202.9\n", + "-2203.9\n", + "-2204.9\n", + "-2205.9\n", + "-2206.9\n", + "-2207.9\n", + "-2208.9\n", + "-2209.9\n", + "-2210.9\n", + "-2211.9\n", + "-2212.9\n", + "-2213.9\n", + "-2214.9\n", + "-2215.9\n", + "-2216.9\n", + "-2217.9\n", + "-2218.9\n", + "-2219.9\n", + "-2220.9\n", + "-2221.9\n", + "-2222.9\n", + "-2223.9\n", + "-2224.9\n", + "-2225.9\n", + "-2226.9\n", + "-2227.9\n", + "-2228.9\n", + "-2229.9\n", + "-2230.9\n", + "-2231.9\n", + "-2232.9\n", + "-2233.9\n", + "-2234.9\n", + "-2235.9\n", + "-2236.9\n", + "-2237.9\n", + "-2238.9\n", + "-2239.9\n", + "-2240.9\n", + "-2241.9\n", + "-2242.9\n", + "-2243.9\n", + "-2244.9\n", + "-2245.9\n", + "-2246.9\n", + "-2247.9\n", + "-2248.9\n", + "-2249.9\n", + "-2250.9\n", + "-2251.9\n", + "-2252.9\n", + "-2253.9\n", + "-2254.9\n", + "-2255.9\n", + "-2256.9\n", + "-2257.9\n", + "-2258.9\n", + "-2259.9\n", + "-2260.9\n", + "-2261.9\n", + "-2262.9\n", + "-2263.9\n", + "-2264.9\n", + "-2265.9\n", + "-2266.9\n", + "-2267.9\n", + "-2268.9\n", + "-2269.9\n", + "-2270.9\n", + "-2271.9\n", + "-2272.9\n", + "-2273.9\n", + "-2274.9\n", + "-2275.9\n", + "-2276.9\n", + "-2277.9\n", + "-2278.9\n", + "-2279.9\n", + "-2280.9\n", + "-2281.9\n", + "-2282.9\n", + "-2283.9\n", + "-2284.9\n", + "-2285.9\n", + "-2286.9\n", + "-2287.9\n", + "-2288.9\n", + "-2289.9\n", + "-2290.9\n", + "-2291.9\n", + "-2292.9\n", + "-2293.9\n", + "-2294.9\n", + "-2295.9\n", + "-2296.9\n", + "-2297.9\n", + "-2298.9\n", + "-2299.9\n", + "-2300.9\n", + "-2301.9\n", + "-2302.9\n", + "-2303.9\n", + "-2304.9\n", + "-2305.9\n", + "-2306.9\n", + "-2307.9\n", + "-2308.9\n", + "-2309.9\n", + "-2310.9\n", + "-2311.9\n", + "-2312.9\n", + "-2313.9\n", + "-2314.9\n", + "-2315.9\n", + "-2316.9\n", + "-2317.9\n", + "-2318.9\n", + "-2319.9\n", + "-2320.9\n", + "-2321.9\n", + "-2322.9\n", + "-2323.9\n", + "-2324.9\n", + "-2325.9\n", + "-2326.9\n", + "-2327.9\n", + "-2328.9\n", + "-2329.9\n", + "-2330.9\n", + "-2331.9\n", + "-2332.9\n", + "-2333.9\n", + "-2334.9\n", + "-2335.9\n", + "-2336.9\n", + "-2337.9\n", + "-2338.9\n", + "-2339.9\n", + "-2340.9\n", + "-2341.9\n", + "-2342.9\n", + "-2343.9\n", + "-2344.9\n", + "-2345.9\n", + "-2346.9\n", + "-2347.9\n", + "-2348.9\n", + "-2349.9\n", + "-2350.9\n", + "-2351.9\n", + "-2352.9\n", + "-2353.9\n", + "-2354.9\n", + "-2355.9\n", + "-2356.9\n", + "-2357.9\n", + "-2358.9\n", + "-2359.9\n", + "-2360.9\n", + "-2361.9\n", + "-2362.9\n", + "-2363.9\n", + "-2364.9\n", + "-2365.9\n", + "-2366.9\n", + "-2367.9\n", + "-2368.9\n", + "-2369.9\n", + "-2370.9\n", + "-2371.9\n", + "-2372.9\n", + "-2373.9\n", + "-2374.9\n", + "-2375.9\n", + "-2376.9\n", + "-2377.9\n", + "-2378.9\n", + "-2379.9\n", + "-2380.9\n", + "-2381.9\n", + "-2382.9\n", + "-2383.9\n", + "-2384.9\n", + "-2385.9\n", + "-2386.9\n", + "-2387.9\n", + "-2388.9\n", + "-2389.9\n", + "-2390.9\n", + "-2391.9\n", + "-2392.9\n", + "-2393.9\n", + "-2394.9\n", + "-2395.9\n", + "-2396.9\n", + "-2397.9\n", + "-2398.9\n", + "-2399.9\n", + "-2400.9\n", + "-2401.9\n", + "-2402.9\n", + "-2403.9\n", + "-2404.9\n", + "-2405.9\n", + "-2406.9\n", + "-2407.9\n", + "-2408.9\n", + "-2409.9\n", + "-2410.9\n", + "-2411.9\n", + "-2412.9\n", + "-2413.9\n", + "-2414.9\n", + "-2415.9\n", + "-2416.9\n", + "-2417.9\n", + "-2418.9\n", + "-2419.9\n", + "-2420.9\n", + "-2421.9\n", + "-2422.9\n", + "-2423.9\n", + "-2424.9\n", + "-2425.9\n", + "-2426.9\n", + "-2427.9\n", + "-2428.9\n", + "-2429.9\n", + "-2430.9\n", + "-2431.9\n", + "-2432.9\n", + "-2433.9\n", + "-2434.9\n", + "-2435.9\n", + "-2436.9\n", + "-2437.9\n", + "-2438.9\n", + "-2439.9\n", + "-2440.9\n", + "-2441.9\n", + "-2442.9\n", + "-2443.9\n", + "-2444.9\n", + "-2445.9\n", + "-2446.9\n", + "-2447.9\n", + "-2448.9\n", + "-2449.9\n", + "-2450.9\n", + "-2451.9\n", + "-2452.9\n", + "-2453.9\n", + "-2454.9\n", + "-2455.9\n", + "-2456.9\n", + "-2457.9\n", + "-2458.9\n", + "-2459.9\n", + "-2460.9\n", + "-2461.9\n", + "-2462.9\n", + "-2463.9\n", + "-2464.9\n", + "-2465.9\n", + "-2466.9\n", + "-2467.9\n", + "-2468.9\n", + "-2469.9\n", + "-2470.9\n", + "-2471.9\n", + "-2472.9\n", + "-2473.9\n", + "-2474.9\n", + "-2475.9\n", + "-2476.9\n", + "-2477.9\n", + "-2478.9\n", + "-2479.9\n", + "-2480.9\n", + "-2481.9\n", + "-2482.9\n", + "-2483.9\n", + "-2484.9\n", + "-2485.9\n", + "-2486.9\n", + "-2487.9\n", + "-2488.9\n", + "-2489.9\n", + "-2490.9\n", + "-2491.9\n", + "-2492.9\n", + "-2493.9\n", + "-2494.9\n", + "-2495.9\n", + "-2496.9\n", + "-2497.9\n", + "-2498.9\n", + "-2499.9\n", + "-2500.9\n", + "-2501.9\n", + "-2502.9\n", + "-2503.9\n", + "-2504.9\n", + "-2505.9\n", + "-2506.9\n", + "-2507.9\n", + "-2508.9\n", + "-2509.9\n", + "-2510.9\n", + "-2511.9\n", + "-2512.9\n", + "-2513.9\n", + "-2514.9\n", + "-2515.9\n", + "-2516.9\n", + "-2517.9\n", + "-2518.9\n", + "-2519.9\n", + "-2520.9\n", + "-2521.9\n", + "-2522.9\n", + "-2523.9\n", + "-2524.9\n", + "-2525.9\n", + "-2526.9\n", + "-2527.9\n", + "-2528.9\n", + "-2529.9\n", + "-2530.9\n", + "-2531.9\n", + "-2532.9\n", + "-2533.9\n", + "-2534.9\n", + "-2535.9\n", + "-2536.9\n", + "-2537.9\n", + "-2538.9\n", + "-2539.9\n", + "-2540.9\n", + "-2541.9\n", + "-2542.9\n", + "-2543.9\n", + "-2544.9\n", + "-2545.9\n", + "-2546.9\n", + "-2547.9\n", + "-2548.9\n", + "-2549.9\n", + "-2550.9\n", + "-2551.9\n", + "-2552.9\n", + "-2553.9\n", + "-2554.9\n", + "-2555.9\n", + "-2556.9\n", + "-2557.9\n", + "-2558.9\n", + "-2559.9\n", + "-2560.9\n", + "-2561.9\n", + "-2562.9\n", + "-2563.9\n", + "-2564.9\n", + "-2565.9\n", + "-2566.9\n", + "-2567.9\n", + "-2568.9\n", + "-2569.9\n", + "-2570.9\n", + "-2571.9\n", + "-2572.9\n", + "-2573.9\n", + "-2574.9\n", + "-2575.9\n", + "-2576.9\n", + "-2577.9\n", + "-2578.9\n", + "-2579.9\n", + "-2580.9\n", + "-2581.9\n", + "-2582.9\n", + "-2583.9\n", + "-2584.9\n", + "-2585.9\n", + "-2586.9\n", + "-2587.9\n", + "-2588.9\n", + "-2589.9\n", + "-2590.9\n", + "-2591.9\n", + "-2592.9\n", + "-2593.9\n", + "-2594.9\n", + "-2595.9\n", + "-2596.9\n", + "-2597.9\n", + "-2598.9\n", + "-2599.9\n", + "-2600.9\n", + "-2601.9\n", + "-2602.9\n", + "-2603.9\n", + "-2604.9\n", + "-2605.9\n", + "-2606.9\n", + "-2607.9\n", + "-2608.9\n", + "-2609.9\n", + "-2610.9\n", + "-2611.9\n", + "-2612.9\n", + "-2613.9\n", + "-2614.9\n", + "-2615.9\n", + "-2616.9\n", + "-2617.9\n", + "-2618.9\n", + "-2619.9\n", + "-2620.9\n", + "-2621.9\n", + "-2622.9\n", + "-2623.9\n", + "-2624.9\n", + "-2625.9\n", + "-2626.9\n", + "-2627.9\n", + "-2628.9\n", + "-2629.9\n", + "-2630.9\n", + "-2631.9\n", + "-2632.9\n", + "-2633.9\n", + "-2634.9\n", + "-2635.9\n", + "-2636.9\n", + "-2637.9\n", + "-2638.9\n", + "-2639.9\n", + "-2640.9\n", + "-2641.9\n", + "-2642.9\n", + "-2643.9\n", + "-2644.9\n", + "-2645.9\n", + "-2646.9\n", + "-2647.9\n", + "-2648.9\n", + "-2649.9\n", + "-2650.9\n", + "-2651.9\n", + "-2652.9\n", + "-2653.9\n", + "-2654.9\n", + "-2655.9\n", + "-2656.9\n", + "-2657.9\n", + "-2658.9\n", + "-2659.9\n", + "-2660.9\n", + "-2661.9\n", + "-2662.9\n", + "-2663.9\n", + "-2664.9\n", + "-2665.9\n", + "-2666.9\n", + "-2667.9\n", + "-2668.9\n", + "-2669.9\n", + "-2670.9\n", + "-2671.9\n", + "-2672.9\n", + "-2673.9\n", + "-2674.9\n", + "-2675.9\n", + "-2676.9\n", + "-2677.9\n", + "-2678.9\n", + "-2679.9\n", + "-2680.9\n", + "-2681.9\n", + "-2682.9\n", + "-2683.9\n", + "-2684.9\n", + "-2685.9\n", + "-2686.9\n", + "-2687.9\n", + "-2688.9\n", + "-2689.9\n", + "-2690.9\n", + "-2691.9\n", + "-2692.9\n", + "-2693.9\n", + "-2694.9\n", + "-2695.9\n", + "-2696.9\n", + "-2697.9\n", + "-2698.9\n", + "-2699.9\n", + "-2700.9\n", + "-2701.9\n", + "-2702.9\n", + "-2703.9\n", + "-2704.9\n", + "-2705.9\n", + "-2706.9\n", + "-2707.9\n", + "-2708.9\n", + "-2709.9\n", + "-2710.9\n", + "-2711.9\n", + "-2712.9\n", + "-2713.9\n", + "-2714.9\n", + "-2715.9\n", + "-2716.9\n", + "-2717.9\n", + "-2718.9\n", + "-2719.9\n", + "-2720.9\n", + "-2721.9\n", + "-2722.9\n", + "-2723.9\n", + "-2724.9\n", + "-2725.9\n", + "-2726.9\n", + "-2727.9\n", + "-2728.9\n", + "-2729.9\n", + "-2730.9\n", + "-2731.9\n", + "-2732.9\n", + "-2733.9\n", + "-2734.9\n", + "-2735.9\n", + "-2736.9\n", + "-2737.9\n", + "-2738.9\n", + "-2739.9\n", + "-2740.9\n", + "-2741.9\n", + "-2742.9\n", + "-2743.9\n", + "-2744.9\n", + "-2745.9\n", + "-2746.9\n", + "-2747.9\n", + "-2748.9\n", + "-2749.9\n", + "-2750.9\n", + "-2751.9\n", + "-2752.9\n", + "-2753.9\n", + "-2754.9\n", + "-2755.9\n", + "-2756.9\n", + "-2757.9\n", + "-2758.9\n", + "-2759.9\n", + "-2760.9\n", + "-2761.9\n", + "-2762.9\n", + "-2763.9\n", + "-2764.9\n", + "-2765.9\n", + "-2766.9\n", + "-2767.9\n", + "-2768.9\n", + "-2769.9\n", + "-2770.9\n", + "-2771.9\n", + "-2772.9\n", + "-2773.9\n", + "-2774.9\n", + "-2775.9\n", + "-2776.9\n", + "-2777.9\n", + "-2778.9\n", + "-2779.9\n", + "-2780.9\n", + "-2781.9\n", + "-2782.9\n", + "-2783.9\n", + "-2784.9\n", + "-2785.9\n", + "-2786.9\n", + "-2787.9\n", + "-2788.9\n", + "-2789.9\n", + "-2790.9\n", + "-2791.9\n", + "-2792.9\n", + "-2793.9\n", + "-2794.9\n", + "-2795.9\n", + "-2796.9\n", + "-2797.9\n", + "-2798.9\n", + "-2799.9\n", + "-2800.9\n", + "-2801.9\n", + "-2802.9\n", + "-2803.9\n", + "-2804.9\n", + "-2805.9\n", + "-2806.9\n", + "-2807.9\n", + "-2808.9\n", + "-2809.9\n", + "-2810.9\n", + "-2811.9\n", + "-2812.9\n", + "-2813.9\n", + "-2814.9\n", + "-2815.9\n", + "-2816.9\n", + "-2817.9\n", + "-2818.9\n", + "-2819.9\n", + "-2820.9\n", + "-2821.9\n", + "-2822.9\n", + "-2823.9\n", + "-2824.9\n", + "-2825.9\n", + "-2826.9\n", + "-2827.9\n", + "-2828.9\n", + "-2829.9\n", + "-2830.9\n", + "-2831.9\n", + "-2832.9\n", + "-2833.9\n", + "-2834.9\n", + "-2835.9\n", + "-2836.9\n", + "-2837.9\n", + "-2838.9\n", + "-2839.9\n", + "-2840.9\n", + "-2841.9\n", + "-2842.9\n", + "-2843.9\n", + "-2844.9\n", + "-2845.9\n", + "-2846.9\n", + "-2847.9\n", + "-2848.9\n", + "-2849.9\n", + "-2850.9\n", + "-2851.9\n", + "-2852.9\n", + "-2853.9\n", + "-2854.9\n", + "-2855.9\n", + "-2856.9\n", + "-2857.9\n", + "-2858.9\n", + "-2859.9\n", + "-2860.9\n", + "-2861.9\n", + "-2862.9\n", + "-2863.9\n", + "-2864.9\n", + "-2865.9\n", + "-2866.9\n", + "-2867.9\n", + "-2868.9\n", + "-2869.9\n", + "-2870.9\n", + "-2871.9\n", + "-2872.9\n", + "-2873.9\n", + "-2874.9\n", + "-2875.9\n", + "-2876.9\n", + "-2877.9\n", + "-2878.9\n", + "-2879.9\n", + "-2880.9\n", + "-2881.9\n", + "-2882.9\n", + "-2883.9\n", + "-2884.9\n", + "-2885.9\n", + "-2886.9\n", + "-2887.9\n", + "-2888.9\n", + "-2889.9\n", + "-2890.9\n", + "-2891.9\n", + "-2892.9\n", + "-2893.9\n", + "-2894.9\n", + "-2895.9\n", + "-2896.9\n", + "-2897.9\n", + "-2898.9\n", + "-2899.9\n", + "-2900.9\n", + "-2901.9\n", + "-2902.9\n", + "-2903.9\n", + "-2904.9\n", + "-2905.9\n", + "-2906.9\n", + "-2907.9\n", + "-2908.9\n", + "-2909.9\n", + "-2910.9\n", + "-2911.9\n", + "-2912.9\n", + "-2913.9\n", + "-2914.9\n", + "-2915.9\n", + "-2916.9\n", + "-2917.9\n", + "-2918.9\n", + "-2919.9\n", + "-2920.9\n", + "-2921.9\n", + "-2922.9\n", + "-2923.9\n", + "-2924.9\n", + "-2925.9\n", + "-2926.9\n", + "-2927.9\n", + "-2928.9\n", + "-2929.9\n", + "-2930.9\n", + "-2931.9\n", + "-2932.9\n", + "-2933.9\n", + "-2934.9\n", + "-2935.9\n", + "-2936.9\n", + "-2937.9\n", + "-2938.9\n", + "-2939.9\n", + "-2940.9\n", + "-2941.9\n", + "-2942.9\n", + "-2943.9\n", + "-2944.9\n", + "-2945.9\n", + "-2946.9\n", + "-2947.9\n", + "-2948.9\n", + "-2949.9\n" + ] + }, + { + "ename": "RecursionError", + "evalue": "maximum recursion depth exceeded while calling a Python object", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcountdown\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mcountdown\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mcountdown\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "... last 1 frames repeated, from the frame below ...\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mcountdown\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mcountdown\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded while calling a Python object" + ] + } + ], + "source": [ + "countdown(3.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "In the same way, a `RecursionError` occurs if we call `factorial()` with `3.1` instead of `3`." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "RecursionError", + "evalue": "maximum recursion depth exceeded in comparison", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "... last 1 frames repeated, from the frame below ...\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded in comparison" + ] + } + ], + "source": [ + "factorial(3.1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The infinite recursions could easily be avoided by replacing `n == 0` with `n <= 0` in both functions and thereby **generalizing** them. But even then, calling either `countdown()` or `factorial()` with a non-integer number is *semantically* wrong and therefore we better leave the base cases unchanged.\n", + "\n", + "Errors as above are a symptom of missing **type checking**: By design, Python allows us to pass in not only integers but objects of any type as arguments to the `countdown()` and `factorial()` functions. As long as the arguments \"behave\" like integers, we will not encounter any *runtime* errors. This is the case here as the two example functions only use the `-` and `*` operators internally and in this context a `float` object behaves exactly like an `int` object. So, the functions keep calling themselves until Python decides with a built-in heuristic that the recursion is likely not going to end and aborts the computations with a `RecursionError`. Stricly speaking, this is of course a *runtime* error as well. The missing type checking is 100% intentional and considered a feature of rather than a bug in Python.\n", + "\n", + "Pythonistas often use the term **[duck typing](https://en.wikipedia.org/wiki/Duck_typing)** when refering to the same idea and the colloquial saying goes \"If it walks like a duck and it quacks like a duck, it must be a duck\". For example, we could call `factorial()` with the `float` object `3.0` and the recursion works out fine. So, as long as the `3.0` \"walks\" like a `3` and \"quacks\" like a `3`, it \"must be\" a `3`.\n", + "\n", + "We see a similar behavior when we mix objects of types `int` and `float` with arithmetic operators. For example, `1 + 2.0` works because Python implicitly views the `1` as a `1.0` at runtime and then knows how to do floating-point arithmetic: Here, the `int` \"walks\" and \"quacks\" like a `float`. Strictly speaking, this is yet another example of operator overloading whereas duck typing refers to the same behavior when passing arguments to function calls.\n", + "\n", + "The important lesson is that we must expect our functions to be called with objects of *any* type at runtime, as opposed to the one type we had in mind when we defined the function.\n", + "\n", + "Duck typing is possible because Python is a dynamically typed language. On the contrary, in statically typed languages like C we have to declare (i.e., \"specify\") the data type of every parameter in a function definition. Then, a `RecursionError` as for `countdown(3.1)` or `factorial(3.1)` above could not occur. For example, if we declared the `countdown()` and `factorial()` functions to only accept `int` objects, calling the functions with a `float` argument would immediately fail *syntactically*. As a downside, we would then lose the ability to call `factorial()` with `3.0`, which is *semantically* correct nevertheless.\n", + "\n", + "So, there is no black or white answer as to which of the two language designs is better. Yet, most professional programmers have very strong opinions with respect to duck typing reaching from \"love\" to \"hate\". This is another example as to how programming is a subjective art and not an \"objective\" science. Probably, Python is regarded more beginner friendly as `3` and `3.0` should intuitively be interchangeable." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Type Checking & Input Validation" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "We can use the built-in [isinstance()](https://docs.python.org/3/library/functions.html#isinstance) function to make sure `factorial()` is called with an `int` object passed in. We further **validate the input** by verifying that the integer is non-negative.\n", + "\n", + "Meanwhile, we also see how we can manually raise exceptions with the `raise` [statement](https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement), another way of controlling the flow of execution.\n", + "\n", + "The first two branches in the revised `factorial()` function act as **guardians** ensuring that the code does not produce *unexpected* runtime errors: Errors can certainly be expected when mentioned in the docstring.\n", + "\n", + "Forcing `n` to be an `int` is a very puritan way of handling the issues discussed above. A more relaxed approach could be to also accept a `float` and use its [is_integer()](https://docs.python.org/3/library/stdtypes.html#float.is_integer) method to check if `n` could be casted as an `int`. After all, by being too puritan we can not take advantage of duck typing.\n", + "\n", + "So in essence, we are doing *two* things here. Besides checking for the correct type, we are also enforcing **domain-specific** (i.e., mathematical) rules with respect to the non-negativity of `n`." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " \"\"\"Calculate the factorial of a number.\n", + "\n", + " Args:\n", + " n (int): number to calculate the factorial for; must be positive\n", + "\n", + " Returns:\n", + " factorial (int)\n", + "\n", + " Raises:\n", + " TypeError: if n is not an integer\n", + " ValueError: if n is negative\n", + " \"\"\"\n", + " if not isinstance(n, int):\n", + " raise TypeError(\"Factorial is only defined for integers\")\n", + " elif n < 0:\n", + " raise ValueError(\"Factorial is not defined for negative integers\")\n", + " elif n == 0:\n", + " return 1\n", + " return n * factorial(n - 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The revised `factorial()` function works like the old one." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "3628800" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Instead of running into an infinite recursion, we now receive very specifc error messages." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "Factorial is only defined for integers", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 13\u001b[0m \"\"\"\n\u001b[1;32m 14\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is only defined for integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is not defined for negative integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: Factorial is only defined for integers" + ] + } + ], + "source": [ + "factorial(3.1)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Factorial is not defined for negative integers", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m42\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n)\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is only defined for integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is not defined for negative integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 18\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: Factorial is not defined for negative integers" + ] + } + ], + "source": [ + "factorial(-42)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "### Theory of Computation" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "With everything *officially* introduced so far (i.e., without the introductary example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) that only served as an overview), Python would be what is called **[Turing complete](https://en.wikipedia.org/wiki/Turing_completeness)**. That means that anything that could be formulated as an algorithm could be expressed with all the language features we have seen. Note that, in particular, we have *not* yet formally *introduced* the `for` and `while` statements!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Looping" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### The `while` Statement" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Whereas functions combined with `if` statements suffice to model any type of iteration with a recursion, Python comes with a `while` [statement](https://docs.python.org/3/reference/compound_stmts.html#the-while-statement) that often makes it easier to implement iterative ideas.\n", + "\n", + "It consists of a header line with a boolean expression followed by an indented code block. Before the first and after every execution of the code block, the boolean expression is evaluated and if it is (still) equal to `True`, the code block runs (again). Eventually, some variable referenced in the boolean expression is changed in the code block such that the condition becomes `False`.\n", + "\n", + "If the condition is `False` before the first iteration, the entire code block is *never* executed. As the flow of control keeps **looping** (or **iterating**) back to the beginning of the code block, this concept is also called a `while`-loop and each pass through the loop an **iteration**." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Trivial Example: Countdown (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's rewrite the `countdown()` example in an iterative style. We also build in **input validation** by allowing the function to only be called with strictly positive integers. As any positive integer will hit $0$ at some point in time when iteratively decremented by $1$, `countdown()` is guaranteed to **terminate**. Note also that the base case is now handled at the end of the function, which commonly happens with iterative solutions to problems." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def countdown(n):\n", + " \"\"\"Print a countdown until the party starts.\n", + "\n", + " Args:\n", + " n (int): seconds until the party begins; must be positive\n", + "\n", + " Raises:\n", + " TypeError: if n is not of an integer\n", + " ValueError: if n is not positive\n", + " \"\"\"\n", + " if not isinstance(n, int):\n", + " raise TypeError(\"Can only count down with whole numbers\")\n", + " elif n <= 0:\n", + " raise ValueError(\"n must be stricly positive\")\n", + "\n", + " while n != 0:\n", + " print(n)\n", + " n -= 1\n", + "\n", + " print(\"Happy new Year!\") # = base case" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "2\n", + "1\n", + "Happy new Year!\n" + ] + } + ], + "source": [ + "countdown(3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As [PythonTutor](http://pythontutor.com/visualize.html#code=def%20countdown%28n%29%3A%0A%20%20%20%20if%20not%20isinstance%28n,%20int%29%3A%0A%20%20%20%20%20%20%20%20raise%20TypeError%28%22...%22%29%0A%20%20%20%20elif%20n%20%3C%3D%200%3A%0A%20%20%20%20%20%20%20%20raise%20ValueError%28%22...%22%29%0A%0A%20%20%20%20while%20n%20!%3D%200%3A%0A%20%20%20%20%20%20%20%20print%28n%29%0A%20%20%20%20%20%20%20%20n%20-%3D%201%0A%0A%20%20%20%20print%28%22Happy%20new%20Year!%22%29%0A%0Acountdown%283%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false) shows, there is a subtle but important difference in the way a `while` statement is treated in memory: In short, `while` statements can *not* run into a `RecursionError` as only *one* frame is needed to manage the names. After all, there is only *one* function call to be made. For common day-to-day applications this difference is, however, not important." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### \"Still involved\" Example: [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm) (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Finding the greatest common divisor of two numbers is still not so obvious when using a `while`-loop instead of a recursion.\n", + "\n", + "The iterative implementation of `gcd()` below accepts any two strictly positive integers. As in any iteration through the loop the smaller number is subtracted from the larger one, the two decremented values of `a` and `b` will eventually be equal. Thus, this algorithm is also guaranteed to terminate. If one of the two numbers were negative or $0$ to begin with, `gcd()` would run forever and not even Python could detect this. Try this out by removing the input validation and running the function with negative arguments!" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def gcd(a, b):\n", + " \"\"\"Calculate the greatest common divisor of two numbers.\n", + "\n", + " Args:\n", + " a (int): first number; must be positive\n", + " b (int): second number; must be positive\n", + "\n", + " Returns:\n", + " gcd (int)\n", + "\n", + " Raises:\n", + " TypeError: if a or b are not of an integer type\n", + " ValueError: if a or b are not positive\n", + " \"\"\"\n", + " if not isinstance(a, int) or not isinstance(b, int):\n", + " raise TypeError(\"Greatest common divisor is only defined for two integers\")\n", + " elif a <= 0 or b <= 0:\n", + " raise ValueError(\"a and b must be strictly positive\")\n", + "\n", + " while a != b:\n", + " if a > b:\n", + " a -= b\n", + " else:\n", + " b -= a\n", + "\n", + " return a" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gcd(12, 4)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gcd(2, 7919)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "##### Efficiency of Algorithms (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "We can also see that this implementation is a lot *less* efficient than its recursive counterpart which solves `gcd()` for the same two numbers $112233445566778899$ and $987654321$ within microseconds." + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.76 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit -n 1 -r 1\n", + "gcd(112233445566778899, 987654321)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Infinite Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "As with recursion, we must ensure that the iteration ends. For the above `countdown()` and `gcd()` examples we could \"prove\" (i.e., at least argue in favor) that some pre-defined **termination criterion** will be reached eventually. However, this cannot be done in all cases as the following example shows." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### \"Mystery\" Example: [Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Let's play the following game:\n", + "- think of any positive integer $n$\n", + "- if $n$ is even, the next $n$ is half the old $n$\n", + "- if $n$ is odd, multiply the old $n$ by $3$ and add $1$ to obtain the next $n$\n", + "- repeat these steps until you reach $1$\n", + "\n", + "**Do we always reach the final $1$?**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The function below implements this game. Does it always reach $1$? No one has proven it so far! We include some input validation as before because `collatz()` would definitely not terminate if we called it with a negative number. Further, the Collatz sequence also works for real numbers but then we would have to study fractals (cf., [this](https://en.wikipedia.org/wiki/Collatz_conjecture#Iterating_on_real_or_complex_numbers)). So we restrict our example to integers only." + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def collatz(n):\n", + " \"\"\"Print a Collatz sequence in descending order.\n", + "\n", + " Given a positive integer n, modify it according to these rules:\n", + " - if n is even, the next n is half the previous one\n", + " - if n is odd, the next n is 3 times the previous one plus 1\n", + " - if n is 1, stop the iteration\n", + "\n", + " Args:\n", + " n (int): a positive number to start the Collatz sequence at\n", + "\n", + " Raises:\n", + " TypeError: if n is not of an integer\n", + " ValueError: if n is not positive\n", + " \"\"\"\n", + " if not isinstance(n, int):\n", + " raise TypeError(\"non-integers require some advanced math\")\n", + " elif n <= 0:\n", + " raise ValueError(\"n must be stricly positive\")\n", + "\n", + " while n != 1:\n", + " print(n, end=\" \")\n", + " if n % 2 == 0:\n", + " n //= 2 # //= so that n remains an int\n", + " else:\n", + " n = 3 * n + 1\n", + "\n", + " print(n) # = base case" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Collatz sequences do not necessarily become longer with a larger initial `n`." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1\n" + ] + } + ], + "source": [ + "collatz(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1000 500 250 125 376 188 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167 502 251 754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619 4858 2429 7288 3644 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154 577 1732 866 433 1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1\n" + ] + } + ], + "source": [ + "collatz(1000)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10000 5000 2500 1250 625 1876 938 469 1408 704 352 176 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1\n" + ] + } + ], + "source": [ + "collatz(10000)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100000 50000 25000 12500 6250 3125 9376 4688 2344 1172 586 293 880 440 220 110 55 166 83 250 125 376 188 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167 502 251 754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619 4858 2429 7288 3644 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154 577 1732 866 433 1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1\n" + ] + } + ], + "source": [ + "collatz(100000)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### The `for` Statement" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Recursion and the `while` statement are two sides of the same coin. Disregarding that in the case of recursion Python internally faces some additional burden for managing the stack of frames in memory, both approaches lead to the *same* computational steps in memory. More importantly, we can re-formulate a recursive implementation in an iterative way and vice verca despite one of the two ways often \"feeling\" a lot more natural given a particular problem.\n", + "\n", + "So how does the `for` [statement](https://docs.python.org/3/reference/compound_stmts.html#the-for-statement) we saw in the very first example in this book fit into this picture? It is really a *redundant* language construct to provide a *shorter* and more *convenient* syntax for common applications of the `while` statement. In programming, such additions to a language are called **syntactic sugar**. Sugar makes a cup of tea taste better but we can drink tea without sugar too.\n", + "\n", + "Consider the following `numbers` list. Without the `for` statement, we would have to keep track of a temporary **index variable** `i` to loop over all its elements and also obtain the individual elements with the `[]` operator in each iteration of the loop." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "numbers = [5, 6, 7, 8, 9]" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5 6 7 8 9 " + ] + } + ], + "source": [ + "i = 0\n", + "while i < len(numbers):\n", + " number = numbers[i]\n", + " print(number, end=\" \")\n", + " i += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The `for` statement, on the contrary, makes the actual business logic more apparent by stripping all the boilerplate code away." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5 6 7 8 9 " + ] + } + ], + "source": [ + "for number in numbers:\n", + " print(number, end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "For sequences of integers the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in makes the `for` statement even more convenient: It creates a list-like object of type `range` that generates integers \"on the fly\" and we will look closely at the underlying data types in Chapter 7." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1 2 3 4 " + ] + } + ], + "source": [ + "for number in [0, 1, 2, 3, 4]:\n", + " print(number, end=\" \")" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1 2 3 4 " + ] + } + ], + "source": [ + "for number in range(5):\n", + " print(number, end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's quickly verify that `range(5)` creates an object of type `range`." + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "range" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(range(5))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "[range()](https://docs.python.org/3/library/functions.html#func-range) takes optional `start` and `step` arguments that we can use to customize the sequence of integers even more." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 3 5 7 9 " + ] + } + ], + "source": [ + "for number in [1, 3, 5, 7, 9]:\n", + " print(number, end=\" \")" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 3 5 7 9 " + ] + } + ], + "source": [ + "for number in range(1, 10, 2):\n", + " print(number, end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Containers vs. Iterables" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The important difference between the `list` objects (i.e., `[0, 1, 2, 3, 4]` and `[1, 3, 5, 7, 9]`) and the `range` objects (i.e., `range(5)` and `range(1, 10, 2)`) is that in the former case *six* objects are created in memory, one `list` holding pointers to *five* `int` objects, whereas in the latter case only *one* `range` object exists in memory that **generates** `int` objects as we ask for it.\n", + "\n", + "However, we can iterate over both of them. So a natural question to ask is why Python treats objects of *different* types in the *same* way when used with a `for` statement.\n", + "\n", + "So far, the overarching storyline in this book goes like this: In Python, *everything* is an object. Besides its *identity* and *value*, every object is characterized by belonging to *one* data type that determines how the object behaves and what we can do with it.\n", + "\n", + "Now, just as we classify objects by their types, we also classify these **concrete data types** (e.g., `int`, `float`, or `str`) into **abstract concepts**.\n", + "\n", + "We have actually done this in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) already when we described a `list` object as \"some sort of container that holds [...] pointers to other objects\". So, abstractly speaking, **containers** are any objects that are \"composed\" of other objects and also \"manage\" how these objects are organized. `list` objects, for example, have the property that they model an inherent order associated with its elements. There exist, however, many other container types, many of which do *not* come with an order. So, containers primarily \"contain\" other objects and have *nothing* to do with looping.\n", + "\n", + "On the contrary, the abstract concept of **iterables** is all about looping: Any object that we can loop over is by definition an iterable. So, `range` objects, for example, are iterables taht do *not* contain any other objects. Moreover, looping does *not* have to occur in any particular order although this is the case for both `list` and `range` objects.\n", + "\n", + "Typically, containers are iterable and iterables are containers. Yet, only because these two concepts coincide often, we must not think of them as the same. Chapter 10 will finally give an explanation as to how abstract concepts are implemented and play together.\n", + "\n", + "`list` objects like `first_names` below are iterable containers. They actually implement even more abstract concepts as we will see in Chapter 7." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "first_names = [\"Achim\", \"Berthold\", \"Carl\", \"Diedrich\", \"Eckardt\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The characteristic operator associated with a container type is the `in` operator which checks if a given object evaluates equal to any of the objects in the container. Colloquially, it checks if an object is \"contained\" in the container. This operation is also called **membership testing**." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"Achim\" in first_names" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"Alexander\" in first_names" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This shows the exact workings of the `in` operator: Although `7.0` is *not* in `numbers`, `7.0` evaluates equal to the `7` that is in it, which is why the following expression evaluates to `True`. So, while we could colloquially say that `numbers` \"contains\" `7.0`, it actually does not." + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 59, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "7.0 in numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Similarly, the characteristic operation of an iterable type is that it supports iteration, for example, with a `for`-loop." + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Achim Berthold Carl Diedrich Eckardt " + ] + } + ], + "source": [ + "for name in first_names:\n", + " print(name, end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "If we need to have an index variable in the loop's body, we use the [enumerate()](https://docs.python.org/3/library/functions.html#enumerate) built-in that takes an iterable as its argument and then generates a stream of \"pairs\" consisting of an index variable and an object provided by the iterable. There is *no* need to ever revert back to the `while` statement to loop over an iterable object." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 > Achim 1 > Berthold 2 > Carl 3 > Diedrich 4 > Eckardt " + ] + } + ], + "source": [ + "for i, name in enumerate(first_names):\n", + " print(i, name, sep=\" > \", end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "[enumerate()](https://docs.python.org/3/library/functions.html#enumerate) takes an optional `start` argument." + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 > Achim 2 > Berthold 3 > Carl 4 > Diedrich 5 > Eckardt " + ] + } + ], + "source": [ + "for i, name in enumerate(first_names, start=1):\n", + " print(i, name, sep=\" > \", end=\" \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The [zip()](https://docs.python.org/3/library/functions.html#zip) built-in allows us to combine the elements of two or more iterables in a *pairwise* fashion: It conceptually works like a zipper for a jacket." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "last_names = [\"Müller\", \"Meyer\", \"Mayer\", \"Schmitt\", \"Schmidt\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Achim Müller\n", + "Berthold Meyer\n", + "Carl Mayer\n", + "Diedrich Schmitt\n", + "Eckardt Schmidt\n" + ] + } + ], + "source": [ + "for first_name, last_name in zip(first_names, last_names):\n", + " print(first_name, last_name)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### \"Hard at first Glance\" Example: [Fibonacci Numbers](https://en.wikipedia.org/wiki/Fibonacci_number) (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "In contrast to its recursive counterpart, the iterative `fibonacci()` function below is somewhat harder to read. For example, it is not so obvious as to how many iterations through the `for`-loop we need to make when implementing it. There is an increased risk of making an *off-by-one* error. Moreover, we need to track a `temp` variable along, at least until we have worked through Chapter 7. Do you understand what `temp` does?\n", + "\n", + "However, one advantage of calculating Fibonacci numbers in a **forwards** fashion with a `for` statement is that we could list the entire sequence in ascending order as we calculate the desired number. To show this, we added `print()` statements in `fibonacci()` below.\n", + "\n", + "We do *not* need to store the index variable in the `for`-loop's header line: That is what the underscore \"\\_\" indicates; we \"throw it away\". Also, we do not need to explicitly check if `i` is of type `int` as the [range()](https://docs.python.org/3/library/functions.html#func-range) built-in raises a `TypeError` if used with anything other than an `int`." + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def fibonacci(i):\n", + " \"\"\"Calculate the ith Fibonacci number.\n", + "\n", + " Args:\n", + " i (int): index of the Fibonacci number to calculate\n", + "\n", + " Returns:\n", + " ith_fibonacci (int)\n", + "\n", + " Raises:\n", + " TypeError: if i is not of an integer type\n", + " ValueError: if i is not positive\n", + " \"\"\"\n", + " # no need to check if i is an integer as range() does that\n", + " if i < 0:\n", + " raise ValueError(\"i must be non-negative\")\n", + "\n", + " a = 0\n", + " b = 1\n", + " print(a, b, sep=\" \", end=\" \") # added for didactical purposes\n", + " for _ in range(i - 1): # the index variable is not needed\n", + " temp = a + b\n", + " a = b\n", + " b = temp\n", + " print(b, end=\" \") # added for didactical purposes\n", + "\n", + " return b" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1 1 2 3 5 8 13 21 34 55 89 144 " + ] + }, + { + "data": { + "text/plain": [ + "144" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fibonacci(12) # = 13th number" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "##### Efficiency of Algorithms (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Another more important advantage is that now we can calculate even big Fibonacci numbers *efficiently*." + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 4807526976 7778742049 12586269025 20365011074 32951280099 53316291173 86267571272 139583862445 225851433717 365435296162 591286729879 956722026041 1548008755920 2504730781961 4052739537881 6557470319842 10610209857723 17167680177565 27777890035288 44945570212853 72723460248141 117669030460994 190392490709135 308061521170129 498454011879264 806515533049393 1304969544928657 2111485077978050 3416454622906707 5527939700884757 8944394323791464 14472334024676221 23416728348467685 37889062373143906 61305790721611591 99194853094755497 160500643816367088 259695496911122585 420196140727489673 679891637638612258 1100087778366101931 1779979416004714189 2880067194370816120 4660046610375530309 7540113804746346429 12200160415121876738 19740274219868223167 31940434634990099905 51680708854858323072 83621143489848422977 135301852344706746049 218922995834555169026 " + ] + }, + { + "data": { + "text/plain": [ + "218922995834555169026" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fibonacci(99) # = 100th number" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Easy Example: [Factorial](https://en.wikipedia.org/wiki/Factorial) (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The iterative `factorial()` function is comparable to its recursive counterpart when it comes to readability. One advantage of calculating the factorial in a forwards fashion is that we could track the intermediate `product` as it grows." + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " \"\"\"Calculate the factorial of a number.\n", + "\n", + " Args:\n", + " n (int): number to calculate the factorial for, must be positive\n", + "\n", + " Returns:\n", + " factorial (int)\n", + "\n", + " Raises:\n", + " TypeError: if n is not an integer\n", + " ValueError: if n is negative\n", + " \"\"\"\n", + " if not isinstance(n, int):\n", + " raise TypeError(\"Factorial is only defined for integers\")\n", + " elif n < 0:\n", + " raise ValueError(\"Factorial is not defined for negative integers\")\n", + "\n", + " product = 1 # because 0! = 1\n", + " for i in range(1, n + 1): # loop starts at 1 as 0! is already covered\n", + " product *= i\n", + " print(product, end=\" \") # added for didactical purposes\n", + "\n", + " return product" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 2 6 24 120 720 5040 40320 362880 3628800 " + ] + }, + { + "data": { + "text/plain": [ + "3628800" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "factorial(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### The `break` Statement" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The remainder of this chapter introduces more syntactic sugar. None of the language constructs introduced below are actually needed but contribute to making Python the expressive and easy to read language that it is." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Example: Searching an Iterable" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's say we have a list of numbers and we want to check if the square of at least one of its numbers is above a `threshold` of `100`." + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "numbers = [3, 7, 2, 9, 11, 4, 7, 9, 4, 5]" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "threshold = 100 # is the square of an element in numbers greater than this?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "A first naive implementation could look like this: We loop over *every* element in `numbers` and set an **indicator variable** `is_above` to `True` once we encounter an element satisfying our search condition." + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 7 2 9 11 4 7 9 4 5 => at least one number's square is above 100\n" + ] + } + ], + "source": [ + "is_above = False\n", + "\n", + "for number in numbers:\n", + " print(number, end=\" \") # added for didactical purposes\n", + " if number ** 2 > threshold:\n", + " is_above = True\n", + "\n", + "if is_above:\n", + " print(\"=> at least one number's square is above\", threshold)\n", + "else:\n", + " print(\"=> no number's square is above\", threshold)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This implementation is *inefficient* as even if the *first* number in `numbers` has a square greater than `100`, we loop until the last element, which could take a long time for a big list.\n", + "\n", + "Moreover, we must initialize `is_above` before the `for`-loop and write an `if`-`else`-logic seperate from it to check for the final result. The actual business logic is not clear right away.\n", + "\n", + "Luckily, Python provides a `break` [statement](https://docs.python.org/3/reference/simple_stmts.html#the-break-statement) that let's us stop the `for`-loop in any iteration of the loop. Conceptually, it is yet another means of controlling the flow of execution." + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 7 2 9 11 => at least one number's square is above 100\n" + ] + } + ], + "source": [ + "is_above = False\n", + "\n", + "for number in numbers:\n", + " print(number, end=\" \") # added for didactical purposes\n", + " if number ** 2 > threshold:\n", + " is_above = True\n", + " break\n", + "\n", + "if is_above:\n", + " print(\"=> at least one number's square is above\", threshold)\n", + "else:\n", + " print(\"=> no number's square is above\", threshold)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This is a computational improvement. However, the code can still be split into *three* groups: initialization, the `for`-loop, and some finalizing logic. We would prefer to convey the program's idea in *one* compound statement." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### The `for`-`else` Clause" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "To express the logic in a prettier way, we add an `else`-clause at the end of the `for`-loop. The `else`-branch is only executed if the body in the `for`-branch is *not* stopped with a `break` statement before reaching the last iteration in the loop. The word \"else\" implies a rather unintuitive meaning and it had better been named a `then`-clause. In most scenarios, however, the `else`-clause logically goes together with some `if` statement within the `for`-loop's body.\n", + "\n", + "Overall, the expressive power of our code increases. Not many programming languages support a `for`-`else`-branching, which turns out to be very useful in practice." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### Example: Searching an Iterable (revisited)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 7 2 9 11 => at least one number's square is above 100\n" + ] + } + ], + "source": [ + "for number in numbers:\n", + " print(number, end=\" \") # added for didactical purposes\n", + " if number ** 2 > threshold:\n", + " is_above = True\n", + " break\n", + "else:\n", + " is_above = False\n", + "\n", + "if is_above:\n", + " print(\"=> at least one number's square is above\", threshold)\n", + "else:\n", + " print(\"=> no number's square is above\", threshold)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Lastly, we incorporate the `if`-`else` logic at the end into the `for`-loop and avoid the `is_above` variable alltogether." + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 7 2 9 11 => at least one number's square is above 100\n" + ] + } + ], + "source": [ + "for number in numbers:\n", + " print(number, end=\" \") # added for didactical purposes\n", + " if number ** 2 > threshold:\n", + " print(\"=> at least one number's square is above\", threshold)\n", + " break\n", + "else:\n", + " print(\"=> no number's square is above\", threshold)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Of course, if we set the `threshold` a number's square has to pass higher, for example to `200`, we have to loop through the entire `numbers` list. There is no way to optimize this **[linear search](https://en.wikipedia.org/wiki/Linear_search)**, at least as long as we model the list of numbers with a `list` object. More advanced data types, however, exist that mitigate that downside." + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 7 2 9 11 4 7 9 4 5 => no number's square is above 200\n" + ] + } + ], + "source": [ + "threshold = 200\n", + "\n", + "for number in numbers:\n", + " print(number, end=\" \") # added for didactical purposes\n", + " if number ** 2 > threshold:\n", + " print(\"=> at least one number's square is above\", threshold)\n", + " break\n", + "else:\n", + " print(\"=> no number's square is above\", threshold)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### The `continue` Statement" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Often times, we process some iterable with numeric data, for example, a list of numbers as in the introductory example in [Chapter 1](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) or, more realistically, data from a CSV file with many rows and columns.\n", + "\n", + "Processing numeric data usually comes down to operations that can be grouped into one of the following three categories:\n", + "\n", + "- **mapping**: transform an observation according to some functional relationship $y = f(x)$\n", + "- **filtering**: throw away individual observations (e.g., statistical outliers)\n", + "- **reducing**: collect individual observations into summary statistics\n", + "\n", + "We will study this **map-filter-reduce** paradigm extensively in Chapter 7 after introducing more advanced data types that are needed to work with \"big\" data.\n", + "\n", + "In this section, we focus on *filtering out* some samples within a `for`-loop." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Example: A simple Filter" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Calculate the sum of all even numbers from $1$ through $12$ after squaring them and adding $1$ to the squares:\n", + "\n", + "- **\"all\"** => loop over an iterable\n", + "- **\"even\"** => *filter* out the odd numbers\n", + "- **\"square and add $1$\"** => apply the *map* $y = f(x) = x^2 + 1$\n", + "- **\"sum\"** => *reduce* the remaining and mapped numbers to their sum" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 > 5 4 > 17 6 > 37 8 > 65 10 > 101 12 > 145 " + ] + }, + { + "data": { + "text/plain": [ + "370" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for x in numbers:\n", + " if x % 2 == 0: # only keep even numbers\n", + " y = (x ** 2) + 1\n", + " print(x, y, sep=\" > \", end=\" \") # added for didactical purposes\n", + " total += y\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "The above code is still rather easy to read as it only involves two levels of indentation.\n", + "\n", + "In general, code gets harder to comprehend the more **horizontal space** it occupies. It is commonly considered good practice to grow a program **vertically** rather than horizontally. Code complient with [PEP 8](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) requires us to use *at most* 79 characters in a line!\n", + "\n", + "Consider the next example, whose implementation in code already starts to look \"unbalanced\"." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Example: Nested Filters" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Calculate the sum of every third and even number from $1$ through $12$ after squaring them and adding $1$ to the squares:\n", + "\n", + "- **\"every\"** => loop over an iterable\n", + "- **\"third\"** => *filter* out all numbers except every third\n", + "- **\"even\"** => *filter* out the odd numbers\n", + "- **\"square and add $1$\"** => apply the *map* $y = f(x) = x^2 + 1$\n", + "- **\"sum\"** => *reduce* the remaining and mapped numbers to their sum" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6 > 37 12 > 145 " + ] + }, + { + "data": { + "text/plain": [ + "182" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for i, x in enumerate(numbers, start=1):\n", + " if i % 3 == 0: # only keep every third number\n", + " if x % 2 == 0: # only keep even numbers\n", + " y = (x ** 2) + 1\n", + " print(x, y, sep=\" > \", end=\" \") # added for didactical purposes \n", + " total += y\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "With already three levels of indentation, less horizontal space is available for the actual code. Of course, one could combine the two `if` statements with the logical `and` operator as shown in [Chapter 3](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb). However, then we trade off horizontal space against a more \"complex\" `if` logic and this is not a real improvement.\n", + "\n", + "A Pythonista would instead make use of the `continue` [statement](https://docs.python.org/3/reference/simple_stmts.html#the-continue-statement) that causes a loop to jump right into the next iteration skipping the rest of the code block.\n", + "\n", + "The revised code fragement below occupies more vertical space and less horizontal space. A good trade-off." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "#### Example: Nested Filters (revisited)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6 > 37 12 > 145 " + ] + }, + { + "data": { + "text/plain": [ + "182" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "total = 0\n", + "\n", + "for i, x in enumerate(numbers, start=1):\n", + " if i % 3 != 0: # only keep every third number\n", + " continue\n", + " elif x % 2 != 0: # only keep even numbers\n", + " continue\n", + "\n", + " y = (x ** 2) + 1\n", + " print(x, y, sep=\" > \", end=\" \") # added for didactical purposes \n", + " total += y\n", + "\n", + "total" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This is yet another illustration of why programming is an art. The two preceding code fragments do *exactly* the *same* with *identical* time complexity. However, arguably the latter it a lot easier to read for a human, at least when the business logic grows beyond more than just two nested filters.\n", + "\n", + "The idea behind the `continue` statement is conceptually similar to the early exit pattern we saw in the context of function definitions in [Chapter 2](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb).\n", + "\n", + "The two examples can be modeled in an even better way as we will see in Chapter 7.\n", + "\n", + "Both the `break` and `continue` statements as well as the optional `else`-clause are not only supported within `for`-loops but also `while`-loops." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Indefinite Loops" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Sometimes we find ourselves in situations where we can *not* know ahead of time how often or until which point in time a code block is to be executed." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Example: Guessing a Coin Toss" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's consider a game where we randomly choose a variable to be either \"Heads\" or \"Tails\" and the user of our program has to guess it.\n", + "\n", + "Python provides the built-in [input()](https://docs.python.org/3/library/functions.html#input) function that prints a message to the user, called the **prompt**, and reads in what the user typed in response as a `str` object. We use it to process the user's \"unpredictable\" input to our program (i.e., a user might type in some invalid response). Further, we use the [random()](https://docs.python.org/3/library/random.html#random.random) function in the [random](https://docs.python.org/3/library/random.html) module to model the coin toss.\n", + "\n", + "A popular pattern to approach such **indefinite loops** is to go with a `while True` statement which on its own would cause Python to enter into an infinite loop. Then, once a certain event occurs, we `break` out of the loop.\n", + "\n", + "Let's look at a first naive implementation." + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "import random" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [], + "source": [ + "random.seed(42)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "code_folding": [], + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Guess if the coin comes up as heads or tails: Tails\n", + "Ooops, it was tails\n", + "Guess if the coin comes up as heads or tails: heads\n", + "Yes, it was heads\n" + ] + } + ], + "source": [ + "while True:\n", + " guess = input(\"Guess if the coin comes up as heads or tails: \")\n", + "\n", + " if random.random() < 0.5:\n", + " if guess == \"heads\":\n", + " print(\"Yes, it was heads\")\n", + " break\n", + " else:\n", + " print(\"Ooops, it was heads\")\n", + " else:\n", + " if guess == \"tails\":\n", + " print(\"Yes, it was tails\")\n", + " break\n", + " else:\n", + " print(\"Ooops, it was tails\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "This version has two *severe* aspects where we should improve on:\n", + "\n", + "1. If a user enters something other than \"heads\" or \"tails\", for example, \"Heads\" or \"Tails\", the program keeps running without the user knowing about the mistake!\n", + "2. It intermingles the coin tossing with the comparison against the user's input: Mixing unrelated business logic in the same code fragment makes a program harder to read and maintain in the long run." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "#### Example: Guessing a Coin Toss (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Let's refactor the code and make it *modular* and *comprehendable*.\n", + "\n", + "First, we divide the logic into two functions `get_guess()` and `toss_coin()` that are controlled from within a `while`-loop.\n", + "\n", + "`get_guess()` not only reads in the user's input but also implements a simple input validation pattern in that the [strip()](https://docs.python.org/3/library/stdtypes.html?highlight=__contains__#str.strip) and [lower()](https://docs.python.org/3/library/stdtypes.html?highlight=__contains__#str.lower) methods remove preceeding and trailing whitespace and lower case the input ensuring that the user can spell the input in any possible way (e.g. all upper or lower case). Also, `get_guess()` checks if the user entered one of the two valid options. If so, it returns either `\"heads\"` or `\"tails\"`; if not, it returns `None`." + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def get_guess():\n", + " \"\"\"Process the user's input.\n", + " \n", + " Returns:\n", + " guess (str / NoneType): either \"heads\" or \"tails\"\n", + " if the input can be parsed and None otherwise\n", + " \"\"\"\n", + " guess = input(\"Guess if the coin comes up as heads or tails: \")\n", + " # handle frequent cases of \"misspelled\" user input\n", + " guess = guess.strip().lower()\n", + "\n", + " if guess in [\"heads\", \"tails\"]:\n", + " return guess\n", + " return None" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "`toss_coin()` is a simple function that models a fair coin toss when called with default arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [], + "source": [ + "def toss_coin(p_heads=0.5):\n", + " \"\"\"Simulate the tossing of a coin.\n", + "\n", + " Args:\n", + " p_heads (optional, float): probability that the coin comes up \"heads\";\n", + " defaults to 0.5 resembling a fair coin\n", + "\n", + " Returns:\n", + " side_on_top (str): \"heads\" or \"tails\"\n", + " \"\"\"\n", + " if random.random() < p_heads:\n", + " return \"heads\"\n", + " return \"tails\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Second, we rewrite the `if`-`else`-logic to explictly handle the case where `get_guess()` returns `None`: Whenever the user enters something invalid, a warning is shown, and another try is granted. Observe how we use the `is` operator and not the `==` operator as `None` is a singleton object.\n", + "\n", + "The `while` statement itself takes on the role of **glue code** that only manages how other parts of the program interact with each other." + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [], + "source": [ + "random.seed(42)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Guess if the coin comes up as heads or tails: invalid\n", + "Make sure to enter your guess correctly!\n", + "Guess if the coin comes up as heads or tails: Heads\n", + "Yes, it was heads\n" + ] + } + ], + "source": [ + "while True:\n", + " guess = get_guess()\n", + " result = toss_coin()\n", + "\n", + " if guess is None:\n", + " print(\"Make sure to enter your guess correctly!\")\n", + " elif guess == result:\n", + " print(\"Yes, it was\", result)\n", + " break\n", + " else:\n", + " print(\"Ooops, it was\", result)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Now, our little program's business logic is a lot easier to comprehend. More importantly, we can now easily make changes to the program. For example, we could make the `toss_coin()` function base the tossing on a probability distribution other than the uniform (i.e., replace the [random.random()](https://docs.python.org/3/library/random.html#random.random) function with another one). In general, a modular architecture leads to improved software maintenance." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "## TL;DR" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "**Iteration** is about **running blocks of code repeatedly**.\n", + "\n", + "There are two redundant approaches of achieving that.\n", + "\n", + "First, we can combine functions that call themselves with conditional statements. This concept is known as **recursion** and suffices to control the flow of execution in *every* way we desire. For a beginner, this approach of **backwards** reasoning might not be intuitive but it turns out to be a very useful tool to have in one's toolbox.\n", + "\n", + "Second, the `while` and `for` statements are alternative and potentially more intuitive ways to express iteration as they correspond to a **forwards** reasoning. The `for` statement is **syntactic sugar** that allows to rewrite common occurences of the `while` statement in a concise way. Python provides the `break` and `continue` statements as well as an optional `else`-clause that make working with the `for` and `while` statements even more convenient.\n", + "\n", + "**Iterables** are any **concrete data types** that support being looped over, for example, with the `for` statement. The idea behind iterables is an **abstract concept** that may or may not be implemented by any given concrete data type. For example, both `list` and `range` objects can be looped over. The `list` type is also a **container** as any given `list` objects \"contains\" pointers to other objects in memory. On the contrary, the `range` type does not point to any other objects but rather creates new `int` objects \"on the fly\"." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + }, + "livereveal": { + "auto_select": "code", + "auto_select_fragment": true, + "scroll": true, + "theme": "serif" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "384px" + }, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 2c8ff65f57ea3efa01e327e4c9c14451db9de096 Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 1 Oct 2019 17:50:58 +0200 Subject: [PATCH 4/5] Adjust content overview in README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 951bf75..4561afb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ As such they can be viewed in a plain web browser: - [01 - Elements of a Program](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/01_elements.ipynb) - [02 - Functions & Modularization](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions.ipynb) - [03 - Conditionals & Exceptions](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals.ipynb) +- [04 - Recursion & Looping](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb) However, it is recommended that students **install Python and Jupyter locally** and run the code in the notebooks on their own. From 6385153e38219106efdbaced296f3175d20cc7de Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Tue, 1 Oct 2019 23:21:05 +0200 Subject: [PATCH 5/5] Add review and exercises for notebook 04 --- 04_iteration_review_and_exercises.ipynb | 941 ++++++++++++++++++++++++ static/towers_of_hanoi.gif | Bin 0 -> 197609 bytes 2 files changed, 941 insertions(+) create mode 100644 04_iteration_review_and_exercises.ipynb create mode 100644 static/towers_of_hanoi.gif diff --git a/04_iteration_review_and_exercises.ipynb b/04_iteration_review_and_exercises.ipynb new file mode 100644 index 0000000..0e937b7 --- /dev/null +++ b/04_iteration_review_and_exercises.ipynb @@ -0,0 +1,941 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Chapter 4: Iteration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Content Review" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration.ipynb) of the book. Then work through the fourteen review questions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Essay Questions " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Answer the following questions briefly with *at most* 300 characters per question!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: What is so \"special\" about the number **7919**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Solving a problem with a **recursion** is not only popular in computer science and math. Name some examples from the fields of business or economics where problems are also solved in a **backwards** fashion!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Explain what **duck typing** means! Why can it cause problems? Why it is [not a bug but a feature](https://www.urbandictionary.com/define.php?term=It%27s%20not%20a%20bug%2C%20it%27s%20a%20feature)?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: What is **syntactic sugar**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: Describe in your own words why the **recursive** version of `fibonacci()`, the \"Easy at first Glance\" example in the chapter, is computationally **inefficient**! Why does the **iterative** version of `fibonacci()`, the \"Hard at first Glance\" example, run so much faster?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: What is the conceptual difference between a **container** and a **list**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q7**: What is a good use case for the `for`-loop's optional `else`-clause?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### True / False Questions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Motivate your answer with *one short* sentence!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q8**: When a **recursion** does **not** reach the base case, this is an example of the **early exit** strategy." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9**: Any programming language **without** looping constructs like the `for` or `while` statements is **not** Turing complete." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q10**: A **recursive** formulation is the same as a **circular** one: The terms are **synonyms**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q11**: Formulating a computational problem as a **recursion** results in an **efficient** implementation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q12**: Whereas a **recursion** may accidently result in a **never ending** program, `while`-loops and `for`-loops are guaranteed to **terminate**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q13**: Before writing **any** kind of **loop**, we **always** need to think about a **stopping criterion** ahead of time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q14**: **Container** types such as `list` objects are characterized by their **support** for **being looped over**, for example as in:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python\n", + "for element in container:\n", + " # do something for every element\n", + " ...\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coding Exercises" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Towers of Hanoi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A popular example for a problem that is solved with a recursion art the **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)**.\n", + "\n", + "In its basic version, a tower consisting of, for example, four disks with increasing radii, is placed on the left-most of **three** adjacent spots. In the following, we refer to the number of disks as $n$, so here $n = 4$.\n", + "\n", + "The task is to move the entire tower to the right-most spot whereby **two rules** must be obeyed:\n", + "\n", + "1. Disks can only be moved individually, and\n", + "2. a disk with a larger radius must *never* be placed on a disk with a smaller one.\n", + "\n", + "Although the **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** are a **classic** example, introduced by the mathematician [Édouard Lucas](https://en.wikipedia.org/wiki/%C3%89douard_Lucas) already in 1883, it is still **actively** researched as this scholarly [article](https://www.worldscientific.com/doi/abs/10.1142/S1793830919300017?journalCode=dmaa&) published in January 2019 shows.\n", + "\n", + "Despite being so easy to formulate, the game is quite hard to solve.\n", + "\n", + "Below is an interactive illustration of the solution with the minimal number of moves for $n = 4$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Watch the following video by [MIT](https://www.mit.edu/)'s professor [Richard Larson](https://idss.mit.edu/staff/richard-larson/) for a comprehensive introduction.\n", + "\n", + "The [MIT Blossoms Initative](https://blossoms.mit.edu/) is primarily aimed at high school students and does not have any prerequisites.\n", + "\n", + "The video consists of three segments the last of which is *not* necessary to have watched in order to solve the tasks below. So, watch the video until 37:55." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import YouTubeVideo\n", + "YouTubeVideo(\"UuIneNBbscc\", width=\"60%\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Video Review Questions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.1**: Explain for the $n = 3$ case why it can be solved as a **recursion**!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.2**: How does the number of minimal moves needed to solve a problem with three spots and $n$ disks grow as a function of $n$? How does this relate to the answer to **Q15.1**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.3**: The **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem is of **exponential growth**. What does that mean? What does that imply for large $n$?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.4**: The video introduces the recursive relationship $Sol(4, 1, 3) = Sol(3, 1, 2) ~ \\bigoplus ~ Sol(1, 1, 3) ~ \\bigoplus ~ Sol(3, 2, 3)$. The $\\bigoplus$ is to be interpreted as some sort of \"plus\" operation. How does this \"plus\" operation work? How does this way of expressing the problem relate to the answer to **Q15.1**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Naive Translation to Python" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As most likely the first couple of tries will result in *semantic* errors, it is advisable to have some sort of **visualization tool** for the progam's output: For example, an online version of the game can be found **[here](https://www.mathsisfun.com/games/towerofhanoi.html)**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's first **generalize** the mathematical relationship from above.\n", + "\n", + "While the first number of $Sol(\\cdot)$ is the number of `disks` $n$, the second and third \"numbers\" are actually the **labels** for the three spots. Instead of spots `1`, `2`, and `3` we could also call them `\"left\"`, `\"center\"`, and `\"right\"` in our Python implementation. When \"passed\" to the $Sol(\\cdot)$ \"function\" they take on the role of an `origin` (= $o$) and `destination` (= $d$) pair.\n", + "\n", + "So, the expression $Sol(4, 1, 3)$ is the same as $Sol(4, \\text{\"left\"}, \\text{\"right\"})$ and describes the problem of moving a tower consisting of $n = 4$ disks from `origin` `1` / `\"left\"` to `destination` `3` / `right`. As we have seen in the video, we need some `intermediate` (= $i$) spot." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In summary, the generalized functional relationship can be expressed as:\n", + "\n", + "$Sol(n, o, d) = Sol(n-1, o, i) ~ \\bigoplus ~ Sol(1, o, d) ~ \\bigoplus ~ Sol(n-1, i, d)$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In words, this means that in order to move a tower consisting of $n$ disks from an `origin` $o$ to a `destination` $d$, we three steps must be executed:\n", + "\n", + "1. Move the top most $n - 1$ disks of the tower temporarily from $o$ to $i$ (= sub-problem 1)\n", + "2. Move the remaining and largest disk from $o$ to $d$\n", + "3. Move the the $n - 1$ disks from the temporary spot $i$ to $d$ (= sub-problem 2)\n", + "\n", + "The two sub-problems can be solved via the same recursive logic." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$Sol(\\cdot)$ can be written in Python as a function `sol()` that takes three arguments `disks`, `origin`, and `destination` that mirror $n$, $o$, and $d$.\n", + "\n", + "Assume that all arguments to `sol()` will be `int` objects!\n", + "\n", + "Once completed, `sol()` should print out all the moves in the correct order. With **printing a move**, we simply mean a line like \"1 -> 3\", short for \"Move the top-most disk from spot 1 to spot 3\".\n", + "\n", + "Write your answers to **Q15.5** to **Q15.7** into the subsequent code cell and finalize `sol()`! No need to write a docstring or validate the input here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sol(disks, origin, destination):\n", + "\n", + " # answer to Q15.5\n", + " # ...\n", + "\n", + " # answer to Q15.6\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + " # ...\n", + "\n", + " # answer to Q15.7\n", + " # ...\n", + " # ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.5**: What is the `disks` argument when the function reaches its **base case**? Check for the base case with a simple `if` statement and return from the function using the **early exit** pattern!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.6**: If not in the base case, `sol()` needs to determine the `intermediate` spot given concrete `origin` and `destination` arguments. For example, if called with `origin=1` and `destination=2`, `intermediate` must be `3`.\n", + "\n", + "Add **one** compound `if` statement to `sol()` that has a branch for **every** possible `origin`-`destination` pair that sets a variable `intermediate` to the correct temporary spot. **How many** branches will there be?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.7**: `sol()` needs to call itself **two more times** with the correct 2-pairs chosen from the three available spots `origin`, `intermediate`, and `destination`.\n", + "\n", + "In between the two recursive function calls, write a `print()` statement that prints out from where to where the \"remaining and largest\" disk has to be moved!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.8**: Execute the code cells below and confirm that the printed moves are correct!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol(1, 1, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol(2, 1, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol(3, 1, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol(4, 1, 3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Pythonic Re-Factoring" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The previous `sol()` implementation does the job but the conditional statement needed in unnecessarily tedious. \n", + "\n", + "Let's create a more concise `hanoi()` function that in addition to a positional `disks` argument takes three keyword-only arguments `origin`, `intermediate`, and `destination` with default values `\"left\"`, `\"center\"`, and `\"right\"`.\n", + "\n", + "Write your answers to **Q15.9** and **Q15.10** into the subsequent code cell and finalize `hanoi()`! No need to write a docstring or validate the input here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def hanoi(disks, *, origin=\"left\", intermediate=\"center\", destination=\"right\"):\n", + "\n", + " # answer to Q15.9\n", + " # ...\n", + "\n", + " # answer to Q15.10\n", + " # ...\n", + " # ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.9**: Copy the base case from `sol()`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.10**: Instead of conditional logic, `hanoi()` calls itself **two times** with the **three** arguments `origin`, `intermediate`, and `destination` passed on in a **different** order.\n", + "\n", + "Figure out how the arguments are passed on in the two recursive `hanoi()` calls!\n", + "\n", + "Also, write a `print()` statement analogous to the one in `sol()` in between the two recursive function calls. Is it ok to just copy and paste it?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.11**: Execute the code cells below and confirm that the printed moves are correct!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi(4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We could of course also use **numeric labels** for the three steps like so." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi(3, origin=1, intermediate=2, destination=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Passing a Value \"up\" the Recursion Tree" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's say, we did not know about the **analytical formula** for the number of **minimal moves** given $n$.\n", + "\n", + "In such cases, we could modify a recursive function to return a count value to be passed up the recursion tree.\n", + "\n", + "In fact, this is similar to what we do in the recursive versions of `factorial()` and `fibonacci()` in [Chapter 4](https://github.com/webartifex/intro-to-python/blob/master/04_iteration.ipynb) where we pass up an intermediate result.\n", + "\n", + "Let's create a `hanoi_moves()` function that follows the same internal logic as `hanoi()` but instead of printing out the moves returns the number of steps done so far in the recursion.\n", + "\n", + "Write your answers to **Q15.12** to **Q15.14** into the subsequent code cell and finalize `hanoi_moves()`! No need to write a docstring or validate the input here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def hanoi_moves(disks, *, origin=\"left\", intermediate=\"center\", destination=\"right\"):\n", + "\n", + " # answer to Q15.12\n", + " # ...\n", + "\n", + " moves = ... # <- answer to Q15.13\n", + " moves += hanoi_moves(...) # <- answer to Q15.14 between the ()\n", + " moves += hanoi_moves(...) # <- answer to Q15.14 between the ()\n", + "\n", + " return moves" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.12**: Copy the base case from `hanoi()`! What count should be returned when it is reached?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.13**: Initialize the variable `moves` with an appropriate count! This is the number of moves that corresponds to **one** recursive function call." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.14**: `moves` is updated with the counts passed up from the two recursive calls.\n", + "\n", + "Complete the two recursive function calls with the same arguments as in `hanoi()`!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.15**: Write a `for`-loop that prints out the **minimum number** of moves needed to solve Towers of Hanoi for any number of `disks` from `1` through `20` to confirm your answer to **Q15.2**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Time Complexity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Observe how quickly the `hanoi_moves()` function slows down for increasing `disks` arguments.\n", + "\n", + "With `disks` in the range from `24` through `26` the computation time roughly doubles for each increase of `disks` by 1.\n", + "\n", + "**Q15.16**: Execute the code cells below and see for yourself!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%timeit -n 1 -r 1\n", + "print(\"Number of moves:\", hanoi_moves(24))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%timeit -n 1 -r 1\n", + "print(\"Number of moves:\", hanoi_moves(25))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%timeit -n 1 -r 1\n", + "print(\"Number of moves:\", hanoi_moves(26))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Passing a Value \"down\" the Recursion Tree (Advanced)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above `hanoi()` prints the optimal solution's moves in the correct order but fails to label each move with an order number. This can be build in by passing on one more argument `offset` down the recursion tree. As the logic gets a bit \"involved\", `hanoi_ordered()` below is almost finished.\n", + "\n", + "Write your answers to **Q15.17** and **Q15.18** into the subsequent code cell and finalize `hanoi_ordered()`! No need to write a docstring or validate the input here." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def hanoi_ordered(disks, *, origin=\"left\", intermediate=\"center\", destination=\"right\", offset=None):\n", + "\n", + " # answer to Q15.17\n", + " # ...\n", + "\n", + " total = (2 ** disks - 1)\n", + " half = (2 ** (disks - 1) - 1)\n", + " count = total - half\n", + "\n", + " if offset is not None:\n", + " count += offset\n", + "\n", + " hanoi_ordered(..., offset=offset) # <- answer to Q15.18 between the ()\n", + " # answer to Q15.18\n", + " hanoi_ordered(..., offset=count) # <- answer to Q15.18 between the ()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.17**: Copy the base case from the original `hanoi()`!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.18**: Complete the two recursive function calls with the same arguments as in `hanoi()` or `hanoi_moves()`! Do not change the already filled in `offset` arguments!\n", + "\n", + "Then, copy the `print()` statement from `hanoi()` and adjust it to print out `count` as well!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.19**: Execute the code cells below and confirm that the order numbers are correct!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi_ordered(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi_ordered(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi_ordered(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hanoi_ordered(4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lastly, it is to be mentioned that for problem instances with a small `disks` argument it is easier to collect all the moves first in a list and then add the order number with the [enumerate()](https://docs.python.org/3/library/functions.html#enumerate) built-in." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Open Question" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15.20**: Conducting your own research on the internet (max. 15 minutes), what can you say about generalizing the **[Towers of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi)** problem to a setting with **more than three** landing spots?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/static/towers_of_hanoi.gif b/static/towers_of_hanoi.gif new file mode 100644 index 0000000000000000000000000000000000000000..7ab13d43bcb28bf830b0d864cb72062ed393ec2d GIT binary patch literal 197609 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®usM#|8+M$%bN-%|4p zTAPE8KzH7a)E_RjEJv60-xh2erpC(RpSyP943xOW$CNDekgglgk0SqutjL#G{0X@Q z4}8pr${Y!gMRr4-U<na>-4U>{;=#%KNg>wj6)UOIR)f66fOJeMZd0=;0_Ie{(;eJKbO`NE?sTZH$W?AM4r; znj|H1A|G~zZ=#^uCt%zmg}DX5hhe;qf1Gh;a$Kvw{%|nlush@l`lWg&{oikWheJ3Q z@at@p9TtWEcX{HQ-!Lz9Ok-r2&>5rbhF2y{Zh~SeV<1eEB*Y1JSC_kg98Tj(voMBl zET-e1bEkrHryA&6B4axl`1A3XhV-LBx62bYHQz@W8fce3r9!6pSq7bJz4(efNn##Ao!{rEr6-j3lb}%Zx0vtaYrL_*$JL2Q__o(r(Y`E@IA1t zMN6`TPfqZp;6yq>_+Gh7`(q=z0^^|q-!=~i0}new4nG@I)nCQci;#SQx-MiLEiR=J+KhnHlz{gReo)il}|(g}&dqDTi((03<4 zEHyXz+k5eZs-+P-K1sMt+Rj1`iF6z`q`^X`A9060-70N_yz!;$Fpf;inX;e*=M zSMYgurf-~@Q?9ijRn&nV5)=a<{szYrgM&r>?cG5MFde-P{%h$04?JAqk%^4faLB!X zJMvF=C1m$?g4RQsfjD#=i`-Wd{10vS#IB2Z{79&eo7(j3`j{idT*Oxmy zx_~VOi(Ne6@gj2nLEskCyR)tQtx!18GZb+afY=g#_!p~*fA{Yf;0JIRhgq4P5PP3M zBfxBvki38z1-~P7{ONB&LeoS7+$#JKPV`WAl{Oy8Q*ib?XzMvM(C`7lvlD#6pkLWq zU`q?&|3$~23jMZ%gU?-mGg@?AqYo=~evcMHsD$xWaT@A1fC&AT1M)x>b&O-VX+Qrt zU;PtRK#*jyx)gu>ObDO{zt(ppq{Cg2Ac-8cz@#XADiri>;DzY3!~WHa1T!+c{NXRm zuqQ7sJ8<80N^*_5oYf>e?mVU`IHfHh(6LxeLf*DL`?W`Uo&4-NE$}+q6*`Ez?s2(z z7jzN9e1kPR9ETC$eV)aaxvUPPryR3r$0EU&T6pU}2hymQe$*g9%Akal{&nuvr&t5xep1p<#n9VJrhV#X^6bJx6q!CmWQ_ zTsU&JKkNH1bEfAAGf5wX6p)7FEW?}D(cbzB2EVHo)i=yNq31>>nIOGt6HK8(0%sn$ z`j*R zaa6pMQZj4bk1(XNk$2*Ibh#>M^pD%BM7{M_(35l6>)`Wzz(NWrd$(oo{MRm7wtir8 zz(RQDEQLxx1Z;uCPgNJw+Kg78mUxLTpKMgkGZ_7wg_K!hc{7%zc$lMl0w8w!;-0Sh zQO2Pw0tEM9&f1K9v4ff%Sl_`VP)IM?yC_tEBc*#AKKjjS^B@ zMR`Zin7A%*WN?3B6Mn{tCHlW7?*EM`{rC5H_Wz%_8I)a_>;4N{s|}$FyTeJ@Hlmg5 ztiB?sc&uI-z**%IXrD(zTPN3FB(mvN7Dv4=QHy&>vXN~dQaY3^{$ZzIGLh?Bnt(eo z@a%_;|X$uvv-c-0Kmzn6_Rvo-o15<n+Y4pZ zOaGp?Bp-ik7CaUCgCHqdEoDLfJ8IGA9{Ow*IAR*>Rkt~qh@EjVxzDDD(qp4kuxsYs z&J3lDm{nh_o17?dkLOfvZN$vz=u(CWpqn%n{cID$N6__Fz2U*=N7Y|A>MG!I@rrR` zBEKUh0;`%}hOO2)lNDf_CF74ykt*0JtYGcksaGT4#Jeto&W=r!_cNbtvqdF0lWbNF zCLrb(SoE!PW1=H0oU=d{Y(s6~gM9s`AOOUhnH=V5ufXE&6?b7_Nw4#EDzdoZlFH?l zu?4Bcs5reISSWL49?jY#@x#>)v1b{?_%Ce}L9}gUr7Ch3^*sT~3NbU0ETOUXZuxUr z6xe1zxAjbLr-W9SlUMn>kK*x1)7Sj<;H?nR`?5(EWk8FCt1uitu8%X8X# z)2|LE=Es~~?`ZH|6WRKb*0PAVdhb4V)AykB9Sn0h0gnwu3dZC@Zp zy7);$XvAx+3~5BfQk>w!yPuVqguUXeFdZReQ#5u7=Z*R>zRzecbX=5$`pZGYjKV)P z{GNAGLR6a7u=v7B4lN~iR34*qt<#8jG=EUM+NOH1nb&kFy?BSS(m97)>cz3v^>ua) znx#Z-5`DyJ{ka6@&dby3Tbo++1^A0E2L+-`byY|6j|x`L*E>*W0Q zpU)cy8hz+-^^VAG!a%Iz@|z)}!oR2{7@t#8kBb?)_#2;TjHr>cC&_L^P5jbli~xG> zciRA~Y4zy6g>Us=$=BO|f4^bW_*JdCQ)D~%{Q1giZ;zrBrr}iq19Il6u95QsVWI!$ zxu(0_izZc)_O&q&%9W2juI5;o)SeH%M<0JU8&^?0JWGbTuVtSPdKt@@$9SoxP`kKp zhhsypHpA!-JnTMf^0T#O+FHBxmXI{O+s{i8znbR>7kt0T)_i<2S#R9$GtMj8f34S* z^YqNMxAg`D@FUG7o<`n3M0`Zd7@dPU^pqx$-3w zlf3w;w1Vjr{4(LXbD)3M`Qv6dA^qRt_CJHRa$W82@wB=Uxu3pJIRJ3E zR@o!+>AszSA#~KjI{k6$43Tv()%91akc{pKRJ_578e~V=3w1j-%E5n+Xy=82d>$r| z^)Xb1bg4IHQ{_bFYp5|P_5*hp<{9;ul!xG`RbG;;fC*ep~I2Udi7dC-wLkrpx5b-aDo3#_s6% zNt5A1Oz=$8pA@(byDV=FAvk-GFlrT4IWO~r_AGHD*$jT&BF7})8g6cFeF2eIiqoh~ zfFZUB%9P-*#dWx!GnA;Bv<}}P-ZM8iZH8#MeKorg$&jyj!0LY0>6*Hkxh=FKI6$rr zBgPe1!svNvL^K?xFd6NCx9@+c&>-JIWxpocV(Y8Jdj?^J?;VCp`69nV=6i{I zdq%iPzXW~N-P8+Oz>Y)*r7*88bBYs=sJ*iOjl@6Nrfp1#5x6P@`U3_)oNd8OuTqPs z#`a!_-e}4>1?SgNvLANZDb<`%W=LLh$?EE8g%JOt28HvelPv0FkKZe0)3#UqxR`h! zQbb1C2vmqvoi1{D^@*M)97?yIY}_lv`66sz4Uc$uh~`hF@K~j~z0voq+0?4`Vp0em zi*_NgJHCxVm3E|qc9BB^IQZnbqNb4=eUnnDF`=X0=j^!}pZis&?os4F+xqUm0Mv*p zI~kEz&3>t!si7X@=EUoH)z&uQDMIq*nTlbOGOte96PSvfXY@?hzWZlCff}m7!NioJ_wHSIN!DM*UX~3UciCO+A@aeeVrw2lgW=fo#ZO|v{PwX zlV4J8Y&Uf#4YvF3AC>EIo%tsUI4&41ROJ12)qBrU0A~_$kTIllQ8shkW|x2iznKQ z_!0>g$Q*VfeV=P9aXqYMbLJ-Tcm2kp$%m7053xkK=7Os#hh726^m_0)xN*(%t1#e{ zlMRP~CHDTaD>--sGw`S8aE4GQq(J zA%Xw6dx0}D_SX$v`-m$lEM_^B%Or^IyYht?L86n5v@u08CbB+7;HL^7-H87}Lz>cl z)swC!@wqfvcmSLPzgucXSF5qg(%i43X|ALEU!Z%TY4x-A#c^%Cg%b`!cW?rd-P^DnaOsms&8XhFh$EC zta3AYZ0x;9m(=!NK;y{kRTqQ74e)c6XmB_l9v5@>?%!3<&;AU1%nv>A4dBngQ)?&T z(sw_#B5(S5#t-dHa_OSe->2-8D6B9xcX4Y(HG>t-SgMP*e`+@4S=3ylel`U<1fst! zFnWIIGM&kxQG|b7UCh1e0ciq!Fkr0XDV6Dvd~Nwu2Ge=C`P$C}PaLNt2(UL^S-;;2bHfiH|8Cd)+lqUP_>K7UMD3t*dq1L=q?W7;du8}6 z;xq?KS$Gn0WZt{7th5G%!To++j@kB+NdEl#IDn3Q!f*R==QZZi6{O@$lVQIYA^v99 zXvM~KQ0g&S|)_}nF z$AM?Nwm%4=GFl+3#J~Y+Xi`Qf?&Wo2Fi^YMZ!*L6n}^$+jX(9h_sh1Fb0y#$jL)`y z0Ht#9JpWKpjUQr(*}t7 z%(%qzD6A~F9fRO;BO(DswmpvKiHgv`!1QNe5fN48A-}-d{z9Ss`k`%^G3OY( zj-kk><)N}Pi6mS>>C{p5)bgWy6f@@}J3{c~A+qn8zy#%_dxk(-*CZ;Ha0*1y{cbWw z$v76tIQ$;OObG?_gv<`($jKc|78K75!K*Tet}KuK4Z(B3LIPo0MD)xg210&T$b{SS zm~#NZE!ZD#IMS!Z56(rT7wMkq!SIj6h(yIy{{sIJrUy_0C{(`i+bJWtXJ?UQV?l1f{X z2;G3^jT(=4C^C@Hr_|BA648IkGla8J{AmNF5k&q$gw4vKFST+b>@#J9{JO6KzY!&Z z^xc9C!U#mOydqx1LP_#i;Iyvb`>x>1itG}}Y+CHkyd|Fe9hLl5+WZYflG#E&tsy*- zIjXgr1Z5aS;6~If8}T+O#JwWt&sBimb#$6mj1p(2oMGnRaDr@irWeE=z#TN|5u3r8 zMpBYEy#V)XBx!YpPh;?iddT(>`JYtsxrOp+5qLkn!5mWgKeK=ws`;FYMZdhk1adIC z%WUaO3hl&#IH5(JZ_^>-t1D|wo*Z(e5?H;{3Ia$B+x6-u0QCLR1c&S z0R12ty?6ELxoRG$`#_OPg12D zytNfZwVMuAyp{#99)L8iqfG<($W#7;w>ns<`k?WD=z7nfCff&kGmV6jkSFviL3&e~ zfPfm1E=UligP_ujp!6o8cL=?AY0`TaP>>>0rCLCcj)KwzG@JLgJ3Bk`pZ&&{Fv-Bc zb6@v4*C`p!D)_TeNb0SEvc|>>fmF)fvgWwutg9u6xvY9Mb=%b&Z1tF($_kTuv|mk3 zJ&KzECv&nlLNwd37e{AFZ?vlVD-wn}YCVl|+yF#%dxS0mHE8LYN^L(x@~$&1tz$?8 zIB=M?v&Jg6Cc2%v&smia320>!hK(Kb9t$M*)^jgI-SGYcLU66hl2*B#5c?eA(Q?r{ zWaa`-Fah+~eCW#183K`WUYgYB+7x{diWMjmp-KH5&170n?^pleKtbmm4F)yeGew&# zwCOB1+}wvhB~y{*1}bh3DUnbW7L? zBbPzNrX9h49m6L6NBb}7trM4lV&;a$^vnIN5;?W;R@OHq7|7ao0g#(SYMb>N zfb5d*-Uc9&`C^KL%7w7olN2OzIE17`fyZGwcYs0<6h-|Y!{i`zvPnneEsXnZekbh< zEV-3L`M>@WooN-_Ok!EK){q4E8&<+lGZD$EheBEnADE6l%>nWi=!ASmB)CCU+MN7} zbaje!!pi`?INebqu&^`AqcjX7j#3p4!|F%--uEVOs5m;Il0@k~b6{pJ&?}0-lI7SO z^4e4Z{hk8wE(hSnGS~nZkA7gv|HH91@ckUkV@a=x1qKx91or8Iv>6z4M(ND@#>78B z4tmx(Mo8ilJbiU1NZH2))voy(xR-+jNpB@H=}#Ja@XKZ~~?T3!q2IiwQ>tJu0c6V(8P~F=GtpnE6yjSwns$ zc~o0mM*=C1ERB~BlfPHU(mg; zkTLE<9S=73?{(qK1NGW0zyk&09R9~cAd{69^N@!U`VY{fs%f4-EgPe&(q z6$}Rd{{|ob^WVG}r@mxHrb2Hb(En}S5DVXiP`Ev~?_K}xZTuxp2c+h`<)ILPJ9qs{ z8@NZ)#BT?~G?Vy;QzTG}?}w$P? zi1Jgl2kN!nMLiC`VbaE{Ur#+}6Q_-7F!%ty!NqtZOXBtvjb@1U^+rC2iBc<`T%Fbi zr;e-vg9m^A$b9{(sQTP}&-7$!I@tN)o-pRuPS(KfZ@%%&MT@N?T+a>e20VBFIS=L{ z@&D`Y!dERk^-9RPDYw6RSt3g}*X!o{<74(Y3*-%fz`qw1=9Qk@tf`_&d$QVHy3A#b zXI4?!L=df9iT1blk1v&wS_{e98q_e`OyRM1%PVG(u-U99$Hqy~o>y86^3|u(?iJj8 zAZ?gfc68k^YK|DnogX$OkRAR($QLN8)7!Q#UZpA*x{a4l6EgPkY%uD|{Gsy&!3zm}%?%wD_8x0F~Hr6a!?(QUxHTimxj2K{UV2=Hrm|zpV=F99A)oreq}Syp7-=)nBd<)rsQfMoE`5{Ldy#RaW3XvkqR5!8lym6VL_5L3(KJ_l|NnL|3{HnQe?$^0G zR&6_Stkt|ZJn?B>bwK!SD(QC($*Bq|T`4twYreuS*M2Cqo89|ab9F}H7t-qe#jWw3 zG3QraQh7c;lj^#d-zRiW^TYERffZZ1a5?Z|w_5pSN~-acQr zsoJTMPdfdPov>vIkxtWddNH9-HQ&)HQ}Vag0j&LLLq%PplvUI3KzVufS&D(C z=ng_+upV6V^AYOFS0x;!YlKt$1zkiC`n~zVG57SDRI9^Icd%E zVNW73idhK5HVN{`8^7+18J$m?O1R2_U%?wQAm%rXuw+RL0A9V_G1M<&K@1X*wpuBr z#ISj)#&-G9aI6ZZNQFp&E4Yfx^rW7BbA#mbTT&Yhp|EpL#_JD~2WS5olZ8ed`37PHOSu&dAQM^`*pS#6bJjC_5i_+`7X z@TzC2ua{Nj4BH3ye3C=HZk3KV4bywF>0@2p%lJ|k5?$keGaol?$R0(Jbf59>=Wbk- zZC1(=Z?H8a;1xBP`!X~LS^Du0-6IuEgU7CrKMwN)>YG2?^#Y=k^OrA5<@z*rDIAjG z7=`$5XHv2`+N6kX#|rT%oJ|sc{VwI~w$&Lho}xda7ffJSy(1!d|7&^5l}GO@?#Z6% zyb$*)9J%Y}F5?gXnz7pMyf zM>N?#C^}Xte|)s9_9kntXUd&O!^!*LZ?K{bKYjMIYZ{L_w}}J4O0vmw?uL32#C2i<2d>lSJVDw+(l;i4VkZjrogSKhr85q0rb|rA6}3L{T^J>iVNu{;5q;U6 z1>z5>k|IuL`x^@ew^%*Xa#+`tMHEa&Mvhyo;%c5BR2Xlsx3oU_Xm9K#JoWUMTO0TA zrbG6%*bt6F-3AYr=hF(Niw-UAoYp@)Zk!vJp2?J4+N<%}kosbrm(EKXOYlW#FCPsW zbkA0cxjZ-dyeo55n|p01K(%AmrddXP#ZDuLQJg3w_ZBoDR2Qi?2}4&|QeY!{p)l@9 zToVf{c>fL4&@#bXBfX_H_vuZqUCZ+A*4TlUf;i$%Ht4I(+myXH7EoOx#f-RJ80hX=ZQ6^a%Ap$>@Rrx%HqQHunUZ3YrR6e03rCCR0 zP9suI-rI^SSwaoqhj7SB1S897_w3kChzI-1SBJTLnxhqET9GH0U%}pD0(5(g zBT48ih1c?`@-dfEA6x zXFlWBQiZ=itjEv49okU#eh`>{VIHTUtqkF8xrX zmQ|=y(_QcCjjr)0vXqjs+;Mh_Jlu}ss!M$w50m{&KUv=Ya|R-u)I3>MO?QRN(&+kT zt(tu;Z&gCS?FF!~+o0)0__a%1%)=oDYZFI1>Q+UcI*V1{h=p^NS+R?7%FfdP*>S#2 z^RxA*H;(jvfK@E6g1{QZ2Z^mWT%LZ~D>=82$v+t)ak5ATMx;E%4wGWev{zs@319wv zXeG@3?j}eou2H$ohu{h%P&@iOY|V4G{61PtgxOtJb@?jbLR0uc%q`IW1h`lZdgMkW zvkcoiLGPy%WMw^p1DG@p+DDE;fl!TrUn4Vfa)jmhcZ<(9UZmw<6&Vyn4~-x|R?=An z>wxbYK|^(DWhDaT1gNl-z$)lj<@Mrp1IpnFKbNJcoAcJT@`LibF4~w=QQmhah6r;L zqU!xAmtm-V5PBkTPdzkr4r=5YN{>O@1RzYkq5tKt_Co~(eW+v{;rx!!LY;3OVV73m zqzN$nN|1>L(=`w#8AJD89Kf-JqDcT)SSHlk?s>9?Z>1qTN)~fO9$c^lE9{3uFcB95 zepH14yv*jJ<%W*y5mkb~?Fk@84yfM@dq^3Mt%F=5<1X=Vrqi(Z22r851g18y{U%0t znc%VsiUlADE9Ae3;7(UdiZnlqkI_o?AXo^OUgFayl;LO)WMu+H&OQpZ#GtWJPmE%k zSsavE98z(y8FsOkPT|}DgTmO~m1Qu$=cCs0m=4M);yi*3NvyH(cXqMTxP*~NI5`}NZ3D=OtQj1# z9eY=U$uxs6F^c47VGhty8i$aN!4VlOV>k@5H*QBTG=VazBQl0%0d{vQg*lU$xcMYt z0!pTNMt@+u#+cumQON~K$X*bw6;fO%c_!>hinX?VRI+$IEI=6wRRU`rAbKYfX@$Zc zm8WoIKJwopJ`xPQ3re~{#!uL!M|G)a?nn|Ap4$f11JX#?G(aL^GKfYdJnct`53*IG zgd8}VU|ie>dI#y*aCA!(k+e}M2^lGv31amYQP?y7u@P131T-TkJX|v=a|qxh8(I%C z_`rVS;>jdAOQ!|;G=T2DC7>Y0ga=p`!~w7+_3Ml*tD&sAt#t2&crpm<#itsP-wdfD z8&a4-m!=JwGa!~sW3 zYDUWNFOlgBnYk|(;_u?A9z;=H7NUtT&fCl^?Dk1ga78Ay1IYkcpqkTVnIkTjPrs6O zQ;OEg5}+6X7Jyv%0fGsizU!SUJX=s7mAJzJ*Sa`c5PY)<6)+-W-E)pwD zfLlGe(MLhrr+^%w=-nXpgTU48A{tCC9{}kEh0hHa%nuje5Dxts75?pdQba}J(L_}2 zej$=jlGRwEtwmSV%Wc#FNZSFc|Bb5yv%N1#*kXhdEg73+OduYUvdA6B;!muF5A3t8 zu}LNi*+*nWOE0CnZ`sYpvK;Q02r!)YARkc=CG8_5h^QT0adbzy)jUYyEd2&`_?PP$ z#zH010EDlgk`@EH(dU!r%OFX~FjhhLPKyaIUx4VVLQNv8M<^Bc;SE@tm}shb>ZI1| z8JCUW(m^kDd%;Y-lrNTFLF-X(v;=1+7$w93m=N%DyJk>{iQNz^e_9f(! zc*^Z9V6&qx^GUsq7RJUBh+k%Z-|-Ts*MM|u5F|O;7svx*=V*l;DbwvLMv0V3`^G?S zl&oKqxI{S(xQT|l5n@%2tWQ)@3f2%|@T8`X>;pjXI522SHf`ACA66jToZzZCClvQof!ziM&(O-T!`hjX{0E;qxKV2T7NNjwWu z*cRCNOxRC@7t3UM-c}_DLr6ey1O%^J3w<9{jA)gnaL2GyhQSZe#4>eWzg2vPKWj%S zQURzC=}Z-2c(nrzEOrc#-T1=;MUo4qS>{NCR($L?kvxgG9XqCt(>K5o^*_d}1 z>M|9iuQOU4Q=84xlgKiP>+aDSgwXdPXjjm*^mGL@Jx)H_Ioa^;B5=<+ddm?oz+=iQ zd#K7YiB{cEFce--dBFaf22)Ny2|4xa9gsj!cJ)qTuJT83>P6<$_;#Kf+3(JE2=E|%pMHB#so*KiUgbCy}u)XH$0IKnf9>iPO;#+9dR zIZ=%pD!G>l9V$XI8@E#7G2to>O+w>QiV`>DDxPm^k)IY_VjbKnbyAGDv>2CWxThPK zQf(+S53$3EEHUJDDbGE#Xx<(EPZ`X6#*NI6!&CjdHoo-VMttGjbroI>p>yl@M;=|V ze*5g*YQn~ zw&cB+qX#2ecQgDvpLIg=Me;wi|54wX5qdO!CA;%ke|&-;X}sLa@7uvNilRu5gBfnhR8?36H%~L@AU^Pv*erK`N?qH zRI`~~(n@3zp4VmlaV-AkCZ4!ieT+}uPnF|H%`tvpbp`h=m@l2_`!}l;t`UP(O{2?d z{K`+^?dh2}2Qt6KsZAYzk9l^leMQY|arly{L<`k}gkVmCr9`#AK8Xc;f1X@2w5K)N zyq&mhxRyXS_=lg!#Ad{!;u+|$^|Z1t>QV{AO%nl~@Mu!2adK75eUYrzM~i$}T{WA; z{E^JIj0EHT8CgtqVSGQt^PNkT>XhJnda3N2JH0ZwZlR$>&3ndIH->k?Q5Kq z`CqM?-T(2;S@XxbaYloYm0W6L^vJ879@Jjs)7XQW7<}(@^51|K^-4eMHio~BtF23t zRn>a1*CO`@{@(p$H2B&f2Qw%~*i9T-nWdH-Zfd5=E}oH5weHR?{PgPmrMdT+Z>SAb z#D@>2{JB1O{n4)Mf1GBVKc3`e*0*=MeK;F7wI zRIJh&Y|6p{bUfb~oRl1!-BcH|tAey1dMfL`=B$n0m?iNaerEd0m}WRMtiwKI-BAWxb=~Q$ir*_~)_KlRz5U?nAdQx^S7686 z=uR_*HO6jQy}oc zHUY-|Coj04ET2QX4QNO*H`gmsM?pMRB9si@PIS z_pv5sJSJ5egBhC`6R)@CSi_85rT(=9UC}#S^qR_?9|mGx8-cmB2Cm zG@7)$1h3yu^raU>?lBFfoJ)OoEggC@H*hCq%kjyvzoC-4X>&GgvpF3(uRnA2qW-7c`;=oQ>!KC^dd) zb2C44D$GJU-Wj@n+$)rr1!u_nvlgrSf=y4LB{7f+yybe9sb(Q~R7zHLd4!(MxCx!^$uaAB(@eQHGqAb@z;BS&Yu1|D!H0F&4hMCrrSpN#BirdX~IrP!sK~M%Y zk%-BbkS6@8nu5U+t&>p*`|RnU?4yGaE)uekYBQ?J#VcmE{L59$N(SxIcXz%t9BTojNSvp%<8(;u zW6EKav!xDA*mPc6$5gYLN3&zx?(rPxqg?PcnCSBErM{NfTpb_gu4PsenXq#wLDj@p zX5Z6}`;V(@-L212e}ARFUbu!Mpm5*lxCn0rWI*U({Kt67(}C|t&YqX;KYZ>rJ=l6{jG65ld>1!QU9=LR1s}&-iMpgp%#; z)k%V;c9Ktc(Nl54hJ##l&E9_2lK&dt=)$mv3@GnfbwOHCwOt z+x+=(c+&xMIC)p27=yCMKW1wSSD{i9S;D@6wtQN?68SafiM#^qjQ5wr(!JP?y9%At zw*-$;I=N|8?yoGKl=t6g2-p+GDsy};kZb}bl6==2MvLi_i|oZvX1cdQkf89c5Mt!a zm-IK6WF(`aP#gTVXJ1J!o{jlBt`zrs7jAEA`V18Ap((*kb>f7#jP)=GunbDW_VQe+ z59QNP1oHsFz|G}g;YglASyBMI)-99Qx9NGKXn%VV z|NQly_MtrU#lmAeZb~7*HH6(Cv`V?<()`!;rsxVNL9Tb;>c7Ys#~V9Fb7$bDA0G8r zxxsa(INHh}hn&z>(Y1f-pB|jiB(=y@IKUb+BM*=n&0g zIIE|I!=P5FD1^&lu|nt8-CJ$zB6z}G4G=$3_3e$D;t={+&RvVv)4AafzHu?;yOm$P z=h2qIm_!at;=6Wco};Scu)i{a5PCalhx+%wnhp|$~Y?|eQR5*W$@ScZJOf*_Lybn#)7 zTp*fgkl(9~z*>ago^7yks|UZG+kUG@w54C0;fvrw&Etr>r~w+kIj_A^G%UkE%r;0a z0;y{W+e>`%+|z!>%NA|tgGhJR@gii)!dWuFIq%SniD1?sh!l?IlD9$EKA68Zczw=y zz07SZBAn@6uvtX-`bn_JeBgeBr+|9MqNEoq7zN>`nwjw9xn|sx;^MFFf8hB%%rHnf zGKjMd!6$C1K`MRnz9n>6%~c=oijO2{r4v|(&=;0rQsU5y5%jbQUu zH|MtSn)2u?^TCdk5xg28s(rAhH}-UcJ`oG-mkLJ~hJXd1Ct*Q2!O$TMZ?OsRQ7@Q& z-$tj!9xWIJLxgF!`eb>B8QX<1_C}c)fxTQ2*IW_$*k~$>@Vdm{SEtc?Ug0}K!OzOW zYsKs+y*?%yI z`ZO1?v_brw5tfq<{xToMEtJNJjVB8`uZcr-W(h(*1`m2+zva?px02j_(!G7srR`%5 zZ7oI!5tIiBf(Ni>jBYNkfAg`+;Cu>7(;L~II4YQWPZKIG4pw)CrDX&xWW*WFM?LmQ z_NkhCDV_5D_RP5*}kSK$EnOCfS$hESCHm zE@_X-)@FNIwqK&>P@%f$mN!yzm+d8!dWqiB zg($Kmlm%Bj6J73j9coYx!h=9m12j@f1%+A_jqNa%vl7^1MUHQUgimdrR&CCr+gVh} zX+?gLJYD4(umE~xC=8r=VYw}VMw5)X7Mix+oWY1f7L!6-YSKf=lgCsRbl$2e4b-zj&fb#j&uuj-F;q+fGUj|24oM_eR zZrA?%&wX246y0>XSdpt$tIF1_>sL~I2K4L$)P6v46dejguZx9?Ss|qlUi8V9N*YE+ zWyHq$fcxdE$fYtj5KJ1|z)J(=69-!WG>SObY-KgM%qKe9z~b5#sX*SMXbkUYln~F_ zwGXS`_v9kL;7XPE?^LQOH0RJXA4j+AXSahyn(sN5l$_P-jh5)FRKgqlpcv4Il4k$u zvpvsxXTMV2sOR=TtD^~;3RN-tpk&`|;9}Q!b~S@`U#W3-d}rF~5W1?a z`=(NlhDgshKWZNB{(IRy{7(HFBK<;6Jz1SS8Gb$bB6M>Tz%M^wZGwS4h$$A2X{Oe# zYw?mWjMZLf8Lz1C>#b)uLF4KWeF_NiM9PBR)^{;b6`*fIzK^l1Ehf8hrlWD4I=U*+ zRY#(kNA!)|ZvSp}zpYu1KwW>XZ_m0&KVMgmgFi&t2~)L0e*=ekw~s!J0qR8PCM^Zk zug6CFJZB?07QW8%r`oL7-S51tfbi*TrNVA`>VJMQSbj0MwKF0t+HCiJuu8k12?Iyyz4>SfTzk*jkcbIE4oQG16J|6Y^}9$5 z^xAEw1VNI>hB{$~T>@gRfw;$iD2|u@5HQ;foZ__z$}{^jnbJxGVX4z5As&F3ve^;|h@? zaZdlZn6jH3g%(aj4@Myev?M2>&mSnp(t*X_LzF1hRtkpQhpx6x#MqaPZ%xQCBQYr0 zYsX2}8(^~RQ>y?*whd#thQ~+Rhgw)~a@>Kw57Eo7+Bhj(5 zow2+bgIWi!UQFtNN=W`!`O!@53L7ISYfT(OiRBO(# zHJvYg1&g*Li}Z)+utdNH3miBvb>=P|=Pn)TOgHLGlR%%ixKV0WD9VG;kv-u3*e3{K zc`QJoP1v8j>h)gnqkit^w(NQo3I)NUgv7WTKYt~OPha}-^&sw@_oo%sKFCc17-a>b zmnrMt!MSsc7LgO?Ofu@IPm|A@c0wk^S5R@K=)D}G*wZOsZqqEptMJob(be%d zCUAwG(#5l%GQHheYjbh2`eGp0TpEjY`ftk^<3u1roVni_v!IIkn*-deUWOJfzqmlV zP0-1^V6|b6)72>|m)4YBzRR7=&LmDTP>6k*co7x|aFO-_K?^2_Wgs9N(4PSAi!W=r z;N>;GgGCqSKW|(YcsdPic8YJFJi$D7mZJ89Rb^s`H84aUG&L`TA~S=4Scwx2y@o)Y z?QgwZUM#x8ed2_Px0K4Cqj#aA|I?*7>6{W*{i<2y>A~^thby3<{jEuI1AiHplCm}; z0jYBZfC>7cWlV=62D%JfB|9o{gS9t}y{>c;53PTG(Y%|whbY?H`2vIo0q^c&2LBkG zd=SC?qGUMOGvJ|sTkS)+DF(jK-Q54Fm50O+Y*RgCV!{F(`xwjZeKwNH_a8u(C4+C< z!3_o^sSf0g{S_SYD>w}yhWRB^JcFu7UJ@$Q7k;YBKs=x?rk3FTeeLV-?C%n1O8^@d z$Xx!d_To?@|4{4U<3+mvn;!n3RYio*?jqp47HVFpcnky5s#Y5zs*^UIof*SU|IPNm8xi!~T6 zM7O1$yeq-$@N=*+3O^uV{rY#Q=$NN7Ij&j+Y%!E;SJTMG=MK5f4i5- z+sSs(?(XvGbr9J0J)2Rrat_m0R$OO`%fdh)n0bJ40W0xNOrnv|gvI*aTSj}fA5{lG zY&!FFeEB%jn(vM!m>X96%kMu)H?w~8lGCKs`m3uFX)U)=@F4D$9<+6jU1lSx(>Rz` z+l=@7)F{QJIXQQQ*|rbQeM#eY10^grzfUvQo?YvDmiFV$;H`6x)i*=&726+cdR~)C zRwYgznn0O`^ny+}`DT4|Su+;Bim$hsT_G!87)&ZMT^GFL(-$sl_A7mIg%5L8`dOSWX_ZY9nlu=}}@<-6rpYk%_ zy_BHqe|SQMl%70FGE$>pPuD$8UwV4P{aw$3E^iAH(_XT!y+Ip77ljI-5Lbam=d%6Vq zFU?d!9v;q&w!iUX0&7yphIm*bq^$3HZ4x0kM%jg2g>R((-6;cFMYuKBZD>H0R;AirB| z-5oHGDPv3MhcmJGf4)_EL)X_!enq2Amui(oxs0FPxjI_a*!TBiRe7|(a;ntWLf-c8 z5AgQN{gItP59tr5d7YEp%$*!FSK=>;X1_k8<=mc=y!E#UXL0NB*E}NAR7O?3SZu$? zwc0%KlLk~xw(LoQs9UZVlw?L65v@cWe6oM-AT!y{WZLBLVq;8v;K|9Jd(A4G_Swwu zjy=!rKy(c|xhRSB{jA^mezMzL>u%-KO7^zvE0PCA#NCosTH@Y4F6)~5TJ})CRrI7w zN_+of3yYtc-#J`{TwY&vDi1to=)N<6zVYL5>&CF!-#T+_E2ay)8X+d}?dlVRI<$|NK-l6j z^DgW-P<@IYYQ(b9c)elycRLYHSbNxHr=)437wMUD$^NW$sLh>DJSlWd;N_;uTMD9Y z{hMzbe`JO4RX%~D}%i9%QSlMx-j@npT)hmgx_!2XYTsk z;q+9?c$tEdPL>=~$aA&r+UG+;sYXKX(=(QC7xLXWRs9wFEZIZ(vK*=YE}=*& z*f6=yV@jt>0x`&OHkS!}|D!^@=Z@nJE59YX&2IP1$rq8rF3CfM`Mm|t5xAzob$dH0 zhjys!%X>!p@vWf(WtEqhmqMz%RQJQAAISV`;?=dyoGF9rm#Dq0d|xUr{3 zt;p@9hXwsruf=zar`blNA6?V1%(XFn7d`c`#-rNl!HzMQ8sEHqRDH|Z-hk9N$klQf z>36haKHXu|v;Cmf|F59s^q)Ir!XIDIJ`%BD@0|OfCevW|ch^=x!MH97o>BVX@gwGQ zqwyMprn- zt8rJ4FOp3%98E)sB=}F*W`U$??F|9S@olQzb|Kb zhTW$DLrxVwGpGNUI{KPxgD5!eE-r%dcKughu)Q)K?2+k(#=E+mH^K;t{k$h2QHZu= zj4!;R*2lxumRod%PPbKjF=!~PngT?CVTBPNJ_H(1eRzA;+aQ_I5 zRoFE!>^fx#8KZ(GP>|7B(1KM^vo~=u92*{s%IJ%WXwo)0{i6|ziOs>y% z*OpAC9_RI!@NsTwtS%#N3kEw8gCpDC|G^-ZH5v%X8y}=Q`DW@wpKEej4k;UaEHqM8 zpw(Fy7g?OJ_dF~bsNS*AU;MOrNe##XE%iqFE+8--s%ttOwqJ*m8oE6LrrAQZgRaj) zGLJAUaXXSbCUc!%u5~c?xL$%O%@g@Jy96NL^{%gQF-Ooy%Xbl36;j_~?(SS!Q$k!1 z&76!PF?qG2dN-fx66T0kWZ&4<1X0f`PCaG`hh3&kj~<21+~o4O7i;C&pnq1eG`!zF-sfs9A-V0p$no2cX#F#0jrLqv`m%meKJei= zoqNb(54KEB^+Dh`5#1E}i%{S7^svu7Sv&j3YoiWn7|wmF)e@5Yp{Kw8%2qlJ?^M;p zHqyLpt@qNL#qmWs4*n#caHL+u9%S697MSn($BQ2{h6_~9a06h1q+7B3=wvL=R{(r` z_i&ftSyvFvWTF=wgXF*>?D?M?mAQ(aJVVO*$(Dhly#g5%1Gi5IGOd9ZxL{Hu_yVAP zq2$ld7feC)yfTD=S-wC|BH!1c&Q8!{1?)zy3<>}76uqTyvLSK;S?A`AcH2M z8d8=X44<2PKolL~pv6r)Wn0C{jT<+zo=ZO1SEsKmx*lc{A|g zFdsk|a0Wvvz>r}JT%D!+Iq$R495jg!1qet^JX(AoCAAU#$<7ZO8EI%2wr3d6l?mQ3 ziWkHsk(Oh~WUpc(K9`UnI+=i2NkUI1i2DHKmV+ee0P%o8CCY8hMu3mHS$GQgs@nl{ z3t(vwG`r5j5)sDH=6yLb&?qvjtu1CxHi`F7Opj3#nXO9Tp=SFiQ6GjYLdon_3D+tB zfyA^2m_)Q2in=hW0fT^Gg08m2YAT_8B+YMM_XQ>)oIr*q6~)ze-gV`~-H0#)yO@jK znAMCJzTs4I8K_4N8ebkSTmbRHgW=+7KY0@RS~0@ji4Z*$$r5!<5O8H>r1*nYY{z*0 zLEl?XR+@~(8JYQo(iF*J)LAp!$h@wOD)wDmbX4$#YtA=~c&u?!Ph0Bi&B)|GF&3KS zWf{mdGOWXeS7pHiP5B_qRKhhpU z)~cBL z3Oqoq*$07Gk$?VDv=Bl%y_+4HkX8N%$guO zB9^`{7oqnO!d>m4i2;_mQcWs2@;MfvFath(~4W9R<9JneQs&zenc63n=2VI49T`X+VtfAPm$CU^l_!$YXNaP-a>_ zd|3>Sg&zlePYg5$?8R%2hb#Sh!IvFj;&@08K%>S)wZ~TVi@F@N+|VZsrWvWZii60I zVhTF6%F)r~%5z*U?OD!4FLM_Q@%3)E1`LY?QHNXgWKR`tqVhimnMlcphqy1(kckPI z1J-wxUEOcqt%O>gzuMKxJ+FkklP~v541|La(`#;|We9u{&eIUfXo?Xv%ww3WU?(IS zHQ)6(MNgliapE=qp-rGcPo$Yo0o+qStrY})h=Xa?mC4YwNQ<;sIyN?DwU`fwWfxGm z6qmE>Ik}$$U-r??t{ogJReDMk6y&ve?oRzO%%U${R?tHvC8e5Csni)vm!>(^v6&u= zs0@OdE;Y;C$<2sqpAmXxcb@t$3v2;Gv_M-a+^XA)U=#-w94lc0B&E&{J!=BY*M}Jy zCQ^KaM}KE)Py?Fpn?fv>DH3D4%nQ0kO&cFNwv3L}K8&iWD4^KJ^{`n%1h`>(CRi~U z>~I0!6IJa_9BRT9{%sK)K?Cz!hQ`o9@9(r7Wp|l7w%eFCj{3FO`ypxzD132BSHNJ( zs!M^{^i(vM<)y}%Lz*^m)Mj?&U6HQm1*PJy&4cXi$)@cMCjEShuk8GCI|>jY+P&KY z-DqwK_yGi=G@!l$RdTCmYz~^3fZ%$2Si0JH6~Oek*F>8BM&Fim-xgul*Hr}+d=oV5 z`@IjXsG?oXRB&wJmT&r+)H|^#X3(H?P~RKVt|Nu^lh?1_N=#7P!_!ptQuDb&WeX5( zIO|>|a5CS3fhFLFWM2LQmju^rHLEYAyb0+-kmp`_I@|aXDP{2u$;i?zeR~L@u%y!cyM1$qpQyS?LKl6j~w4erW0uvQVih@^*$h$p~OqyvKh83 z@&Yf$YF5x5$(;zy`!8Lh%Q+tqZetWiK#LGJ^g70{;KO0n2d%X{iWRa-othu>rppI@ z#4!O00MLpP@G;rh|A%S(PeVht(138{3lb0|2}Gje&`88eJffh#DH17O_=bSu(z;-F zE9#4C6Lt8MQD-&qg7vE8nnu#Mx8dA(k}d?rUus3sJRHfWyBtrJr#pW{y{cKk)MvKVqt#+p?xT`;oC|T9@4k%9if%4-InI**u~}O$4;Ws4 z`q$U_d4XZb$ra8+pSyKa&UCcZ#tjC|57WPr?(b%Mc>a{iw`IEZSJ8WXx56`pbmQsC zr}t6GyVRJczevBk%kup8tkf+79-_QipCD#umwnprN94KP_?tT8Cpxe}?@U=yMt(}k zJK?s`shG`lIn+7L)8z?gc@%Tj?#<=F(ASm}tF<6ljKi>b8ynw9veQpg_^_F$$8Asf zh^YNTz{(3s7qw(|>z>d@HLX0El4u5b-k0f90b9u#ict$C_7t9fjNQYw4)qgMvdG(D zieJij@a;KAHm+X((ig*Mr!p**-SenSp1Uzc7idL8?8=>WuAT7~d1!5CzC>G@B$me9 z@O|kj;j3lmlm9_zyXbD7$rF=|@Dd^N#Tn^voA5YpzBte0+d}fo0JzbLOWTimK_9j; z;pF<#4)POUpS%{(5E3keX}alhwu_5nTC@%IsbnjU?f!S$xja~TBlDHA8e2(bt^un{ z4Z-K!h0HU5C3L69DX>UwfjDfX0Fq=a#AazruCYeuuBL^ z_EX9rg_~3DI}SIbL=`Amf%x)_t}ArW=Q;Q|gY-u_@+t$7jwjdE zv%S~f`CZ;r#nB8ZdP@dxV`?g6`TQs8uWO=@6o+iAbqnihpdsII@ zPPjf%-Fe(}3?t}HAD~saJn_G3cYV(*-*wNfUHy2KNa_MFtHI=YGXe3yTVT$up3Cx$ zj3WVm6)cY_FXO&ms|`dYTY7@pI@gt4@BcKl+=@PFp0%$FVnI$)J@}?{vV13K|9Rx( zBNkkLH9$B#w@_Y7R~lSF2V{#Z5=d)ax3m0RgV*)HEZ9Jr&AXz*dq<6FLiAN4E-rgt zt0?+i+IpLVP1xN?+EV9J*+8>deN6rJ)lF(;mADiMIp^d{yR#X$Wa9PY9T-+|zlMmi z9S2IC3f};tMxW9@XpsNKS08VpM#tW_@Zhyas2xfcvCBze+P{i%yr*h9v?|FkZO$JZ zCvSG8>Ebr7Tl3o%X%U(lf>wCGGrc&W*JWBuz13$eTs{B#%R)n9zy%-WL7IyBluAhd z+Y)kAWi$?1?ZEMAbX|@r#ehvJruWm(HAMTE({V|*-(wrsUp6wXE>oA|q{|BN#L+xT zSLO}D2*puM{4*Bk>~H>>yy=-F6+Qa0XX>g*K zYW6#wXH4*q0XFhx)eKxzr}AF9ynd#OC4;0LOrDWd;m`NUq+3*5hE0{k0;bScRNx)! z3xG29@==xTXVAUOk=e|i|1>mE^}7qxp3hPq#WB2MJr_bNm4Ac>>FhlGs5Rfxe^@6m zpn@%lzRBuKFTK25VewGXxYs+C7xHnN`V5%=;OSXsC$?*XdPSDZJi5Hv81*A(p)-Q_ zS@za_O=}8CQv;H+=hbEk0*c&x`3z}k%{$uFo9>vMykt;uBQZ>D&{m1&$G7&0fFIn2 zqc@3r&nv5|9F1=1o9=ess}d=PJq@7ww45bdSEO@Q-~4|*8Rz!Mr~YnAU(XiPdwz}8 zx>MN7fE-$d<`^8k!c3A!WLCgkI(5NbOQy?dCtU;96>h|(5T=O}>|5_aDaoo8T0glr zEG<|4R~4kS)&W72@4~`|zQ&M{K`7E-KiK-hl#+DR82mt(DF_>9tFroTrXXB8Sn-KH z^7@cQ>0m3DGS3&PLh^rysT`xFriFApa;YqRhP2* zV*f=H({zGGBMYJS6HOA~0R$`d^ZB74houx)DmmTa8LfDDWFd!oe$Drhy7*i!r{z!+ zku$CqxKuIM#in}e;au-snfe6tT@Qh!>C~3rjS>Fa0?BgRwauE&6uEoq&V*T%H?EaY z6o3VFF1H%MYuu_G!+02Jti6>H@)HnG_TtZjgWmPBH7<|eLuOpVWs>#cVp<4$(SJxk zT1V`Qtb_iuuekQ#M&5nyDk4AFP0@;ieRGV`RYd);kR24ebm$eb_~GRxpSxNXdzqGg zH6lL+ihOoL;VK{)Hpr)y=FxsI7ssbBr3c=G$q>oNz72Y`TIXD#TVZSWrV3X}+3Llv zo#Xtt-ngGrOYgD^qO0iAJ`Q$yA}C{=V?{>SwKW%nw8U}j(U*C@`+Uhg9?iLs9p51HGS<@j*x`A-?(E%7Kgeg{1}O&)V9Mk6N43 zfy!SCDqYqI$li~9;tlRIfBu5;9Ex-lEyw>!N zPoJz($HW#M58b@{Ww*kFGOeA@5V!0!J=-G6TmluiRbWf+hI5I=2$PwE3oAdizR0fUupUz(j#s2(~QC(c?1 z;(DRBDik`IBE#c{?*-M9fw&fbZXeG^*-#VpP!h_WUoiL*$nAl*7nR+Yxj1;FGT?7i zzzEX8+3WtvW@)K?^gDf``l?t`NFWSEL6XDKmf^z6Q4q_h5CX`c2rISa4Mql?oTnHZ z1f6T4NZN)n))ppv{txKCVN|7UK=Bq#K?C9Ej1!sVBMePE zyUD>qSrOa(0ec+243#CM*!iBFN55Uj3^`D!M}1h1;QND(OA?-G0B-*Vutq14++vHj zP9c0#1L$^4-QD53+tfy%#0XtLcNM@&yYp{GBYeGkv(?d!BSY z7&bSU=wm{O25_g1V9j7wxSo=^&0-_3jt3+8EU8NX=piQvOM}LtuoQA44VBz7_fRD} z?!{IjM;jq|%Uz5NX!{0OL?@*q9+EOx_OF?FZ#Z0VQ<^>?TOSJA$`iD^3GerS@>PJ5 zcrmYK$k|ilS3x|h(NDYeC6LKmCg|(r-~^N4E)8N2GKRqvfh&i7eeLAK7Fgxw@`aM# zu$IEygNG>Rou@=)3IW--fzdX?xF#?upHFwqNZBKfFn*H5Y=$`+A&<7R$hk}hkVIsR z6)mpgz&~*yuFEG)L*A`f6UxAZaNhosrky=_4?o&XaQ>M8@Gt`m6!1tC{9Fy?UMx00C}`1yy6hp?EWmD51hbn{o|ipO zOUw)VM|2aQQ3=pKB;IQyAddiK4p>1YpQsEP^<}y+Sp@09E=Ujg3n2|qgKpGWH*k*E<8#%IGmEd8p}D+igg1+P_3hOKk~Q#T z+|mTL*|cT^RNs138OjA$pcX$Bsy%mrj~l9@7nQpJ5Cz6WN}t8`LW(x~y@~cm=ue!G zA|lNc@VrPvkhnc12y=VDx@pZqQQ3+^jizwJ%0hyk1I%R=Dx*{o8C$*)Qy$NSv?3RN zcL4t!0;NizFI$GhA8N$^5VVYugK80>A}j)Q8i|49hOS|WJ#|evIA;GEyh2k@P7UG^ zsWFUV*aDdKORoQ^N-}*i@Cl^#Cm&2B47C$Nln8Cz8o8fX3cCri7g^>$iJkug$oeyR z3j?x$09z3j%nrbeX<`vhb|`}$(}JsOiiC=#4NB<%4mkz9p5Xc@awfK$LAGFF7X{GWgux|N zMUk!vCJEaZU zCly+lF~#W5jnL$LqT91eqAbjvkIs`>_{aqPZqg6Ow##cMK0=YSWcCmPuy=$wA;-ktt_| z_aSt85wztR%dH~eOYyJREOCcRTm_DH`8g+VIuW*9IWKe)g!UX(Xr#`f#(ScGRyW~S zN567$1>Uj>vIbSLc`5Z+cx?wz?It`t2GS47bRol7QDMg=mX{+#XuA=qP$Zi{54@p= zTN2{&9TNYUvvqLDX^}-ZWTcaj0H1`z8V1Ef`~SiGvXxk#kWcok0*-kPZ@BW;JB{33 z^<4}g8(9z-)Me-zsI9R->?0sCp+4h{apW;(Gf05$L*bN(Rc+wt7(cuUywQ0~x)ykE z$7)D%tf&D6x16}LKk@x|lD>*ZH;l0uponYFJ0}M-*Cxr!Q{2TPbE3j5s~8r3gK_b| z>36DSKdmNa$fHjjcfF(he~!uiH#+%y=6~uSB3UGl%(VGSe+%22$OOlxns)`Zba)+GHz-~uPlfPqG=xX1!=*Lm=`!2l}0NgDmE@=R=k|8ci;Kf)*(ANtLa_;Tw$Tb z>_h*V=`W6E4eMF0>BFjuiY|JSopr_;I|_c^moDiV(QN}K|J++QovgW6_|IkgGjg<_ zzS7m@8vpq_UbMcjjs8#E#)DP;!ysbS58izKosVEl)LYx(Vq~$-#L23(pf;1%Ti2w^ zGsrsV_ud7*Jf_<>BTp3Dz4v5Q;k);+nsUof|7=FNm6mL;fIj1<{eYSz6pLClK4)aZ zaZh9xem`X!oNXBi=jSND^Yx=0UrOR=)rPXR@Qh7}&aWRfSzB(l4^+hn+wY9eo64Wi zd$>}@D{if3Xqzv&)~27kzT3hXXQ$%D^ToN`RJnp?f%+=b2j{ zvJETq4te~_ixqeUh0GMvt5*y1e{I@Vd(~a6)K*fXx98S+1#zvHF;vSHnOBHE`C^-< zE|%%nyg$%ufb)<(WixxWJ+6~PJASUWkXroIpl&tKoiv3QtbF<`rEI%&MvC)s|+Oy_fdA z- zUgHjrlq=^%^ylx?ba~D0Umm^CknwLvW@xbfplL2$iXJHan(rm*nVy;KCE077-!HXZ zi<-W)J94J&?LoU-OBZ!8=0n#3rOznvk;|{e;cr)E^;Xt3Dhf~TeG*64wQjz)2@?Cr z{m##~&&gJ_-SO$mg7#Mz*y8HjU$va-aO@mm_TP0>;H+35H9hdR8dR9^_{nsuu(NC4 z`a)o*-mgo0n=4CB`oGsnFrWRO)zP)%>E93h3SR$?3d;Ijvt|ADlgPPC+aIOxX=$;` z^y6?!@2pS%MfJA^uP5>14F{%qw@FND>p}CWT<1hhz_|ZB_1NS{Tk_kagUCss0p_XN+2d>t!DTHG;epa&5kFE+$d)i>D7vwnMz`9+u*=^NZ%eyp{Vv0 zhS_vLcsFU30=kaM;=8ssi z@>MJDd}Hr%I|VzT@5DGD88G7~SO`(>TYeW>={?$azvaa#76<)klk?$vRkXGTLcs_W zC0GeQuuAoGhygn0q6}kw6MmYDz--S1D+pDr65_d`6Z~tskbhU;oPN8qqv?Hr=(_bC z(5I=KjBlYBo+=fM$2T+mEHGrBZG@9WSTXTu)wT1&Hy(oG5f&csUsBuZ;2&|-1x?jL z&m4>n+opmpmib*uzfbffYF)ZZt$3bXtujE4Mu`5bb4?I2$Q6!0@mZ}7-&1|pz~M$+ zy~h*!{f}C1rsB6_8>-haHCLMfl*Pas1S&-I{uz;l0aLbm6zDbd*h1S7@~bfz?qvLT zajyQkhx_);a;xvAgwDm8vtga;ut>j!A^LTrr_I;88Dyo~%co9&Nzoy97*P1R*$wt8 zrTRxTId8`=dOs;msJ}9qs;g2hEn9QeS*v*hx%_RmBlTy!OaGtc<=DCAKn`a|YpH?F zi*sG$318ijxpSW%5!2x@e6k6{rgMA7zNM^m7+Mem8#LEc>^2J?Be0P}dt`Z@xwP&Yw+*x)u?ijnoV|vcsbLDGvhV%>eg*=YQD}E>u(VIjpmJvmbVs{zh)0h&(dOe=C0Hl*_U)wjyue9rDW3Ay~LyU<84)6a-0-=i2$g35z@!q*X0fnLla;x z{n8EM__cQb(EXCe+}HiTT08S=91Kq{KH+tFoQsbcjQc^#d7*!3WquuJZ@!AQ>JANY zPjvsf`1Uj6a_ge|mvEegGFGn@biRs^5Iv1vKH;s|(J`6einT;Jp%h6>`XGRn%wjBf zyov#sE*xLtUY=-ea5?_cHD>l?!uhAs3IA_>#eVGI{%gaflRxdvi=bA5Ve^!=a0ck$ zb94~O ze}^9O@5<`WXR`kGbAAj$3SlDHx!m8R+h320fPeyeZN0mV0{o(wbZL;mxd1GUGTlNs zbwHWe3K+KyoQ*=Hx&|7A1Uk|JU6l|Y0EZ$Y-;Fsp9b?nd^Hw}Ow~V9iE5KcgdpxHk zaMNUveMqp$1e7GWsDp7x?=y(*1Walcr@I=HJK$Y1?=1p?AP2m%%l$9y zdAWKcCdeQw4R0cc(|8jF+zm=~jl&kjJ)Do@MumDt2l5V}&PIp+-*UAeIp2~D>(N<{ zTz;#*pMXNE3mpW)Tf%qT9E*O3xeJ8TP&oEg#N#OVk*whm)xDlEJK7FE^&cu&?<*>) z+$REs3X#t=+%!Sx0p3ppK`9cE1a&M+l!*`lG+Ie%8Hj7$j_aDII17gI`ULVthdL@T zWO6YD6&?&<-03atzq7vV$xIC)cRE3SW^>V3Q8BLpEMw?nqmQ_xALFPV^4B}Wm>wNr zVizlKpG5!dcaRlcGZ3o>U?=us8JHk3+elV+qxNX(X%5g0`?wBNsN**E#X;OuOZt2i z!l1~YEyS8+Ya`|3d%gcAo2B_1jsHNA2qgkj(J3JTS0%ad*Hi>!h*rh!rJfZ|El-4N zL|kf1z4$TpN=(xAZo_JhRK23iK`P?)UdS{#u9V^}*${_`$z~vn4F{>WV$x5dlBZ<@ z1x)@&0;eC@0l1Lttto7F-=6W#?`6=Ha!(L4ANi($`yZ7F;2_|6*ceQh(neGjo_rEftv&gP@jXC8i`f|B;|8q_lQV%c@!)QtI} zW7+asej${YtmJ3z)4oMIT18fVAf!^oD`PgN>TIW@YJH)Sb#$ocVq~#=4znwQZh@tP za7Riw*kDd@YkXOSQ-oH6qJieoAzs-JK+vl2l5lYYu-hS%sYl8|HBBK}X*e~rR;QdM_1tW1HdUvFVvLUG z=J+2=9?`>FNRK*`Ai;5DeL$J8U=k$sAcjxyuvM0C zJH!_|9V1Guue4i_cdE~tmSinZv*n|Nhd`|Ru|zYEo6k-{0K#!w7h$sN@;>7^$PYJx z)7(8@{@}}~?PoiBHZdI-3v|X_&$U|8!XEw`sh3H)cO>LRR7YQQ&5Jn4&W_e5F`Y`O z079}n&ZerZubISLTLmFxD&}!;>a*Raz}S^Ru%c!y)1r;xSN>+zmP3#X;Q0XKOk>`M zr@OuACV|eH_lA>R^Hpct9H&Y0;9ilt@|#JM7Q7WZoOB5cj~fKC-=q1qF3q&)4d;`S z6V0`vPgsk}mL1S#tE4d{0wViR;&bX1{QM;69YJbS*IF1h6^*`3$VDJ`!F$ zfN>i>Q9KN+bwvCbzKb195KTW8Nr$+NTwd#L1yxD?>VAiLg*WIwL4kNBkDVzVrH72s zU75D>Ch4@XsbhdUpZF^Ph>jmXBzLqOH+KBNzYv+A7rp3OlV|0@bzN*fLEj%?4kVw> zC+_MH-iS^T{{kmZz?mj9;DjkQ?Qu7TfNbY^#VGAJB??jU+J|#^4eM z>yEM$<`o;TfB}v#8K?ah;K9ybuOk(%zGU7Xx&I!aNt`<&iT2zj-q{6s;%CHggz!DQ z<0{dAcgFA%QFsq{L?apPk^mY>_0G6r@eG8}RP=Wq$uq4ux!AQoc&I!-A+rQmeyc+q z?RW%Mkp#5|Mh|lly_V-Y&Dkf&L-(iV806^owNh0I3PVqZ^0{>piWk_GVeM=4qxsw) zb&01fJRh#&{!Z4)0mSjHl^sfv{&FWP4?ONAL|k`OK_YvrT+oI(Sqwn7q z*Bj@V8W!6K2uTC{^-CE0Rp3bXvKT;6*j;4;V~~WU%M_#+WtF)Y3QQVYwp{ZK*IqCK z^y`*>IlQyvUGZO^@%ad_{=+}lCDtkl4n6$9WVr%Qh9M~HY+xp&Boes>MXbG-*I38w ze_$?NzxV9aAZ7Wokk!+PNQKRnkCAWPk3mR$ea^X>{Ge4_zs zG=Rjs6%Yh){=@VC!$*WD2HxEcNMzoz#79$w5vu`>CX40qnf1ea5p@0%8GCBEcE&0A>j2Hvvx7Nu z=rNhL=?8-a1Y^XqiDa>U1SDzGy!tyMYU6hCf(hT`o1vcf*0RxX61kOZmL2PPkX}BO zX9IVDwawbjP}l?_J+r-Pm)qp_FU;ho)xWD`rF?tlm~wxvR>yYstfKyhwJvl2Q1g*g zH;Y#MlIcGUAk!*3?8AkXYH!z-S6JO7=k~T|J9Eq~)&FEWB%Ly!x$LZrlDvBco6kKe z%cEV`U(wn6bk?g=SZ6HXaqO=!M}=j~fc=FRaq=D0nKmtd=nqDhI}X2ZUu6&em)Y_u z|K;FUwj{;c&4vp1uzHQtmv;U|915&zA1Ti+Qzm#SW<$nqBgkR64Xe8pM6>aN3#LLf zH{e9T<#WkD(=|et+sOl1zsCjKiJu4vySD6xwe)7$=;?? z#R-~O>Z7}I>8^rS@UmpSAq^l+;GYSQCUXJ39$B|mUgl^R%UY4ur&*P4SiO;H9%EL` zk#}cw&?qGxm94RL#qfQ~a2EKHFK@1?)a$JWN6SAp9KD&-hIReD25d465??J95jNP^ z%B$9@9+$~`X&L4Mgc$oW7_@z2)M56RTBEFyFBb*xN}M|@ z-M6qC@F-#NDapO|vURThSP`*PdMfv^U(MJ@s}TorcJ>6Ihm&M~UR7sq!1-ZJ&TZld z<9#AMelCey#Hp0&VL`W9Zh{w8v+~m2>jCY58$%xDGUO~P9xQynox>VO8XY1q7`cKl zfm5}wXhi}3>iNy<~jGe^0|WLuzIldPu{`N zORGh5eDdMivSojN;;#hX)AgKJiGyC=H@MK+qxA*yn*IeX{Fr0;#EYen^b__-N{mqt%9sb7s|gkO5E zG+8;PRVxf7d5qt3!zcrNqIX}#@q#}n70C9{Z&7(a1kWKRCO?wwh4al+h`T3%ur*M zZbSKxCZJxw*75^U;qrecP|1TSIg2Cw7aAVZM+3fmKfNr&rwkDuGI5?xE&H>4^!zXh z7HN&y;)Y9Hn1IHbHkF)M4pEbBpY#s3z*v5|BM4m_eJI6OH2Xt9_}jv`(^Hx9<5!zX z1y!Twp;M9N_jz4PG!UG$?!ObDlzme-@@P>t%AE zSXOgJa1taOexAkR_~C`E5lR-2QmzvYY7tt730yzxoXjCo zH&qAcR~tGCcRV?j?2AfPC;N5JCR}K)Bl(D!KUBIs$n_KaZ33tKQ~piYr=L%5!E0@= zEKTLE+#-8ls^jHUx#^m7Bhd0052&wwxQ_nM#kYVOVLi>XFyQR*G`X(UHA;Iy>tKzi z8ZM}-h%v2}%6w9~>vZoi6RFp^B6GredE+4Z#U1?whvkQNzk5mcuINHBoqMYO zkjS{Bh(GmPj_dNKTaq_+O}eP1=9CvdaG+(=xh6vzvrBmr6oOkz9vPIts{E;8h_X4#rx#iY?=9DvP0dRf5%Pr1zIQ+LurQ4J>JH<_*+8Ya1(kj+ovd=oXfdKYWz+Z8(fO9%(d`SvXrg*6G|R+c;llzFZ!7Z~?_#i@D&8mEyU z8`+dAAO=!m&3$()emHn-%p;)i?YdB~3a3f^r_lc6PtuIWfCl%M+@0f{=9PR0x7{=2 zKjh|LUT>b#eeUId<qc@Ric?p(g4J>a z@;{bt<*w`6`mZmn{9^N1{RTSci4Q5>HTrOJ%`XXrQUWN5iM$=k>CR8LMT;~K`ct=9 zzP&G}e6&vLTyMGO_eCh_YwNv#=o|eir$Z#&VR`?)OMCZ18I)eUTreCz;g{AimeS*W zl{>mB^w(E|2!Gdme{Lzk=;zuceGrl%`@KtB7zkh3@*e&a4H8)C$nIeDVmy6WyXR_$6 zJMYQj)NK8KMFn5?_D^Ad^otF99OcUZq1^Z#9H@`>7w}_{hecKcPSHZJ8o=@dY)svc zVCUB#1!4fLnq~vJ29VlHp=W(SXEdUaN>NF!QNAWoyc(fituQnQbD9dhrQ`?=MG$&G z(c6G>mECzdPP9LDEr6B+!FEOhmsjESBg+40i@)}O$G}8Pw`>F>?|Ry8Vr&;OycJt2 zn`9=JRDTdl^a;SbS{Oyf1%TpxP*g9$PzXByj8EuU6!n!{R6j>_gocl{WWuzd8+)0k%CD-=3^iDL^jw3G;I?_B2oVlv?QpHIH(us zx8q?#@m?D7is*O&6ctv48s3ioXTu35C*0m}7jICcZYLyeg{OJPWCrJxFi=jx9|pVzx?_%IBdnC5^tr^Z;Sv0t8CDCi zHZe&J+e}3vEXSS~oKV3ZdDBFf=CU)n=O~&x!yS`DT4h&V_87e?lvfQC8%L_5Jrd zzjV9!^rH8cefebNb+&F4q6h>x0MkRDPSH#ZD3;h_iA;N;d`^W^b;U!bB1kgm3YP_H zGVDA7gg7E1kGSwD))RyF8ac@)HG^4)Jf8n9dn+GN(&~GP&Xi%X0QwpZw^?PdzZqyL z++8go+t2+y2m{?m*$q`V#+LHRRiD?YF4wBAaHv+e4V)o|p(jxcfl*_1+CWSYE;(;7 zhWn<>12xm|Rl#DNd5@Gs{PozX=-6z7_QVuZgv?${_Z*n9;NiA-tWSFk>%q(Opl!8) zrtH!S?XXI6=m#z8YHVp~PAKely)#!mEE`BEN}$tlfO1W{{b!R8aVc-g=aznUs^#{NDb<=8|tOgFp`t8_;lO6T2 z?)tM!)$pDY`UD=$2&E^mSmh^Bp2lD8tp4;P`~{yzIRZAARc(2rQtz?7hF~_gy$ftV z8JpWQz=dS&*O);F^^iJd%Z8|IpmL(&Om3(#Db(Dte&b?&C8+tm)>CW$XBK8ptvebj zLjbu&U_t2#W32gIi{<<jzFML8lj62aaG_ziA9gl?9cFN$D9h z89X!0TKfmTAObuPX|CvaW=h92zaup-lbYXG*O%vpE-C=RBES-fAn^w;k&D~U1*AlX z-f=Ii-DujDx?OP?HDL$)%(A1`z>EWoyBo}~yl3{ujN~@q73*X`4Hh)?34L&e0x2oo_KL;#esUz<&jT2tR|Ba9YS8lg4{*^OxDwyeB5a+#{^S}q zSWTenwLUSIPD9_70JG>r;=5l-NDQW#Ls(Yf?`Q*$^}&z3@fo>2@U@;|9iSw>i{J)< z7QfzHdRUfhJh zynfvNn8;JkS-#e5I<{)IP2tI4LeDto-sm=E?0gCqwFZLoynLesd=7Yt@0oy1V!wTU zDHkXDQ}NX`MI7{fPdRoBRXmo#Gl5l}fHy!{bb;0pqIVw9J_0l`{_^PnFS!Xp9i%Y& zi1Q2?jnQH`j%OkL#YDT{|QZLh}sa4&q0=j?ZZ#tD9I?9loB zS#h2PIRlh+F;vE20p_+~v&&_C=S)lj%N6QEhx;6B&kS9^KV)|&(eD!GCgn6#Ry0- z43%tdHN?7p2dETUf=f=Ll>4weEAWQ-0Z6sGI}BfpLopajJQbU|z{fyR6omiFU%-6? zNbDxZk%>el4#cuL>+~Wrh~TzcEh_~Q1%s}JoU*t;w%1?F7K0b{Uflx2pgmw17}^uc ze()Dyzbwvo8ITqS&NDMCU;vLk5Get;(PjyhN$IoinRyu8VJI(T5wicD^(x#@2{2Lu zR4q7#?-Fg5)>+kou{=PuUR{=V(S(_B>C`*4@|tCV%0m^fFBym>zgJXRwLP^(r)|2k zZ15+4fHyFT%3F?Sws;d|e5k<0! zT@hLSm5T7TMa4Xc2IEW*&dhZ43qq@}>D+U#G(4-6iac3f{8U(|?s<;|~QsE@ivztmsNy7#P;m`~7_P=K1wxa^UyZ_EW9jmUAc=?{&HQf3H!F9KM#*vz1Bt zvCr7+F-&OQ^Dy7IkumZiC;JeEt9{>FMLSwHF$6`V%Wfl zkap86o0xf>l5MVHrDeYqU?-V98K*7oGkvYCljB3Y%!=XW74Q1n2DuLk9;ciACHS1S z_idN0G>TZMU=feelCdtF{;Pift~(ogqx7K1#5C1X>J@)@`(sX?GJ}%26t4uUv`;~0 z&7Xvms)=;NiYWW%Icx6z2w&mKZ*|Yo>$+d_tyiB65~{6v)!t0X()W5*9w*G7do~IY zYnoNnszv(TeD(FGk6E)*)!V6W>)SpnbsVRPyEJBW09meHA~ki3Oij*OzuD5hw5x2! zE#=R$i5T2L%wnoLxWFHubYsQh#S55xw1}*TWd+W_!yt8?KP(-{F)0JkGuKaZ+ywFy$*TJ#W{J-D6KOFaZ_kFUeeJ|mP-gASkt@@&ug)B)@#hiL+ z&pWvg2HGLpnMZC(_Lt;hK1pKfPQxQ5swbUMl&w zX_2!a`_rYr;?9RRQE*IXCqYX!j5oZYR~K4pluBDv(R5tyE-Z((|*DE*gGyhD6^V&k|%QKb7-dGL3mZ1Ibg6>)mNw$o_p!+mh*sZW3|yOGS>+qlk`Qys0+8ss+4xl zP5Hfv{?=dJPI0)L37ylGl8m6g{Gdn>zLA?T^ThU+qbcLt_BuDx-mjONd&X#&&fF>? z7~DNeuX<&`KaroMyL~>>??wvZS6Sp85n)8f>=f^>CdUK^EukECTk&QpM0EqI9o;`d ze=XgJhu7Y|QZqe~VML2M!I&)jFTT0B(NI=WC+gU-uqoVB5cqdT$JcRwvieq2@Jhgn{>|S_U85QR)i)exs?o=2Vw}vISxOU{;IePTF%nPrFBK>+EtHwWX>zvdz4 z%W4&NWkCADzj&h`pqarH$(JXde~dr}C6-2LV=Pq)%kBFi9V9VE)st#n~5EwQDH zn^w{E0!P}*x)Szj3KagXxPdC82*#joJ3pWNhrba<{+7v(+Q_x?4gC>xnY4BMund1l2p#uO z;HkU+c6F?FiIa*xPCUsU1YngYwcQJjk#U{IcXl8aSWX6DX3uZ2KM*w^xFQ?WnH-dA z3^3aT!6t)tk(6#o@O26WDGmHGzHXQPaDKz36A(ZWa7MDYU?h=IOJb;^Xq7(b0UxVb z(2DFM-+g~!0>ws|NjQ}9&6c&`H=gSN-?+-|(GqYZ>-x{ubH+GOj0dr><-V5bd{fZN z>K6zP1oe88(u^r^N*Js-47=}t*N&nl70%fZK_G;4QSM)k2>y9qZ`|8Y=fE2x$fCz6 zUV*T0jUxuwg07PvF#2p{YDB+UKoB&NQRXo1!E(@*QP}-3vEoRya*ULv3s2R<9~)O- zvhJSS;d1*h@m6s6YLt|Q1LeT_{;UOADQwLa`brl5y(gNZIGXz@j!uqA5{xmkiy?d2 zpKK0>e#1_x2YL^%=uxAdPC#)J@iN=7lxWaRj%ews*#Asp3|rVLIAT8j)&UY?0RHI4 z)FcSz!U#bQtc#I<<3Y8wT@6X)^Bx%O=aS~4ZGQkKqej(uQLOQlM`?DNy-!}tJ$>4O0 zUwo8Pz7;%8Mtjn;3ETkk=Uxt^CzNKN>bC&>g2p!Ardns@M%*rBy`8M}5jJGO)O(2c z?&g)t%Db1vKDNqgB~SROk%KADclV5`wYm4MEh$8zfQ7;AwSdXE7CdPyhR=t}#-uXF zqUk^(Tr>ICLT;4M1BxBAg35HA$9F_C-P9mkfDB0H5Ft$YFgF~GkPoNC%?SZB@);Pn zBB*5s$9@=A3xMq5CuuxCY;^frlV&oBk3k5DZt&nhFSMB~s}3yqbS zKo7f>!g?xn)+*ozrDREF*cw(bhp4Ot_zq#u9%lPeqIU`9P^9Or-}qZOgu*?1E)9K~ z{waqfj3}`~*^n`0;gV64WRtAiAMzF1pW@R&ShgZeS`lDQWq*`I9Pwpx%>gQ7NpQbP zs2dK>MYzmG2;w5BX#p8oHH7`L7Plk`G+}xVUmHVUVq_5@sFFT@ODI-68vbPgnc?@? zs`@dbx7TgK#Ip)_7&2LHsFs|pCc0r6Td`?*!n4KFC5bY4PYoO#qs3%3d%|_d5@am_ z3sce;E`me$Dft zu0gGiLA63LwF^mNRVzmnIX`a@ zU=k+iI`FA@f_u!mIKVaDT=_XMad++8so{VFeIaRlnnI_#nYy9G2wgUopf(Yfg`zH| z2F804CaH|0zQ3lS!jporbppRu?H+{ombqbki;*mnAYxCyTEj~s z&vX4e;M<-^k5nh8!OQVWH(z(|%Y>O<`nNZbV&2uW$6h7{h7o#GI|nz?fpu*ij~s#n z4OqWO5L+G0%Nsh4Kv%yVqN=hwR*?SJMgIRo1O0zB9NK?1oEV&8G;OUn7<*DHPf*h8 zY8ti4Cm4YTRT1Dl+h(|~N0G=?5z{&^&{t`E+6d=6Wvx|9D(62*N)^3TpuOCx&SKZ|8 z{i%(S(tE!a6!tdXn?!Amy`6XWTy@8V(N8DM^LVVShZ!~BP1#v(+uG+%dZO^d`w!2@ zsCT#0`s(dcr`V zR$FTyhc;Jz8h3PQ-v%iTm)`n5vZ)+p9W1uOX6`5(h<7^qevD zjmluHPx{$X%sGUr>kltZl$In$RD0N}(c3Dkl|suNcx(18eDWyu<68CYApSP z%)8y?ce8{==ueHlW&yIgk@)Yh-OoVxop^ZWk3#<+NLMoXa9= zzNNlK6>CfO=6dGRp6uQDWY`kXEc4BW=#JeR^0@6}`~3gn>#YBpd;@U3WE*4fZj^xN zCh-SDQ+^Uyo^ccZXNK#m(UOlJSSVhae^UK?e%i7_%JcQx0LPX5N@-EY1vMXf)wz1x zhOC6q>|Ut{*54pm4R6LOiY|P3_QaC9(l&7S>-@6OizchEE0=dCV2)qfsu~;(-fm#_ zaBVtgztuNxy2+cg&ePQLtyC6z2JZ1K zbNMcdSkLgM2>}rmE1jE%&mCpQeL4K*)HV*(J86bOES=Uz#>kpXugPH0^vXCL^b@@+ z#Y$G@u!b8&X#Nc)lCdfROsJcEb;d^0{BnZc2?$N9j$y>&kJaltqL=e6T_vrua!v%> zXG*WqC>MnF{*1Q{$Q6Xd1}f!l<0BF-$BYv@9n1{Bcn!Q;nG(3FBFuiVu>I_Uk)Q|1 z>ftHzt}TAqXtSFi|LFuNU!OKgY@W{+TZ!n`{XQA_H2>pWV@EENk`QikmGE{XLPWm8 zm6G|&_M~`_atwSjCDjivjwrZd81$6d>bEu*yUAs@1Ek^G1q8gs6V3+QOtnGf$(>8< zi*7xiev{*sP!|O-DJa0NYw9T7y4kOJsV`lcynYrgHu~l+yViD<-DS~w`i)1c)U2WC zlRrL+1J{4eJV3lTO`s@p9Y5BLhr$gt$|F)KE(v)yJ!=|&H-V^yM8R>DQf-l^hS3Ah zqOWM)X){F;Y^A@a;BQlOQRi>Q2E9&y+c>5_{BQ)^o0K2Hp>v(?I+>p!lDj&0m2<~6 zj;$NQW#BI%8M6GE&2RaXbQwgj&xo4dJ5%=2b=_c8m(N@2NmVoWtT5L4wy7|QEz+wG z{MiT8_BOf3OBIAm$wRUWgDMWnAa`7Y-Ud}%5Dw+ndElvQVto(D=-OO=aA)o{R(Kif z(eG?`F>`i&{C16=OwX-Kno*OBU43Ns{hLoS%qe-lf(%2H}7HlL{ZGS9CzPo}vv;4?K&3CaAXH_#X_T|x!$a(0WCT5q1CFb%@vYJC*xKHbl z1k)_;c3exXdFsFOY_I+O{%Uj0=9?;!JafxrQ{(uq7(vlMbB%{LKW6QRPO0LoC>`fh zYqmpoz__Y=@D}cNwy@eD?yUKB^B~j#t^Cm`v$+Bsr|>2G5K}-BtEuTK784*7$*phA zRhrh%>EU{}aB+D{aIWn~zjTsjq=7MRR;1*%ZiM)1$iR|N8=J{DH#5nHkgB<1Rs&gZ zN!5F%5AGxS2C{ZXRO=}I=`vKzhUShgF6Mhf(^H=F-aFXY`2|k;h;+$bP@Vp|;vmn! zc@NphPx|&hT#lfU5+L@PO2 zdfUdQR0#r~^La4T5HQT_Wz5#7L;5E{Hp77LS+--2H*Ujyz{LO z1BgNB5Rja@#xNUk>+h<(aM_f&;T56%f@F<59P~LWZMcD#@7=};}E_OzB zov!ZldF|xSy!$~v9|kaQFrqF;geo|%>u(^D{(0=+AN?0}Jjg~rc)w4qz2E5j4v3_~ z^b1ts(F4USKm5TRH`sq6LJb4P2SZZu9v9dB7DNLUwV%nA`cHW>PY;qxNyIlT9#g3v ztAqY)_GD*I5E=x7VG!mR_xQaG-JD&N2c^MPTQe3on9z2Xm8`on_R-5UXKJ< zKoL#Yzj9vu@GCHD7Vd5%vat7z3})XG?6bk-*9sF|CdE2Lw5CNwY(#W8L|`H!Vicko z25;RB|55_QWfDxVV(Ah^t#bzj5U@L?*f$YCZmSCoq-7|sMJKLJEc(C;QbYrBOoCH3 zq6cKq87D9~1SGN!BQJ}ZHI0vYdrhTY?T-w$R~s`8LcS=CY}klJ6PQJ$-(BQa$Gf3^E0cnTn?yf@_-4zqK)cML{g(;a_#Y--Z~~s{|A%QQDhX#xd~{Dp6@T zk!Y6a#Y0uvjFTBo5$%Q`#gmx5DOb}eZVZ~vB#S@~3$%xYTb#p?hl4~g8j}-Vz_K_e zKApg)*bGyBCu21zDU1bIBo*XA%&@b9fOJ#oUa3__88lR8&1Qm(BgBrFfx_Qoz=MO@ z5G;;KGX%suo^b+8gRCU+T4%9SaB-Uem>6_^E$rYRUv<4#_Y7BIINS+>8nlUxrBU=Hr>cLZr+V?@U3b3=a@^c{pE@R&2Qi zQN%-p@D`EX5IN?wZzpn@=OJ5VvEAa4ys}wzQZ8RzE>BMqPLYq28pcEC*MZX%l2ZIk>ZjqOc{x}Bm?d$!T65* z#pNM&h^0%YT=h*R!er@q8s#U6QGNjWm4Lx(070UNRXzSn26jyRMB&3Cvw0jF2$!{N zeoe_wVAEHbmt}Z4mfO70T*|2cQyHGuyr6(`)YB}W?R2H031s5p8fQujkb%XN^?R?fTPxTb9BDSuK zoy;O^!~_Ggc#$EB4}<@$P^tUzYH&ST{wRKZtRW(imh=d1|{AS{Ce49b&yz-xG(nODH! zK2OT?12&fO$RT{qJKdTT0<#T*c5$>;2w!rAFGmU8NT_Ua@@e_IRZExfPjfH*#*;QA zlOJWD^m>;Ck?*EpT?aSHVxMZ_>2ZPn7L5dlLspXCCOn;*40PIVp**Qj3EKts1)&CC=9(R3;+y{>^7Q&H~a#;9X*>m(B6+61%4V8C^W7Io|b zZScA#}YW+Wb9R)N4o~7l+34E>1P2Z5-<|g1nKGgua6~xy(|gf%ALeyF>2Akf*$UFl7*B# zHj1w4x7(8tUftQDK-^8bey_-@TF3Smw;nZE>QhRO`+F+;E~pI5?6MGyyS@Fmu~oR* zJf55=Tn8|8p|eM?Dzay?FRT+3YKZic>Ah;vujyCUlc@((wNg1!`Kqij-e{ubO$8MVSDmYb(Mqva$G;f%DgK#;I6289>WQsy1WN zVsKKCf2!Q_O=Q#?^SfzyscEC<*w<)A2L*d;mv1gw%Ayo^Pe#NjCa_b+?`+4Lw5&J4 z-8a3;lk1)n_f%gCPfcfHnWW-bs7bFSrUo;xZysY(E@k&Ad>u<$nz{re_! z4-#a=79xdBYr{SziA2QA9o`9EQYpXlbq*^v@xd|>0z$^{O()09spr4StX6Z*7Rl#d zaN+lUU>2A-GH3QT^M&eU`r!f>_hNoEk1m0WOA?z=jrFozydDFz#4NT+EeK-t%iaV$_JaEJR-EcOCQyvbA2fn=n*#5AQDuSfQc}=R=lXyS|kCg}T zTl~u#&!4!cE<fZ|f)N0HM zI!0jSM8GOP=chXmp^N`h$=c^K|YjXG2paM5%uN&XL?&W19otTcjvkbWBVeLr( zxBZ$uJm>$>khhJ2OJz)!l9QNCzE8)#xhA`PJ&iN|OyAs$(-iG;wMM93i{k+Ko=9vp z-_#@1F3ulsV;H|XS}!qhHOW83Z>!``9&Y2Ro8JeUQQ|^cS#Jal6HZ?IaJ`e~`*NYt zl?Au<-?^Wr^{k)ej2*Z;MhiSnO&;U>sQ)_E{oko~H(Q*`P1TQgFxXP9DTnkc`c8jn zdbN{LdZ{^b%6Gmk(!unm7}ZYev9+I`S8*+GC$1s@P`ULk~L_+B8AQ9aY+2LF%CDvC?EEJv4 z6-{Zi(BAe=$-SZA&7Bd|UG666bwYY>l_;1WUP#*Ke*D5pb1lcCB44YgCj=v|{eE2#cCSF;jHf{gBMnjGCO4C8P6lm}6*uro-&`IPDLp8v#| zaXYMi^C@$0iBr17JG$7GU)Xb{t*Si{ig-d5YrC^%vqxlQaScw-$@C<=qkt#{*Gp|k zdcSb9zL%GmI~%2bb}ESIQYz*6!S?LCmMzpkI8WY8}SgH=pl@ zaaN`3`s*c|ce#u{YEKUp|Joq3;=Eo7=GLd_EL?hYy3I#I|6Bf{Ig7-z;-F0DM}u}c z@nQQrkg|T>XRpc$`wQ)QBlN>f!Izw$Ilmc++=4v|{UN9+JHc}5%a8v0uPTkL8lz|G z24|%B!k$e*;g0jfJw zs6ee>>@9TrTxxr)_+X{u^%iO=Rz{CE4~wgE_!}K zs>gbMP^-Xvja65Cu|K!tGVZ?;`PeO~t&hqUj*pJtpGD*Jb9Y5YEU#YEip=tKy zo^s!+r2q3(@6RlCoq+Xxd9*9#S+j39S{NhrVtzZeq5IcPOxu;Q(y0ACX^$uJ-vrC) zKd;OWzPNYP9XRn@b4NKT@Mpx=T=rL6qj#VGTJL)G97B|hS|pT&o$I;nKtj&nJ;Fz* zkvU{U!7P!#H(GjN0U-fOO3VJzC)8KUUC126@8S2ExXapPLZtRA_IT4YzN-t{@;*Ba z);p2H{manrVi6iiSF=~?W2uuC7s_u;a_ISeG2WZgrr?X;EbiXPDUmJ*U9Rh8%Hj*e z3-PNN*Capp??2k3NQkcyJW91hUwpfliM{)78mYG0Rulu7FW_$R(vtpH7-tv~LHEj6 z$OU}yZTyv?~Mu(W3FIHU-8X!T`N8DJQ65HtC8 zLr$PD@^X0^o!$KMv$Qjo@701eM*X**Wzoyl&#|=g>j$tWvP2_gr#7EI8@W}mlx45% z|3Eiv`fA}!NDS}9Th)6cW2IB74!SqZ+Y$v~Mf`5@dMmxJ(gj0`EqlsUZ~x}Jw$+$c z8NDvB@2M-tDwlE8H*w?igPG)ZhjL}igi-p8PX75O0dZT$TXkNyjJ@_NtuU3QJQb5T z0YUEDt%Hcmc$h%x->f`uEGlx&KWt|(FKcz@9%LY++g zBx2o`)~fZFg9Rn6QA8C8D$O6JAcKw_@$hJnT)twn{hKV2W*jx}rP3+8$n;3~R}+nY z`+-mpvWXts4U1F&;ZEf*jtchR(l9$u!jBin%!A;|R_eBK&Zx_sO{YVWN^aD*=u&rn zwEI7*c78beZYQ8g&M_2z+H2H8_~dduLZ{aIg7dw1%q{gV`oBC?9u4~a?`_-Zxysw0 zns2vxA9T^HN6%G&(CkGA-J74Jg5Fr%gMa(g!^R|SzZMlTW^w{GGWJrc0vP2pF#wiX z*htzc4{9RTphAYbLAN`XxmrA*bJWO$DqC2h_)_6QY1(doe~%~VKkeeYt;^N4oq%{0 z-lxM#G~AJez#3Zn4KME|VjsO9HCJqq8>o7kZee}ql@Ry2MYzEHp{`d&ZQM>_k%Ihg zk#L6@eON+ZR|rYHr=+debMwW8oZ3!{cfWaFe23S>M2$ku^sVts;F+X}J!qMzqaYua z0=L;W`4O-m( zc)2UJfs@I_o|_1EKrS!Mq-oWZ$2(X8YqN1VTUIDNtli>q69mmoSVHQ474GHjXt_AV3;ib{oV=E=H6 z`s&NBZAs!S?T&?Wxy{|RV~h&~uMa&}zxjwno2giKpHQnk>>sP%i|OKf)yq}HaX`6l z-1?10#3;<)z+nHSh9)1)^eF49>U!Fb#Sc@g9i!MsUmrPVer9{|gMSLgc2O#I#x+|c`Kl{B)|5cLfKOq8-c2p<_iJ7*eWJD~Mqyr9osd^) zmCPf^1hF3EBKUb5hP-MDSGKjoua=sG49N-K+$?4KxBuYr5Q3F$R}tFztN6WA(`c+$ z2>a4OQtH!O^7g%bK{7Uu~uKtHC+(LgHr6QPvZG=Y(KfrTA_- z&f)&?qUgWf^^5LZ_j8Vo!hOD9n(!ENcSbRT1a?NAyqL_-XLDcV=k7Ln!oG5QRvws^ z0Va2`)!{<#W=U3|015~Qmk*#fyL0LUG$Xw8-}-*MNR%#p@B=y#YJ_{!cT zK?b80?nW5koXKN@P)Y1{Bq{4)zZH_w;a!IJTc5~`(;+vChUihr&8g(AQgUf?z_)Ox zhwHwE0}y^<;2EzV6QmFCptE)hdamf2g1bvwWAKBG+t7GKDG{|=6v|Djy!S4*i5JU*dib*st33@n_7oBW;E|hujtzFj!iD(%1%#O*!Dw>c+S>q1KNQ-`@K<17J z(LHp(-b&W@dJH4RaOA}x=OK`(m_Vk%HUL2rsYp773g3&w@VISg#j-2<%dW|B z2F1Udg~4TjMFOR`8OBHz!a-mU8f@P*S*$#c;E>?F5$$3c(sU43;N{fmo>-oixR4eF zj}P=a;i)N#2@N&2+wUX zsd4~YdgOD50E_|1<4g9Ps7yOhve_h)IK!-T8lNmm3hPYI6e&-8F`PE$MGlv@-#$Wy zQoU`xvlJ;Q>GM>M*_1C#8G3hsDXaKj#@V-LVJ{4UylzN=7HHiO(tnr~z6@bNJ>FB{ zAH`uFhS6=Pkj?ZQuux!B{#*4jm0Q5OWUpe7st5^H%>eyaXIE0 z%d@&00v|yr9U5ibkqO0!>~@m`sZd5z^?3RAs!WcP2m}Cug$#>CeR4#JY2l7cDW*k2 zRtO6m$0J{)#B{LG)z_Hw=E*E|~H;LiIi`fKwkb+YPT)ZPt7sZ-i2zPq2 zMg`crVb{$P?n=bn+Cs+C@el_1THh)E{wK_8IwV3S^EN48npS=-1I|d{1eZ;&nwOwS z2p1}gV|&Tre2J)7VNtlJWrX=FGMo(yj>s<*m1ngk0JC_&nusU6M5d0EhvQ)Y739~A@Me&%CadKs72ahf&c7LrMgYg;+EFgnj!59`F5A&H<_PBe ze@;~~bY2=%FO7+>BG#&!xsrA!k`eqNBncH>1h5UNW@V({#5RQDyY ziMxnIL)<^JCiP*(KSTr!+{JDL(>Cf9xdd#Yu~s0aQ4+$t8{uHle(7w2pkwu|jOTwB zXiJ%hecO@`7IpJFHTwjp45>5`07+T96dt%dKdbWJNXQT;0kr*EbQH7((TSLEhKRpW z2v8QN_-w+gZ@2NaVh6pJE50q&nJq3v>WRfh#z-=d$T8jhLTHhXfhudDMo6u|t8Vww zKC!=@WPQr$gb|s-2w?gsLhZQL`gel^I$!;)8QXTdgE?pn+kLept4y>_ejsVojE9Rfs_z+J>P z0Q$Jgsox1aoyRdYY)W|Cw=$g17k}0s5F{Rhl?6e_y^K!S*JboEnu*;I!Qjku(O3j% zqXJeiE*dl%-^Wg4P3~mfre(0WvOwaSq|`COXl@=tZ*i5HY6jqB#W71Ao2QL^n`Hf# zH!{`@%>H@Bx;KnjDG0gMD?)z7=rW(~8A0X47*@7U*^CPhC$fav6zh;rgU2Dfl~1AW zGsf9rJFVgKl3HLqj2fH$VuZ>)`KnTp=ryQ_%WVweB>#^!N+hY$$10-_TT zaM^KG{wpA#%3=1_?Q#4`0`Sam*5~@H=J5ZwM)W^vKI{_4Uc~$>X~R;Y2gy~k{eXD;A=LNXJwP2 z7<&zsk)MTw@d{A|NfMk6wiN`e2eMR=CifCN&eSQy+1m?+28GL`-?M5R@SELo`{;9J}|o)tt55- zRQ4O&p@}%%C%4Bk#GRsIErj|GmGZ|I3T)*+RkSvLjefEA;)~fO`QeTMi(Bps2@SjL zit}em7mu8XZ)eK4?K+=-+<%iP^_xC^%0!45D)1>l{=;+e`F9mYU1ypD9t=_%wP&An zJr_NSZ~I!B?R<-TG27=)e0Yi>5GHTW;CQeOOZ;lZ0;|!3`F(Vj+2u9utYy5P_zQC<8Ia#*lqxX|$+Xoq<0eyB< zuIqf(Z;iQe0GV`+``%SkTztksp&4(r~G z`IbZ?rxi4A#8NYkJAJ(&d=#dD0 zS3Vrd2J=`oR<0JC34#3E)Qc*-JG~V9qqow~@NAN&o@sBj`6r(87u2s`Swob2?c%h) zZ^y50DD0|#Wlh|Je2rD^9(pqSCqroB-^KdI%$%bS$cyKEzQ-%ubpBEkh*A7lwHWjF zNd0zg&FnkTqJUj1tQz)kr-8nF%skZv{5Z9(=Czb@Y}uQlsX+5%36%SR>iTnlTa=xA z*5s61>J-);q(Jl7KMwyDE#HE0Ip=+AEfjIOKxHR}rqwaT`y2nV=Wlhb)K5MECU?(H z&IA`Zk)o_uT4GnWRSkk(FPOmTABtYw2a3YwG$XK%t$pE=brhU>!Qao?8gs?p%qtQF zztz-hepH_lxGzWHhU2uF;$ePLAMec?LTXPr?fHm_7hZk8!LB5+7tKCwzRh8ZJL2C9 zP1L0V1c5;;x(bCEB<>(5QFl zR)NUg?MOV?X6i7M;)hMbfs3)$W>+-d8+lP)-}_{vP&izEGg?Hz))T2qHDiWH+9s{? zIa03hb3Ki?E^c#%J&5^gN>N4?Mfg-)?<*d=CmA23-j5U=jYU72PNR1-zE9$SyGMNr zdh?7f*O7tM)ARB0Jz>=!>2w|M-kUj>jY^emp@yj(KjYqCC>FWf`;y{UM}?}|SqLgk zF%__7B*4&$>*YWs)91V=3mbPdf3qjBK2!b@Z7-&_I_1`$lmfyO>iQ#xN=P`0RPmWu z0`F+*$DdDrzjTmQGr#eydA$@YqI)s0=ax=TT`6xgyU2w1M8(a<^4prj`f6rxYM9~W zP;8I}t07Q-Ed&l14>|i-{G!wFRJLtj#U1U3CPAeqgPcnBbfy5@2N76`#Bp@TT9x}ontRk~^3 zlP7}URnYuLwzkR^qx6Nh^*O&o5eyF+LXN<5i9lk|d@NU$^1lRXV4eI-mP^NndLU!q^&1_h ztftt=OmhDiG@sTRfu{Uom$swV4V)Ea0+6&^ZBbgd`yzv%88~rWy6N^yqKYcxV4%d9yrGRzZ z$!V$hzT%h)W584C zk#`*)RMOnXcLtBlpks-lkKWZp7+lb`Vtp9WrOA75zS(vV8+p6&%DPI+0Cr@|#RKsU z^yRa{q?!Q(rjfm&g4AF)SGB+Q5yJZbXrdOnyf0lp-ZPjZo%ljVV_ihwJd|op$4*0N zL$|&re!2=Y%DA-IXRUk8cDyUy{SkBg_Zy9VEE7cJy!WN|0=JjO%pSjc89H?@T7HL^ z?*f%nS%Ij`!_N_Xf`Z)q@e|=MuDtk%OG{*`aGk% zqYEO@9T0biB;G}PZeQj~W{t>47g)bsnZjdcmV*f=LimW54AS?D+a#^Ddr=#{`t*nh3X+8Z?s-5Z_25ze)t^Y{ zj%D3q8DM*t-D1NXS?B)RldPRj1Si|>rJ|L^K$R&-PI=E|PtQ-YE}92Ht|x*on1+8j zi0U2+_(KctFATO91NB%1K9HgC(ZH985p0I$_+7Jzp%A!N3>+Dg+iy0rVbM(ktAav} z=D?14&Y%$DkMyQ*sty>p5m=`2paB^`N(SsZ8{~s{`dQlz zj`HoCi}F4ZeE}K$G7bF2lS5Z1=vWNoxC>(}u^3Yz)#Ye|!4NEnv4es!h({~S;EpDX zlH`OHfc5%r!l}s^_*}Fq32u}|a%A9*(@tQ9TXexx3?t>xF|;p0!GnG1oV{=dv53*3_;H1h z`9qL^xB02%1Yxs;bKVJOyUnoF2)G0EhH2uZbP_iRvpz(!TGM^C%NDhX)7$miJ;a8F zncSO-gXFXA_umv~M*kK=OmT^YO%vr^UoYMEEPl2EAiFa!@u-ymIqfwf(k z>3P{1o=JuIWVE{1F+Dk0c_<044t-zh*2M1g>D})DVF*aWzNb>dDEKp+a5ZmK#`w^@RYH=DUTJa3l-`P zbqvNT6yJB?!Q_+!u7;4cSx*b`;L7=&is1ksh3J>2;6M1x#$h&3LZ*rjLU|!~$tHRR z$m6CV2t)Dw>4BOjvZ!;Z1`DYyTNWeUG33px2Uf^XMfCa!Ojhe14~8oZ?~wHx_y)b# zwH!Iq9mfiWZ*d2oGY|iciazqrZKUKXWPsHoOO+!bO{sAzLvaH{aM)zZ3XJteem;>cB1EtouT<>z|NOV_QQCw>t3v=-sv0}}#zz-*4O+m0^ z-m*zTwhD^OW`w{^`8|VYK(LtSS1MB6eP8F5pvWx9DNh%tU}m83qEq2d-CP<^<>hOc zVtJ*WB*-tHN*KBJoNEc=K>mBOGS$3DT`XiSqU^dvR*XdPTZQ}&4vD5d<$yBgHGw6& z%v=ME#Ns$w`qPh1aZlQ*KO74WbxXf7XR2)#iaA#{D?vTG>)GN%-9yk5q%blsjZAMx zgc&lWQDc}#%20gy!wWRqN#-6<9gta`j4+(tWqZT86WJ>kA!j4wK@+KnKRwls+&--Y z%x5!Pk3#0YccDBlqry|mV^z8DR4XO}{iOuOkukx2=)cTJE$0Sq5XzT<=_1fnw;Pxj zLCJ=w8)E1%A`{iB+}*bvB2zc^i_NZ^*To9wYKT+v=1IJbP0_-AAO=GPQVztMZKCS! zeVg~qYb7h2okvRx)pL#=8Y7$=djJ+GD`XfR?W@eJI*DjsM5K{W{*%ypL#9S&WVl6x zdsOQrDYo$$3{}^7ZUy;31h_fM@kHi=gExn#QsvLBLJ8+~$L;2Jx_XXdM(d@_R&Jo9 zhsd;*$+Y1MPWk=fvqj72LzaNor?{3uQhRo3M{K5gyveuNpnE8sQM-e0?W2xcC(&ge z(RH=Xoh%HFvgM032@FRRjs=fpq+B@?KtVT$lP&hfF597VojUl1x&Xp532k(g9)a$< zxZR8U(~gns;c-ZtqLr)dL6B3dXmHbYa5o*)2dV41Jk?e43-^+AIgC4*S^uTfqs|*D zFK=X#XS$31n*c)sucivX_&dFDt@o%AU5lh$@ax>mY@NE+!|5xPG|yjY(sf$k*^_2K zLm$wZ#3^+OYuWhz%_sp`yuervB%A>ybhnz!@_+gah|moI2A7L#7aK(Y-u`BjBi^V3 z4@7bV+C_vl;2m@R4Cg$GWsnfUB{{4o`{6yE^gI|cAA^#GYvhl>@=U1%^2&KP6K z45u63)-N93OVzL{^b>6K>r&y35eMp*jL>^fBzTk-Jv`mn?kEISmj&Hd?+Q$0VrDqX z@*y)zTqby6&Jy?bJcfGQP0a~D{%#Kl=o2=|N)pB+njJwyjVpPEd{SUa&9jf<%xVRcX*qd{ms z`A)RtceiQYcR0-RY3aYyG6K^wsxwyS{NP-5EOOa1b3f2)yKE=U0;8maUwIjCFtk(wq7j$qF_y7NJmpXemyP#YeO`s=~Rp?qYBSYzr>ic)QQ-Sz!Fo;Lp zfJHGOPdirZhLSO*-c~aLZr!Y@bDlB95_4W%+B7WHw7l%i{CEArMt`KF=b5Hfw~Z^M z(zY7>4szDFbMBNIj8!yA%m$sha^~?Cj@yiKzqEq0jjQlxmexd=uy=Fyy97NH(H}!mZ*IT2yi%`Weed$Z;b*(i2ySkVBc3h$luUBa zMTtXa$0?fPtT*#X}OP9sXT0Pes2KZ-tqrYL~J6FJqOyB>OQOw zrQ0F0Z#lRRECoNIdn*5t{wdHDC=P0}nv2kjQ&*Yl&F3FPOX|s1| zPQSgHXEY+pk%JScI8nf7;%1g@S<}DaJCm_T-qSTBL8d%rC@`+!MQJKAn!y*w{= z|3=m|R`^zc=2LoPRz$7Kd{I^FLOVVzW9Q7LqU!TUnNOtNY&n;HNguXOD1E^hU#Ft( z>s<3(DYPs+a;rVH@zuD_*E)>radnGRackDKN0%$B%g4C*sw?5DM-$TCy-Z&+0On{hhXF#S`iULhn~BoIyzp z@O|r(c`mlr_bq)`+C*aTcR!D#rtq4xU}3zF= zESK{kd4Dr@|%xXUMU zjHnm=3iNuBN@xEWNooFE6+#VP)?_3gr#ap;O^H#}Za(ph;1KQ!x}!dBgp13c5oF9U zhROO*Rn$Kg@ZCpoo=uq`{#s-|(`Gt){r%Oj+QQjg885=E?;#C1+aOXa-P=ABM9NQjVwTc5M2xD`8jBX%@e z{DMDEe3lPKrl3fM=I_DD-<(C+n4>k_(2T+-1-)g)pN3RcBNA>DybhZXwkJnt7#Fw< z;n*HW&1WoVCAG#^*?pQ2f(3<;U%e4nKB04WiucY`(Ow0H?0kRl$5_X;q8fJfFXC^M zw3!SvX~DKR*6fS87nh2d<3C~4%iZ6M`}}IiZAyP2@{~mW_(rhsu8l_c2z&7OQ@6aB z>PNPf`P1}fn|io-wXIYyBpmqC1m2G#%%__Lz53NUv@aR+=q$&Q*2hK+I9frieXhw= zu2TP6jYkU~-{O1DmT}JOUT7TVo_R#)*!7cTM;uG@c2U-#fq*EZwJIQWG932Rjm&rjVgZ*j9 z1+Xdo(=!h~S2G+{P={SZ#N`qGyCbH3Z-ovX)yEbvIPk9TdsMS-`DAwF6K8xVu8 z2)-jRY2qPnE)ZYu0?cpLzR|syh-b+sKLENvt$*k8&cV9iBH`;ZmSS&QW)4=~5+ao_bUc+ww8dQuWF_G}S+;lSZ z#_y%wu(IPb=$29Vqx$Uo3RSQl(v$twXBS>ezQ(gzZqS*+@P^~-L48Xi zy6>s!e1dCVjPvly++&aag4~LPx>5Jod?$NOdDu#3H;c_{J?7B|zTA8%p!kGRb?)gt z<@I0b`ga<$p#~mx$9FfhMHOY5Wfm!aR!)x*n(pVYx|4sV2szH7@V|XCtMvN5KOXLW z{%|xZCh+gKJZ|6R;LFUaQKo{F`$q%=>m5Vo=btoOT`lbX#hG;~8(+F4c=60PYUINg zQh#(JKBI7cIf2b5yYb#1{=WD#8Fz2DhpF29Bse+Dw{0a_G(yk=64KoK>HITo1Nt8P z{GakZE<3p_y#rL z+z{y-BKW~zfL}OBbr;4BVA>{wG1&iZ&&MZ$<5{kQNgyuOY|b@ATLJ4y1)g|ebsYlA zcF~N3P7gz@1qwa45nyu=&MFrAkBJ=r8K!E;#E_)DCZS8@Ic@1;4zxWFzPGr?rof#+ zwlz=oXAam#tAI`tdYT&kz>tY=*ZpmCfcAR${n>D=Sn%7opb;AQzg!1|nkKNsC}2ZO zfH!zxc9|RK7MGE=RREL3>QJ;gN``ItGzi6yXL`U0H4IS(lOQ&bWBesIGBU!SJ2c6| zIhl!t5o9#Xf#U}w#Ohd3Q&Et;U?vT4i!8eO^LdCYg=-HMl^;!)fzD4|pQ48Qh{Z5S zHE#|2Rv(v;**KBHH@VaFxD5saM);w0E|_D0a8Hwu0TEZ zRCi}se>4P5c*R57z?Tdi5p9rD0PC}62%b(&O!aV7L_yq}A&e0a*6J}M-QlFbO+hjI z0L#QKda@C^K_(lzvP@2SEcdckEr&s|;nMjS90bFk7jBD>(Q<@_I>aC-_U|S!x&0~5 zJW0rMYP=nE)giv|5H>(VV@zBjJqV9@MtK1zBLgtJF)Sbo69oQP6SEJBd8nJxZIzN_ z7xUJEsz^z^Oi4$fVw0IX>P+LgC=oXZ7#2>{6>!2SagM`7wn|5n+wvS{;=F&vcsnK` zv6Lj$NvNB5O0tLZtOJ!vJidD~lg&HQfRL)K8$0R6N?8oJ<3d)PmecAYV(e0K*F93o(@*Tl68fI6*#K6u+_Q% z1rNNS-GtDxTQ{@23Di}ytYpQkPn5iQ)4Zz;SdAkRLd*?6gLUs_ef={VfUQ`?$LA& zhS6H$NhDh~T-f2=DY>NGBE8b-F3 zD?S%zA!{D{tJRSJ+zbKrEr44I>&u--lgw<$?5p7d zqf+Yhl=vD`>Wx3({@3W?|BmhWKcff3<(@FWRbBs(SkO=s+#|i+m{RIGE0p#md})mgqn2D z%h?+g5&WI{wut5GiSXwEpO|k8y{gBWCAdfa5MF43Dck*-bA3D?=@FcwiuSCWY78`s z?4P?+`ys;nU5!e_**!w74Zr9~ONC9s{~+uwFp@4Lkv^r2a1d9{_1xfep_kaC7pJ(s)*{gfobzbLr9Fxq?{1x^Hz}8Al zKJh-L&YGP`w6i~rR(Ff>qJnu5g)Fnc!D^?+e!s57{^5*Dy#GHzXF*)j9I)>>-3E7oJmAOk%J4^LW991i`@5d{ z;u9vT2wYG*+TxC7>v06_bEBu^%nn`lDWMLKeZ|p~|;uH;^nV#g*W@VE4IZ7xM z&g&3cxS(aLd@I=Dhpx8!6jy!W8UAj55sWXcsw_N<^ht1}WXAq0WSYO7Wk7e{7rTis zXB+9K&2~-=^<|x0{vWb9zrMcnxIVvKf*_vmp!d6z(ut-sa;f~$6<76ytt@__C|~qc zpsQvB?(*>O<)w4w5?$tNyNfeb;plXTY*MrO zbv>0eOs`#)Qloms)5(joCCnbuKk{l-yx-ul@XXx#B+qH9-K$e4;Ks8|G*OT$j0%UF2hi&fTvc^{S8aj7|$p{-!u-H=`65s=lS%z`I|nu@pE8b4~`%M8hmw$E1YU+9rtn zUibPvuD86UGFcY06zxKfiPuoM?|TH+foIHD^^xbKjlbm=|> z<*-!Z2`Ev`?$qZ6Iu^HP%cjCUwLI*2%E78~G4kt_l0(mI`A%3D^S?}M;!=zTuicQY ziGVnbQs@uhy=ap07lTNGFGRb0LX#KLEV5+7zSW}n=05>y3eOxxS)Rf7-VZ>?!^mw| zYYK^NnicV%kJduDn)s<;cv`VMEKg=uCX9;aQ{h1dk34NRMnw8gsRb@v{DWI>5GgTj z%o|=4CX#&PEJz{zF0V3mH;%-2tMHf8j>>lsJgc1s`71$sj*!WvxHa0!5=kkR)@Lh%gjpmCVsXo_nOX#P8!SGvYJd7F4@Hw6+?n%eXyu=^oVe`<16*4SG-yhl_2l1qT5U(|Fg&!;1v=}vozBuMb|Luf=vh+8dZ0CsBKBM;e(y;Z8vxF_aig=>)qL> zanuA>XZifK`v?7b+jm96a?a3wZlI`b(u<@Q>wr;VlFk~F@J#q>e||nLcP7etShqMI zyjUv0dhpmw&cbEKdxRD45>Sn_{+o0@rGX^^JyHHV?3wzua5y@?$Eh|`VX<4H{Wvi| zAl4qFjK2km@hB)|4>g`J26-lVkR_n?GrZ~RDd!z@$Mfgkx{omZ+;q*T6tH$=*_wj; z{>h}pg0%6Q99T(F6_ME4fIl!2h$xr=Uu`|XfzvH@)(tJT!ZPC-07yz?L8+3X&C&`3 zuCwixhjRki0T{mFCCDHk?{pML-_fPk`hxMs3YC0LoHo`1t`f105hKI$hc1mS_Q^%Rvu#sVze5&rg_R{-BhU-~OiGgbMjHp7(LoYR9Q-e}#Ma1qlq=F#}VnXp*8-r&M_ zwDqNeVGP7ql@WIv{Kk7spAQ&Kr9Af?=5ux~G|Jm1{V-U0n}XJj=J}WAI=7T90r#}> z-i^OiQes6Qr~3A%apDV9-dysQg-1lUu8a+o`vB9@CP>c zea&x|L))T%O+xpRF^Iv7H9ZVZ2S%SiU{V;cHjCNDi|8v<`WQmX1e6+fgN|XmI{%L_CCw@9ybDyOTigk5uyO} zZVDIM%zfh_-jr-|gH}nIY`UwkPeAXjTlR;viTAjrfeVCqX#RbH`v}LI|g| zXy2EKHBc%vm;s0t4~3+6l8D&Fk`OriZlH1v5b~J#IWhe}S_h@t=XHH0m=F7+l%AOdonrkxE5kz1oL_7sd zc(riV$FWDF8>O9!k%WwZc!Mr!n5g~Q)LR5gj^JDy>T0jlRI`WQ+HbgKGh z2G=IphzRIEfW(jwY~hz|Q%jyBll6BevwtT(**D8%Cv8e9mJ}d$oun%7NPrwC_!!gp zUC`O_Qk7|Dyx56|sC8FN$sjNyQMEYp0VP&%!&M;9^1%ef}I@y7O<#f*7Z3<^YUf!EIy+qLp1OY$WYp?Z^X zA{dCtCYg39R31kpS_1j+0`fLC(?q7^IZ2-BdBL;>*@;&kIUyElhQYw4Zo7p{LkV@0 zz?LyXaBhnGlQ?4g{I1xz)295B<%|cl!4_zQ_8`;}N5sEb{LnZPR+sshq~!fF!C47z z6){6j0Tn3#l{T=t3`ogT;IW~vbF&+@SV|@m*<`~uIun0HX8P%z_{DT^()+fDO1A}u}2QqZQZR;1REyA9E}`SBvS#hvRCMX zT~WkGw-N#B)yZ1?W`ja%X^)%ykzuvBc7BEC3&?R|-vT7?5>{_lc4}YD9|yI>)_0Ir zz17O>)`pm4$Qm|vdlVb~FiB130S`8rl5n+p;5tTSK;|yF>vP+%jv~sPib`KF6dZY) z1)l&AhWx3%pQ(jLHk1&d$q+w6t^b&`K+;}wxxLmy5u8I2BwHmP z_^ENS)IvSXvUu($PjyFwsnT%27eupf`XuA%Q{aL)$OKTMo>FAs+nu+KNbYIYtY4Up+~+mg_FLQn6Gja zZ`#`dCwI=mKFJSyH{BL9YIySrPHaF#p9-RwPqw?ih{S39HU z%;mmce{_C721SmX?PMAnd?iZZMcBOz0<&_|F(8@M-(&-rfm%9qGVeETXMOzR0Awwq zj^7I?I_@=X} z?zzG4SJS;BEF*fU@BuJVLh0dnD6rr<0)WBd27OH^ghc5e*O1=yM>DV?R&gzgY6=+Fg{;O_#*)$sI*s1T-@=|n!r3FeXIs`dJcpUXswhlcj=xOk_nJ4v9#S09tk@@;9 z40{C*`V@4g+OR2X(mYH7g4cj66Dl*LKhuHby#(y~w*Nn}fHm2SldN9JA$cbGNmEDb znN^y3kRXK!b*>y>EdbCB zEIF*m@gVq1H#a&1O1$edWT?dvM;$mzAL;bmHo*sfJO0G9bGD(s z3CTQ&g+gaRdZpu-FepjbJ34k4Z0N0pK+m%60DjPcSe^Vnons5P?HI<^kIvDx-9~Vx zdv@M9iuoPr&bzlJT7nol*+D?#h!Ud+kR8!scY zSt1j*n<);#cipAqi_6qcu+|15KnRA8UtZ{7mByCn9aBLN8M)E4&HVD;DU*N?Dv5)q zZlCUyBAZVr02Bl-f>6hz2)(U%kbhIapvBF+=lZm`!N^Kffj2)Km_aZyQ?LEQb;BWF5%Wi+&t}ed%4JYu{mvo!hH^z>I_4{ zM7Q2qNXQloE|uRVgQQX>oj|k{f&ZFr0pFM!3qLfAk>)T>kRQVox>vD3d234Cnv{s} zDRa+CNuIHT9C$-V72ahCQu$+O-f9Bx6@b8N%IU|1S%)GN#=e%Uur&XZreB1k&wb;d z5ta0lh7P3lQ{nSyDdB5oiKBV_Pv2*X-)iE5fT%g(FbEjQqb4wOyJMe8H*T}IqK29_ zfkTnE5!?%p=>C5Ju_SDqSxxLCQ2@!k1kL6$wMZn7#o7caTP>MI#rqoZUxii}nZEL; z7=y~`G^o{o8GI>~(@7F9Bxh>hRDa016GEzHKl=kytZqu0G5On0ubMtRxPi9~`!Sc~ zwemVs%bxmcq9JY18VP~LVwqcC!fPMf&ZW8bu+iopm0*%RKUj=r{@qt^3_`UR=C#?q zt&gbP>&un4+DviOYY*CKJGM^acRstDcU<%RP4W#XoHg~y&UE(u^0D5PTD^HwouVJe z%pbc8(Hc5gSNgXP)@;m+{*jA{VdAW*Ll(@uD{R&RBI4Rf3+r`jM+2VUx9IEfnTQ*R z$KTTQxjJ9p_URtGlnSzH(J#&S`L*8eojw!&py2ZrXGov@?6$cOWUqt9#D_>~BZP=b zI!6Pb<7E##*86K7459MPjXIq~6nH*Q&0fX|tgABwQ~w*;^10K({V2Yo(1+QSjxL8G zp_@I@CXU&jV6DJ#-9<&M)pDAqa!`GuiI9fa|Cg@wGspVDs1{>IxXZKHZyvVBlTVZc z{V%?R?FH?AP9Klu`(Z3`l2iV`>eakWowaVfxjel#x-yo&nQ20>f`CfgU7;8SJ!sk`hfsSMnoa>R?;Yo6vnF4ca zGhi=QTG3p(a^Srb)oR~Wr=DG}?f9S8Zs>FGE30l?X+T=v&!KOEp)_rBwgZ38D%kt; zs8n73Vb=M(LwgkYn=QTkm#+h^=$KF=P1d@pV|4gErzoEOJ6z*fi)n+m0IRM$VP+QX zsLx^=-!k~FXr`s;iyH6YyMtFq*CCcn#}_$`ta5za_f!HMM(!PJY|iwZ^d9#uaNmgd z2zmp8Pdzpr|s}#O}u$Xo_S^Vr}E?NJJ4qqYl zS$jXjEBpCZJ?X~fe}XArg7Qh%E0F<=_3OUkY?AM?jr-?^+9@hq#_NyMQg*mgg;I8^ zqAR+#;-itj^%BbpH-u`b1upme8)M}hn1qnB%Q^olWajQU_w`_EEqk}rv%cQhK7QAt z@aSa2;4|% z>Z4_CQ21NtpEm?Dk{AfmegTSn0KumY{36G2ojfeUG(8rY>wDpJ)3bQ`>8yLN;1>s( zswS~{xbT6fOC;awrXJ0L64i#YC9kRlS;$Fz{_=hZ)u&<#H*uMoCVfuPZ<+v}L~NKz z_HB$T;}_E1+xHOnaGvL4g;e)5WjTvRV;<_V6TcW%2q4jO0ly*O>SOLRb&tlGX<5+4 zFZRVX7{oWMuC1?00}^qgNv87gOe*0T91bFO-+CBpG3V-$e^B9Ws+M7-T@!ofuh9uK z#7y)IT4KsAa(5fPvFs8{dNk_#kbZl~tD!Yz@J~6TTE0??ViIMzaD2ICiS0wIys4*B&rUVSJhG?-B+tjwlY<$_=xQDV3hj6P~r=Q$K?wQbp{a* zi4`U`I4yySxZk zU1tJyz-z`_F7iw_Bp*`{@e-+8U!^x|+r@1EZqTi+*UQh6Y?OQK>}|Zda_GOQ{gA%!b(v~Nhu=hyC{RgJp>eD)gVVNAYN zBx-h!ZCC5?0D9Uj=Q|!(rl}r-R!#eDW2hg~Tc<9*eWd5kF)G(v6wK&8=7l5wHdl%` zOir?E-&b0)FY{E8Ck@41B4OX9rdSafja7GR9E{|?5y^G7)o8Xv-Y$4bJdks{5*Hq= zkFaagkSWo+=ns^Z<4pB5v_l-sOLZx;91Zk^9V z@7guk|J){y@R{uNZt3+4auYN^rrgg;Hi}V$_+*5Ak<~|>F=x0tOw+1U6sQed@H17+GC!!*ASuy>0%>qGxU6>-Qf* z-l=3}xN_Kgw$Ason6NOyW=HPU`4F=?M3I075jWb=WBZp3O}Wdi>3L{dOXeP)Ww@>) zbm9XobX;7?`+g^+Yw7JhizidbKOFtW$hAfOs6z|4A^5Jruc6clog($8MK)!G@ze6zFRNa z%So1Sn&uchneWrF?X~VWoBZ!m=yl9p`y#TB75A9tq$BXC{?e=U?9bQj`gn$eqF|y1 z%d_q5oAvP{^4qPUOrL=M&D2BtCoRign8N}AQ8$)Z-|0WjcrIn1c5{il?%a#!#|vH& z>Oo6JVRSi9QO!X;O?0D2$XS5=6Jbn&gD8UF*Ux>9d;<6mO&3*U z7v|`#Ej}Lhj5pkln4BQY2>?O!2Pu6((LN0E{=CsX7;sxow0BH=M^60pAf?1kyys55 za7{ER2r7XCPoO~%G|5M7jB;m4WVA-Y1TB0g^4;B+fPwjw4%@oQ*mg;~(6Oh5(n-Zn zl7tanWu0Mx2647E2{i=o>>$`_oJjmAuH84L%+N+=QsBA-5wxR8n*9SkYrqJgCVC@BJtE>({h1!)p!z5TNKxh7Y&*H85z zYP%$%-Pov%q`N$kXif5;ydWGNi<~%u5yC2#!8jibR2&2KL8tgnB=cf25EpU0DbZSf zDOXDwpsr-FamHN?)U1g_1PcoQ!RqXgR9Z1KwIOOthW^c|94I$9p-IG$27t35>?EJ8 zyxku^eczFW>u}uCOcGws-i}GLvt?qli#xO<{6zpO*u&I8Pzw?GT>vT?nyH%$)-ui| zRQdJnb90O{vL#dPqo-}X}v9P`>*au2W%nj(oZ@d^vo@?bqjJ|`wV%t@yQkTJXI z@gz`c5d5XbV^V4r^Ph;8 zP1z$4W~T6;45@?>hldHJ{$~1$F@$TA=$9)@Lj-OHDw0JLu%_f{*cvqu;Z-h5pg4%s z)u_4Fq;}WHDi#r9%H4SiYJy9pDU+bXt&^#4Bq4u;iJ{esY`Gu<(11<~V7E(UvH~>A z0=<4z7P5-bs*ZoSUr@(Y^>-Io$MS!Nx?=z_>ngeaI4e&v@}!x!UuSwU@F;+R@Tb6iK;9QjeY zo~ZOS&cHE0Cl*!XJ|Nq)gz$1+2^v*wfQXPmfD%uCu=yl-g#_y5S{8Aa$a0XB1NYpsu!Lmn?v)%HPNg~qNSD(=cf|u9S9!3Zh74b)}JY@@Ki1SA@up8dg z-F*LBlF%L#L!Q+0vy*3he{H(+(pI|(lb?9u+794ObKw-R1*q|(c4N6;@s<_@ebsCm z(Cxh6UOw4k6Z%R6L}XD?UEPKF#b1ZzOSP4*RLO~nigypWAS$v47VU_-*=O@)@~|Awo-!R=)-Zl|C-S*(oPT^9VG?p* z2HX!cYG7YkDz-mkF5>MOVwNv*xoQ`frhK^B(mzZQSavcv19)Zkvy~7;n{l{w(!p#9)MvQslAl=pY`|HpC-GS{C1 zz-kD;5eO;K5n(}gkuA*KpCcc|(`CuC{N<*V*5@q*CzPE>@krv{JHAF!s0W3b%vSVg z|II7N(`?D-AQO57k6_klILpnvzw__LJ70P;`X=J2#cqG!N@2Y>1x$FVM~+7VqL8}P zf=868&QLrE$t<$`EOZfjv#NA6>n#Y+OC(|jA-fWZtdA%|1xq4xLUJZYi1jsSK z898#B^$Yu})w3H)$r2>9Xv|Gwj3&aiQG|`K=8`~Dc^q(*NN(A$yl!A2|Cj>b1``Vf zrh?c|8d$25Ysw@XkmUNU+z>qmqLsD?+ep>wNoitC0w(&HK4BN8Y{|`1K}08;8oYqP zp`-3N?P?^M{>J9I8@Lngg+D^zP+v*FP^c2I0=UW<{=KnrK`88t?GTj23PhLsjmYg= zFn)s?DBKBt0FGzhRvxPSn)+Yrw77piiZz(};@u7r3Z!xTE%7TGRZ*3(*AI*IUG}gw zW)U`3G!SV4Xej_(gkjVXB|8>OtV97A;Gk~EVHM%m&-Ubhe`zR(n;laW6dinK|MJoQ&&Q?{YOf*(>xI3qM!FD8s8lhp|AwGuEA0H4|!C+Rz_>?@@)=y&g zU5Mqe)EnaXX5^05G0SWIf&{=2OO*#gF;U91hMZVX@8hvYFw_ZMGZbR5&&zxN_f(Sb zTGIbK)#L^UIyblk{`dL4UxZaDIhaH-c7Ghc>vcYvg6?pAsSH!sAkN44=(ejiU9D+{9m^@Ve)@=C`9J3?i-z$JT6x`!(~z7#E(UCMy+1 zQyb{}(X4Bzvhh|Zb*W0Qr()(meN!@`llZQC$D-9bQEjZIJnfr3_w%s(6uA#m*~IvY z9QJN#f8>g7op1=jEc~`#-Yp%Y3N*iWL02sO;0KMqv34tu(mih3g}htuNw~E9%Pz3l zdK_JbC1F{yycN)A_D`yPwN^6ApIRHE>iDYoN_888@l1~zEZ#mf%#7wIrE09IGWndv z@NCjCQiRG8>yYFv)!>6uYF(;dB@DT zol>p#d)1xV)gx`TIl;`Cg@Dlw}@bc*Odj?|0-YGIMxkvP}6 znEwQb*)`Gzxi?;T}D}nOgMC_ z6gYjWvPc4tdr(q#7|6p)=nL2y!t8I&RNNDE$KY@%TFAvqMWVX@UJ!Uc!d|;vMtj<3 zRTC^M2l3Q-BbCshbuFYsMUSO z!@5~Q@y-5m46f%^uTZrR!^!WaKYaDt_Sy@%?=xD`-X1(1m@=O5eoEX5g8r|^HW#e& zs)m*y6Q*q>(+hpA`f|r|Io7}%pS1~piZ0wMnl#;T(W$$&ZUY#6SuSZkMd!C2JmDcT zoC@~p%9%fSQhK$P1?OUE#Slq044FFy+O)1o3)-)WZgefoSNqR9I^CGeuB;f6jru+p z`k`Yfx4hWjwc{M@Guxah=^piw{K$BkX>(W1sQZIplSjSWf_Bu&t?{4<8N=E2Lnds` z=c8A5SDLL(^4eM5+wS;>?R_jgJFV%Lt_$FCg?jD06%*ke6MxELWA=$b|Dy62U8V7W zj9+^+>iNDlO&}JcLf}~46Z0aQG3L^zXIFYP0q{D7@|%u;Xn!1f_gt+bqZda!Zff-{ zO&3qw>B|rGBJY)<$Q_z;@k}n>zw?)Mw{4gF#ze;4l6+=tik?u#Nbo()xaE}IUPdz+ z^Pshi{+*rb>LU&tr(u4iD@@zyV$P^vEUUS|UMPf~xm>WZMy+A7hiaaTf6R^qEt+Vr zSw7#CbXspKNG?5+`+m0b&9kGP&-Z?L+;$f@RDu^~sYqQeO+08XH=v5-H@ck5@@}t^ zdS~w7%e z$=yd?{*QSh#+Kxhd)8Zfo+$;v$4RBUSQu7JMZup_V_99#X4l3Q_+dMWdx~ ztFIGBvWq?U{A}!QPHsm>Exj{8Gu@W`kv1o#|Kq{s9DOIp$b=&N?EPhlKKqV8&m{`} z;7vW9y7-S$GC zd!0rH+H|-dsgvK(KX{>Gcg`LvB<(}MD~OeV2tn1|lu+6u57LRC4Maf0cBm$OSi6RE zfp^%RhDkpbM&N7eKA{{^3_(ZxWlFu|Tynd#_2%!?p%3$*_#JM+>w^%DxW+&U?Kk2Y zknB>BT}@QLU;ocMVc(>}5R0x%a3bc;NL>QQ6ys;G6#X0V65SEls7}tx?hndgx6Fx= zB`g@RAX;8%CR$4(a7~NcR;w5FS5hl9Rnd`j()yztZ0A$)IIwf zHntu2>WO=x}GXvb$pylRFfDu;j6V0mL?Ad_LolKh}BC};8LP1GdBu*U^qOhD!FY0%DCz@T#n?Z|O%P$)YCnFj{c$R<|MUqc7 zqi$Q`PESAW*6#>{0O=@Qah41{V5{Gc1*wwcSYl76}g zcS(t}#i39n;pqe+8Hku&_UR{jiaR*aer=guUe)0)ER28x!uW590LiXEper;3NPAWT zky|MzA+1Q^tB}{Oc+Q8EFM-vGfKAY)`Szs-_`1RxyGk-eu((pvUk&#kbXC@}K3gCN zPhC~fWi2rd6b?|hFOn0XQ568v1jvz<&5@VQ4JNHg)2tB15m{o1w9$x|ha6kt16H6O@t)S2&=Ce zL=($N!JtYMw57y;AQBTaQdYKJey>sXs4k2@mQZEI8Q0W>I(#xN)St@IwX38Vgk%w( zUnUyP3BS3`*8*(O*Ov`~%BLi$c|-tM z6D+QzyWW(Tpfn=Ghax5kpjt)n_jtsJHtFD<-jRLQi)zZ}(c$7%y}ABQp*ZNzuA)M+ zK3md0+zPZvq&u!1IFs#wib5FNNFmL|Iw{?-ranNvSLX=LW#sJ?W$PE2I^Irj_z_w6 zRPma$U&dG6W8hf1VVkQFcHK7x zI&UN~aQaZPUYs4pF+u`WjUIx**=y_ANsh;!_efeUJ{{qRv+DxL>5pLNa>Ggm1HVXy zInBnD)}Z>X;MtU6s4n1z1>R$T#c8UTO_4}xn=3E9+3Mc7tdUOu5|4qOUs2vGDC3eJ zjl;{2?Zu8gz)lc`u6Wn~4P7DEPsv2bJ=U1-=d)kX>X^v;la7&fqW?FKwRQyx@+Z)1 z6VVA{7jgh$+X^{`HK-%A0|6_-hhb5GA~mRF zFlL z98c3UD19??S{x@EZHlXFVET|UO3sa%23XzhP>-VlFvjlc+Pfx&Y{!+2ups4XdxIAt zp##IA?4)q351a9F3O**t@6O^43%IXov`99=I&B?d}=RW5NnzMaHo*n z6hs9-qIAbGm$-gZO{97fno9PQ7KizyTgbR@1i0w}>`lNv7I^0h7_cHfe){w$wGs|S zGKx{)2SEro7^D;i5A(PmgfcQ;fQBuYu@*@HlH_{8^Pj-4PSh`!MKkgRLe-Apc#e?+ zoOXiz_jd6#j06glK&|J<$Az< z5h{r3flf5U;^1)M^f1x(q*tQI^j1 z_N|#)foE>kqEv`+3hQcRV242}#0}*`z4f&lRuRS{O2WQzF_B6TxBg@O&Tinwo;hbw zFT?+L)r>~dsYEFpK~1MS(X=&SO90?Fb*6k7jb}gzjXpcJR7+$O4@SzkRj8zMKCJ7F zaj%??XR(};XYi=f$d^`G$e47i9*w(gN)gHMpPg!%j2n~Q6wY=$o$H1AHLqvwaM*)J zvAa2U%Re?^hl2HFB-u3@(fGn=olTodEe<38&UuE1O0AqWU(CC*?Ul-dGTq;5KdIE} zMD=i!3t*1*N4?o?Rr&w3epkfL_2y+)u7^c?-p>_@T|?X5;j*t)7UuL;cGC?uJ%NI9 z#}B&_;`4qUP&HZRw>px2)@%3K+Z+kgf6VG#`>@k;pgk~2l=~z*fR%Y5zxTyqW7=yT zyoPk}mEDG{_&8fW^N#9q%~p1`%&i{m@o0a17QU+=k0;Np%+(xQmOBd&&Jh1#S^r8Tt05FFI=a zJ58akiT4sNLFiw)j;~g8*TY;>mrTp}`AS310{h|4FS)xxnqPHYWnWh3ID0elB!%S3 z07Wl;)N&T1{G@k^NcSf59_v%kmFT6D{^dv$^6Jj3NmAD?R;^$otxV9J&*85lsl(@O zX?JGK@78OUmisvXbecdA$EXL3r5zO>`5kaltS+A#CJ^`LqFUmW!- zyj%Q7FB`x3k3#jS`PG8deE4xs$a-VzlNqHDwok!7>cTy||;39nL zY6a6l1D{@3HV8R>?}8(Go%@C9_(U3hC3bup&KU0erL)FekX}J=-n%o&mpfzSYGWPn z{n^FX%+_0udefqkOj6s|8F!=e8U}c$XK2e+FXaoSsB_~zm33A>wU*u9o<8n$ue|hp zV#I9r{KFX2dfO`&cZHNmV>0Knvb&b+zehUM1KZzO=}moEQyXa99aP$$IvS$N#FPI~ z?TTS3|Lo0tLD|<6Q%Li{1ZUVpjhC^5va=xpndmMmzpEqwgnt(`yry-yh| z;o*_a`c@@`n=308GTJZr`%`SA1bT28-W=W9qtttJ65y_veOTOCSdX+_FuwEtPe`Bm z-M~L1N=aw?PmF?5r@wzbxH-Dz{;T(ox7WSk&zq|jF4}9iI0IFF-V!pnt~(3t*V)zJ zl)dpj7RFph?iY52+sar3Ip5Lgw)8989!T*06>{|Oq0F~t$o+FAfPSXrR=Z-9dnDBV z=1K!PuQ41^BN(7`d;ahs^FE53i{+#fi@wA~v;DzBrAD{NeU>8bC2#-?YszH!aq;0C zKga*nI4$RxIAj7czlN7DZNXhN-}3#y#66thpn#%??`J>*7_`brmU-@rbT=iCpuTFG z5%ErPHHC`pvOtTC`a_(QfbyC$+O~;tmXqUT=A8(1J9aGc+8XVEv|$SCP?c5|xV_EH z@i(JNGmSGXp?USKP?@NTqW?*H3GykLDNK{N$PFExfW58rjDPd6Ijn}Fwmr7a={=+h(T};o4 z<&gwm@8DK=!4KVPW%};-R&^ewK#;9Ubk}>nxi^Mq2~~;@)3jd*iE*$6eb>3JQvP`= zej5^4rQrCI%$kr31Btb|w%Q+azhHn-to>#rPp?^cWzfe2uJZ?^!=Et16~DK=cL4IMUoTpz{iWKB6eKjuP977938{(fkf$$y%` z&c3Irt)z|z9>0Ni?@Lp58}*;vCEU(vFj6=^dBxq{)Rfq0mC0_pgl}1Bd%O;!69N)9 z&b%6A$qUq9T%@r}!;laqp-@HB2_gzUZy)nri*f#ijsGH;QU)Q8js%kv0U~U){?p6g z%5=)`tmrB~)}8T7d@hY*h?m)ShlR`gd#Atq2R3)5^Ye;7mSr)`rHn}kp`*w{{|*wL zxloR}hS_U=?fz6FWI35<5MGtZi4oC^B5&C!*s&^hbFQaapQ5Rl`&+G`XZEn#aebfE zm+7)|kh(R0lZj^u{=`>Vq-tvuk=)TM)3z=C)Bj6+s}0)SPBW?xNFxzZWrH8{Nqyzd zOQG`%kmfsK4@vzT&eYoa!OktzPXMF^D~DR|gi!-c&zXB<@a+$phQhrBKx}`{$7g*V zo|Wf*&U|uPKo@Sj`@Bm(Bko6<5#58}p5D*9Q5OR?MNynEbSPF{3Hb!`hFbFG2a{YW zIR8+IaS9iP#hBbuICFdP*1;lE+k-y#!GzSmu*3-05%f<@v4;%D$#$V6>~dl{Qea7N^W2t|7Ge7_U}(R`Y*(hBLx&SY>HylukCdi5PSWRa}4m>s8mg?^!>q zmcsU*4mNoa##%^Tb|MhDOMu+RxA^NnP>#V9;)H;YJ3>y~AKo1z z8rHrG`-GD>W1@UJO1_=`a0?y3V@z7!@tIt7@P5WW%1}$yO}riA6Jv|jnYtP3Ew z@ix&dVhLo+WfU)qWSiKt|E|r8;weYZrhka(R|Yt1uIA3Y;q4NADiHNzJEeW!WpGMq z^RKICIWy8Pm|DIGGBnV8>;@krIOT0@KngqOLjHK;%HF_}4R?WdcaM|#gRcXNdk4J&e%x$VD)79N^SmcNir9L)LA=F1?+-1tv zBVybq2;uuF+BZDf^(@r}FXR|IgqI9Ij)p zbjaQ!D~Ym6lG;3=X}%WwRMiKcf{T9fFoy z1j_SSce~gQlz?L*v-$-0zaTx39T72*y} zLWgpu3e^N9ubce~w0kNNET|lj0K${WE|Vh3>B{khMLgdT-qS@}%@yIG7o(v>@0%D? zWFf&l@5+x);V4h%SPNj>Pgt(>V$n?fRUP!!+)fK|*H1U8$Suj4aD7WLO~N9Lpd2Ep zo5r-~zM*qR*$h^=n2ObVkPSjy(+!|5s-%95r;h{VvIXIHBx_uTFYsD&8Xn zMJewSU_nWHOb-x13tq#3e$HjaKV%J|PIz;C^=FDKGWChtLq~6ajraLO^t1lfy zB3)@Tdm zv|MbVnmh+tsv57RjedJ+prVK|O! z6J7t*CzzF19y|4J*9E0CH5Ap}nJOqr3Z?Yi-sC`6tpZ#ajM>rDU7qtAHvYof)$hMR2|OpDUa%} zg)Ox7MZ3p$HEZ-+kC}Wh)O`Xq0|(dFq;Vk982E_(%qQYzfaBiB9&8O8W=*e&-tCx& zN^~VV%XNWt=|alx-;NuQTSVP|W2uf|0&bZELxU(Y3^3CwD&Wd|!Zd%( z6hdI}*J!5rfFNK-(9c%0Mz8w~7MZY0UnTk>j)(Orq`W`XA^PS8Vdy0i%DI@8K)mwj zVOLOy#imNO-&9>neFs*h8iKrgJ-GXAQUVqX=9=x4!FMXRHj2r0WZUqZg{4Z4RjSP++2^?9X|z|Tsw}|Z>5m|Qw@Cm%{KiU`_U8hah|TF|D5gWIy~lS@3D?O=*Q8$ zO6XU_({N=$##RO{;`>)Ao&#@fifOBzBMg7ujJ(Np4e$GwHJ4Aar$ZR__*vL$GN_MLn zQgNh)xQ5R2GLK_{`Txn7{WN>~E?#<1KP-JZyeGjTDhc>r26R+-?*lwyQ$r{8BkH`v z^LEjQ=u4_OrS5kF~Cic|T(I zA~HvBM){pMK1QRTN$)ofiBFL9CUhkyOWE z?`BxP0Z5?ePJj^Vq4;z^bNJI|5x%P38sJ~ z|BIb!fP+9F1O-GvvL5}v_90iD7%!;j762AnsjTuItV!q!%}l5qH)~H8|3tQ^VKzhI zf2B&YcBMx8ZR_I?74NpanPd?f&6DDP+27q>J6oxXS2SzzcYB66mbboVeQ^FxgJHS4 z6xSifyh0%>ab^N(|#S-`cK?gYAO&n3T&x1_s2-i!A& zIKS@r))4fbJNQ;rbop_ocfg-7$+h|?H~w`Wel4$;xEx^@uI%vjiR0~8Qg$LMS^k$( zDG7|XH&%0qtxsPxmG*^y6CUb&Kp7nLYv<}4o9{o@6Ipe3rerQXisW<%${BdWCMQwt zOpIoN9r59Bon0^2pQ6qqXL9fM;XRcoT@o&D7lNyzoFdyW@S#9dG!BOomI_AA)(2RnGT& zK%sXH9CViK479l?nd5EwREYU52}{+6Tv37i#V*2}mZhxCmYa`ou#~k#5re~8)4-ox z+{P)xR;6AR4cboeca67PDvi}s=CC{$gTCmL-P#c~;F_`$HFCJf?j9$}&Dr4cr-btN zZR6eTz$G1bmw9GMok!N0SCYAQP09Bg8ntIP>r6Y^cXm9l zzjO)TZdVl80djKQ!q=spOp~Okx4Dzb)(F*9sZQ>chHu@6JraaLQu*^AgLVIYJvI={ z=KkbM8{7At47yubJNR`@V)5aNWr-@Co1Ggn-G_{$vbPSRY&qL``#c;cMb{hKGzDta z7FuE9yEDUb9g_0b6@wXWzf@Uo`jTSyIi_H=)g?}P_G;Pg-cHTP1`=X=r0d~ZF7Iui*E70SJ30nufAn4+J^gvf z^FZy^cNfdk;sN+d`%mT@H;-&STz!5eV<+R^hhJ;AbEB?Jcm3NxM(ImqwjY*UiSqh7 zTy|*_y-f+deoS9R*|E6vXGZ3J&-(eY(`TtLMIVlS9ERrHBKe<{iGZ=^iV9U(Ds{9L z8wJo{Xx0*?Hewk*Th1Q;JM8Lr-nO%h<+Fmhou^x#Nnq*cr!DzY=0_M}k3o!zQo=Mw z1%89*wY8j>bmUSr2tM=^EAJN7TnA|w@5MvP9iJD}jz}x+aoG1evS(cziBlM6!XvcM zN?0vL?)`KhuL=<#e9J`_8a+R{oSB2}an0(MP?UcO#P#hJ&4i5m7EkDR2lX^%gJ!cF zS=X=5xsK-&J?UdOpTXXB>kG8aQXP*%yqQO1rU(IUi%Q_U3UdwD3q7}%G$Co6pkX7; zO-ah9_n;pfISz=?{J}>XGGv6lF7xYD!o8}Cp^io_jDiI-5hd4StR`ZcFhKF{J(25w z^_7EO=TvG5u#+%QGvl9_+v|5F9JdW%XP;&2Lu=KxkgqIXJ_~nk6tt?VrwqCpXBR4} z317%mnRXVZa!G7%n&7FMZ5!7B@{Eg8*WVi^#sRrLx$&3;SNm75QN~AhQOuuu zQ4^J&V~i3~uJzE8q`79dbFcO?<>Fkf&N`PvdV=M+!P~Ydwk9{bq|KShLCE(XqVgs5 zvgj0(gzo`$>K%=C+XfZ`Z|~HNnti#NP{{maA5yGn+2GVZ`QllNZ?X5ND7*FAW4r0L zk{?>`R`vYmFK?~4&w->aT{~HtD++3QV~J?CH<%DL{nf$n%u^m}xDrSCd8hNqIS+@x zJ`34nf08sh4#ix&h+E$V84JI>zI5kFkRo?QUP4f{9O_$8F!#sL z(!nE*?`Mnhxz)TpAw1S&C9uw}?*pFqJtZ8D-R&iT}*9C{1vZ`Dq-#B(5}n&dj?M2#{f=U5RA|du>`%IA*mmL5%jSf{mW zqP!$d{CedSr2D62OT=gKSCHp-N_7%tB3SKzw+UVT_c`qWuY=jlBIU(#ynJ!6_?F5z zM>lLu%uQS;yy6zwPD0Ia2uMyIn`gzM4+r5jEE{7Fc!`VXHx3R3GP3 z$;sIKMfB^1QL}`xd?oKRm&+$hGZ{hcB2wiz$MqWAVD4O?${pos&`s$n0 zH(wXh(Qx<0_n_M4cZzS5&gZVth-@5>U;PmH7^$}E#mqHHl)MgSL^-?LDlgf%bUvw! z1iLHoF6SiZA5BNR%=ao5_fz zZ#y#mo73!gg2`u$0e8bq5=0o(INvC@CbSxPCtN*Q({tz^DIU0-?pDk{-FIYTqWLw} z2DO!)?h4<$yeJdJK=Y;#jPi+@_BQ!t%ha`b{LkMH zofcop6tOBbZg){BUc{n9U=OYWnJ~4w!81w9lH9LCCdKhJ~;QQ zq_%%d{{~uN`W+G-qCxY?*x&Y}&BxJiN?F&Jg3Bn8s~U9*Yk41bt7K01`jy5;*g}V5 zHPnU7D7ru8Az{;H{l8`?5x=S(em;)=_t%{xa5 zkMw}!nU(RZmiT#Bd=W<&$_-fC3i7E96MWF~$ zn;eYqadiKc1d$+H7BThtQ4RS~j)-6s2~1U!{tk{-I0_D5jaCf_0J(*z)CF*?I^0+g zg-zfXyW^rn@eKQkF^iGgK>*zzd}=j_&oW+^6KqfEhOEudP@zbu4Cm@j}SIn`w` z34@Kw{1U%uk@2)3?2d92nUrR^n(VZfHlysLUdwW}5R$YIGIT3Rh(FbQD;=UjVCO^^ zW9dFw#y40*eNM{wQkNlI5alwFe1%%70#CU~PEfF9qLOjvu&lwNi3YB^?w#JCzlI%} z1o58ie_sGP5Uge|Xk9mfVTrJf$a18Fr1{jQMFN>+%9-4S(Y#b5PJ`Ox%dRZy{b1-O zk0@}1E3RiK`<5613Pzy7v^5|GGrb%k%M2xC0y;EpX91K)0`GlE8>z{nB7;;fQam{E z??iy;-%PqA1q-FT5UW&Z76@Gq5(07tCh{)TXHZF@%lcXC8);mBgQ+dVQ~+-f1jAyv z`v2INz->+89>}cxM}HF;vcOPZIJ^}Zh^5OT5;l%fvC0Vvg=unbS&{HuDn#dL1;K)7 zDKm_1jsdd!xhUW4!`Z^&!Z@)kIxGoVu!k2$JRB3vQr)KE!66UxvwT+zI{%_zYY!h@fIjIde*-@-Y)647d#l)rq1lL`tQ4 z3#a~6l(=&cmze!<7t#`$?*~p@~$|# zMzqFVoZZ=gz%T@lD2GDJAx>+sh%9%xwPLg58na12M3y5Uh1r*gKE!f4iG#ciYN99} zspx$KX`hz5f@#=e4lyX?0zXRKsYu@`yn=>`%GEJCR+u`a6nk)$?9_`=Q7s=jJ$?qY zJtk3A@M=X}aeaO5RDFF|9D^wxwQmxYg$Nz4>9OYQv&O&UZ+O<*)E?4QB7%L+1M+kg{^xZcfx}AGhv+>Fr3cUs?7;a&F zE@G(1PNj9YhDdT*5C(iJ65aAnvx(>HMY`u4FIV|eh@z`KZSLH(NQx$rgl@lUS|?V{ z6gzxb%CNnsmjSKW3U!2;g*jjAd%}vZK<>Ats-lc8ckp;NKpc(DiaWUQ?NI(&r&dtH zF%zQ?;0dy@4)3G@jbi+yeN_OU4z8)4e#IJBr+^4|Ry7G=HVj|@v4~&p!kw^-7NZp# zyPV3sDw(@e4AFrnOg{kh|KV4VnvAL8J&TAoG#;u~1U%|PFJXWexSlE-&XpNJi-=~% z08o?O7SHpkvVZ{@5F~TlJz<{Q>rJ(R%k4w#mVq?_aFy6M`kbS^7`TN&laKjM#AW4e z`fxrh#z+dh;up zJ%W{Y1{k7-A>R#I+|~a7Pa*K?k^WOFBh?Kj{-;)^{gjfl$NwyqQ%wDl9^t}x8b&DL z)YZ3YEKcagHQT!XP2EVo)1yq6v0OR-9foB8svCq+w|@%V?T)W1gfq>j-R0cIldgN} zsMWpUztw0W|Ea+sTf)3R{&B`ZN`TvZvMIXev;M8m=B*aDYi#MenkV|Kv$CH}WIHVn z=-+wxBq_B;e*_9%V2dyn(|wl4A+jsM)%GSei77g=FSp#e2A{lnBdy2TWs)L#H)3Mh zfB3a;Wleng@#n4OI`>SoNUq=?edpP}{=T8M^=j=Y&w9M)FU9Q{ReGjeKK~!@nrNe= zU}8qvBA8|C_ zSoE=4MG8OW&!>UF<{i!u}U z^||)MqcZV3C3&-nad3HqnCj~$9^I$jZ5?7-V|6$9`ui_C+QG{WVs08Gb=z8H8Tz$3 zbJwg^<2eL^t2;P#RJL2=Q+g!tPfZzottWqid51k7HotG!C&@0O`AcWitrM}iBNa84 zGXK7>bP{PUUl;!pmF6c`!H|$ zXMrk_S#Nf(*$K@r-YN-riE&TgX|oUS4~$OXdxVa66e$Wa<@jFVC+#VduHgH5nY*n{ z?W@tgw0|OnRq0lQ;Zj#kWW{OM{7>shUzd+`QXx)T+!Kh$V;@mHPu4K9Lm;74I7T$C> zarQjbm7L8VxBD;M;C4@tf6`Fr=TGW)r=>34a}mxcml0TXfjR4F%q8YxQlq3mnL+Z@ z?P00Bi0hxr=7I)U)qNiNpapq@(I}~ZKOcQD5|KFp5TTaSN$e~e#?o(%?(+F3{T{8o zSkgn8_GP~P@Sws)(J=G{p8HJ^?WNBkyP#okTKFQyI;Uoi=26t#L$ZU$Xzh7Hp^qWd zCgB>wi>0%#&DSo|8!U@#(#t=eI}_R6KnxyGrsoT-Bi zBR197#cvgS)}|54D_@E?&gDF~IHE0`QZ!q2JYUIi_VxDJ@H3l)|bSQqKz=_nB|H8{hu5am6sY10|^OpM6%f$XDOill;HlgD?dUh9!YL)!4j!?g)8^A$z_UrZ9^Si>d|G zNss_HOH{)BL-CKd-v$fj(%z5yEAj3zv&GYAXC5L@qt$zzPkQ9-D)y7Ah8P-5GC~5I zgOam8xtYYCvm}!eW>3}_Brc3tzVv%oZREUnA4JcQlu&S+*O9$;t`xDsujw}Ja>{+1 zGWOu1m&<3~w>(?j8IJ<%t;dn~@NMYEH}Ca-t|l+&Ia@pvWtYEHhfWjq{5wm?cv98+ z&Qw-rdGelp>-3(H`o#T9W5b^x6mO|{a4#&rIVow!Wzu7#F0y0<+trjUt-JFts|si| zcSQCa-_B$2l{Jh?sHo>hxf`uRoEFJd`7d_$9%wLd6eK9H-$>Vzx9UoZyriS`;@jGk z<(n!#=@QpR4lh0&RW<+aIQM*c>oW7L+c^Ur_tO3v?;2PxzLEZ|AefaPqTIU#a_vNs z_TuD?t}nkHJc!FTn)ed9xj?(!Ir^UAe#&_Fil1UfwEm4P$|ryF?!!yj^K^PP@|@BD zg(K-p^W@Hw-wjOgn5uy0!n#^WDZ@4olli1T*>zK(tLxd`hLtd6> z{3(ULqxMyVGEJGlx?kgb6uw{Iz<}hm$|G4v}@5yT8Tpqi-AsZtgnEMk9dUAw2TmCv_2W*r(Bmdfsb>;tt2(F$Q{4rjnrI^GiNNEJy2xZ*G*2;W|u z1Q1Uh-7&K9cP!&gIpfzb@lW!Djfr}?6S#B#8`?}jFeO<$(!!fQ82@<8f%^#0E1H;L zktiV&Gdu1rC>kmz>dWyb(YJ;weegJCb<_5xYB9W6VE!?#49OHM2nM1(*b4Kj)w382 zN0Fj2dvR+ssP_bbI^R!UnJvZ{bH-N{#NSTB4O#?qvL!gpfOS9_bVTah>aCL) zaMvZ(g zxaI-X^CJaZK^x41$G!$=XQR%R4lin%OTV z7qFRtA7N<}a2fJF8Q;ESm>p$U92K7~#Q!Pq&x)gU)`)0VfziprK59fmWC;dVsf(Mo z`!KWo!jff`Jd33g%fE#Y%0(3v_t0~RE}xaI&4;M?3uiA?yNwB>vZ?LSAR4Nx>B-Wg zM<8eqQl~pH`FjWs_cwpU9S57pKRVK$)X(j(D*jK`1fm%uCggA0-#>C$>?z^&C@e}Y z#3*NdL>8G@cyM!><8%zS3RNX^t#n3XT>X;7q*cuy{>=2e}%8&2c^FGQrL|3u}gMDS=dqbcsV3WfrNs9L73M(F&>K1 zZgmS~wVykp{f$LKZIMR0P2s_^XUKd}YLHI|8AAQ2;ABYWF%9?xCu9P-8uC96(_YX2 z^)RiD{O4i9JpE-jswO$Ay*Hw-HmWMyOVu#xVo~2@!7M(5-97LiL$LTMf(Azu;^RZt zRlhaWZ+)E0!`oe~(g1LkcKmKf;s=`Lts>glj(%5&^$$z-gYHvRSEMRuy=Q)VC|y}v zWrmKjlfiv@kUpgemG*9eLY^>W0PU@eieow)_GoWoN3b(}0nft@O_=DhNQqN~Bn}Rp zOt1(Wa_ygT^Xj&A&$y^}j4L$ntk< zcvlnEnx^T0>L;v%ayMaOB|i%>q8s2P8C@R1V&IC?gSMa!Q2#Ws5&9wx{Bn1O@x=^- zRPS3}DD0G0nfSuYtF3VyOf;gC=zk6;fer~Uoh~==PWOiCmy*rZ7kRR(j$7`jF#Ax{ zhBXbxwN@a(jl=u{G*udNhz1}+<5}Q0!+lJ!A{AvzilQ#O>b_zf5UvPx0}98j!c{1^x~cEvxCIv4@oq-` zf6$EpmR5To_S^$J+==&_i|&uy6BdIy0sV}RmTE~$_Gho3rVS2aCUku! z9k3I~7t?QS-#wG+Wwo1KoMyUBe1SE2#tWjMr&3>35|Owx##8HeOrroozNToPUXg98 zBbPT&c|}XrBS!)EEM7Mc-0|$SnLP_NS0&M2HJrH$d?u(4cv7K9D zRHya74A&qGR}hy}qt->R{hbZ(?;gR}W#J#svFez8!tynoql*#$_g3=XJ$8VWe-#>N z_i^Mo#1OZR^ns{G(N&Pw>Gz%|Ym9VY7n262>FhQpr8;c)=z4*;a0-rrRpWgHX(=FT z9Vxq|8~&N+JCq-wWye706_+pYZI-Hc&-S@Ew=lnLA9zDRq>&MfdoW*<1s{X;2Q3IB z7XIWuOj!1FkThNV>hJ^^>`&UV26q3Cv1#Nb^%=Wp#B@q2Jl4(sg? ze4uFZ=e4uXoAy6n6@P!*M?Z=|L9hr0GQ%_(#7@Dii`g`eg#Yj<1pyf9RRfxcfn;Fe zNW!|xzaJtPI&kKJ-h%^5#(EIxSK`bs0o;BH7AZ;irg(E(0Sit8Kr3VfF9`KUgP~9M zgD_=V^anGwHSd*=mjXb$L_kfG5&W`ohd_%`^r1NgVTgrXApf!=(25Zt(yNfGOb380 zG21Hfa?#^#k>31{Qnu zDCXwh*pH_l_L!zW!mND$CYOQ2C})Ti5M$rqz9LiY;T|lSgj$+mSXl)DbSP@e0+t?KdOnt6O$*RNnY+?SZ16z@8Zz#p6MSN<&8&I)qLn?D}mfz_5+`FBdwTpMIOub!ee zo2ET-!PY$JO{DMo*!y! z8W4JgJ&w+IF^#bz*AN&U&z9sF4o){cm)Zn&%U8_WitQ5>&&3UmE-*i1G3|R!cNs6R zqjr)eLYKV+g~>K#5!7`gLp}{w9VAO>U}9P4Gz3x=<|OS)vo@vHOOv4L$i`L|16j$W z3*`xXx2k%7N%tD{jm9DT`_YrJ$o5}uVO8yiekrYd^yC7+m!86{KL_6uvl2M%;|_k^ zT+Uz(n7I%=6wmFJ(non5D8p#{2{>%UoyO*UG=8z%+2MydlPg zkpwySi1Am)WC5QRTVvnS5McTLK=XkMb%?`53&_%(t|_b}Vg&D%TQCfAsm-mVVcgM& zy=H`e{W+cA31xeh&yXs1BbgPP4#7kmK^gR$RfcgFGA73Gmgys}IrXD94(;vm^T7@s zQAkGad+dSP2}+Vj*VAQc3M%ZV|1_~#O1Od`{592G=02Go?b(d`a(##^hwNnN9Y)@Q zRi41YJDiCZ{*hKu-1qEQx!fv-*c=|kZUnoQPJW6naG&e`fvj-fTT2IcE#Yv-IQ>Ns z?c$jWi!8Q)a@|@@R634nxa~P(E9(_SJd-w^BR`WLJ|tF0bkOlANo;KO6Fu)+Uozx; zL{jKmM(aiSg-6iwX4hf*AL5g=Txqee%B)T@UOVKAK(gQ<=iRlsg){2l!MjQZ+;fI5 zd{r}08USAJPh8))XHxCR2q*6ir*^U7ic_V{Ou&iS-x>KIj5(Lg7r2IiZGARcFGlD`ROiWv50GX8UwR9w{xHvg&Vd0@qwJj9lrySz+ zs^~zEj6KMS3EIeq}Z#+SRKy&)mwNdR?uC@ige7d-W(Iw>C%P`biM*0`LKaDD+iW z5qcY|H`y!^y=1<$&C#y|Z0Y053BtmfNg%IEVrqAc`MP`j<7?*BYNeLx-PCWxCY76z+1W);7wpwVu4jRWSiwzN8Ac%-ebpKRZ$T{orq7nj%-@&% z-To;*)IMT4p}?z&`2F3!A#%Od>_@@YU%+Up-L3$~DDgmEv?SG5t7s(SpSGt(;{px@ Hy8QnDu6(%i literal 0 HcmV?d00001