{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "g-dGisms4jDt" }, "source": [ "This is a quick review of some basic python features that you will need to do your assignments.\n", "Of course, this is far from being exhaustive. We have put together some code snippets below.\n", "You should be able to run any piece on its own in python version 3.x - just place the cursor in\n", "the code cell you want to execute, then click on 'Cell/Run' or click on the \"play\" button.\n", "\n", "Python is indentation-sensitive by design – so, please follow the left-indentation that I have used. Otherwise,\n", "you will receive an 'IndentationError'. It doesn’t have to be the exact same amount of indentation, however.\n", "For example, if you see a tab, it means that there needs to be some left-indentation there;\n", "it could be just a single space (I just prefer tabs only for clarity). But if you don’t see any indentation,\n", "then there shouldn’t be any.\n", "\n", "Any line that starts with a '#' is a comment, that is Python does not execute it.\n", "\n", "Official Python documentation - http://python.org/doc/\n", "\n", "A popular book “A byte of python\" - http://www.swaroopch.com/notes/Python" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pkaqqe-Z4jDx" }, "outputs": [], "source": [ "#This command opens a python terminal that has gives you access to this notebook's namespace.\n", "#that is, variables you define within this notebook are only accessible through the special console\n", "#invoked by the command below. The default Python kernel or console you see below does not provide\n", "#you that acess. NOTE that this is a special iPython \"magic\" command, not a regular Python command.\n", "\n", "%qtconsole" ] }, { "cell_type": "markdown", "source": [ "# Programming: Basics" ], "metadata": { "id": "EMAJ5cHxCF7d" } }, { "cell_type": "markdown", "metadata": { "id": "17mUpGnQ4jD1" }, "source": [ "**Conditional logic** statements: Note how the else-if is implemented in python – it is ‘elif’.\n", "Also, notice the colon at the end of the conditions which is part of the syntax." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "dd8KMSJE4jD2", "outputId": "df5d2f5a-dceb-4dc2-9195-dc787870880f" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "x is < 1\n" ] } ], "source": [ "x = 0\n", "\n", "if x == 1:\n", "\tprint(\"x is 1\")\n", "elif x > 1:\n", "\tprint(\"x is > 1\")\n", "else:\n", "\tprint(\"x is < 1\")" ] }, { "cell_type": "markdown", "metadata": { "id": "dny8DVLu4jD2" }, "source": [ "**Loops**: Again note the colon at the end of the loop statements." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "canopy_exercise": { "cell_type": "" }, "colab": { "base_uri": "https://localhost:8080/" }, "id": "AZLB9A1x4jD2", "outputId": "772a2fb7-56ae-4b60-a6fd-56bd8661fadd" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "10\n" ] } ], "source": [ "x=0\n", "\n", "while x < 10:\n", "\t# The '+= ' which is typical in C also works in python\n", "\tx += 1\n", "\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "oBE6xLpd4jD3", "outputId": "037bf9e0-c922-4663-c9e4-9ec1c613446c" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "-35\n" ] } ], "source": [ "# range(0,10) returns a list of values from 0 through 9\n", "for i in range(0,10):\n", "\tx -= i\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "id": "HFhC-Kej4jD3" }, "source": [ "NOTE: All datatypes in Python have their indices starting from 0 as opposed to 1." ] }, { "cell_type": "markdown", "metadata": { "id": "KGFJDtb84jD3" }, "source": [ "**Lists**: A list is an indexed container where you can store a variety of elements like integers, decimals, and strings in the same list." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "a-M3-4Gj4jD3", "outputId": "d9ef6174-edb1-48ad-8bb0-bc93e96d727f" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[10, 'mad', 3.2, 'more']\n" ] } ], "source": [ "# List containing 3 different types of elements. Note the square brackets.\n", "L = [10, 'mad',3.2]\n", "\n", "# Append a string to the end of the list\n", "L.append('more')\n", "\n", "print(L)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "6z2JEpXl4jD3", "outputId": "7fe0924b-67d6-46e8-be01-324f046186d4" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "10\n" ] } ], "source": [ "# Access an element of the list; indices start with 0, and not 1\n", "print(L[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "HCI2z6924jD4", "outputId": "016a8355-9601-4885-bbc6-cd79c7bd3eaf" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "1\n" ] } ], "source": [ "# Retrieves the 'index' of 'mad' in L\n", "print(L.index('mad'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "wM31sqEz4jD4", "outputId": "5100dbac-31b2-4dfe-afdb-c8481249f411" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[10, 3.2, 'more']\n" ] } ], "source": [ "# Delete the element stored at index 1\n", "del L[1]\n", "\n", "print(L)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "RmAKPTmG4jD4", "outputId": "8cd83d32-e6ab-4046-8be4-afe51e5b92af" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "range(0, 20)\n" ] } ], "source": [ "# A standard way of generating a list of numbers (this one generates a list from 0 through 19).\n", "Lst = range(0,20)\n", "\n", "print(Lst)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "77sMd2Tk4jD4", "outputId": "a3122e0b-a4e1-43b8-d88a-a85be6d0c995" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "range(3, 10) range(15, 19)\n" ] } ], "source": [ "# Indexing parts of a list\n", "print(Lst[3:10], Lst[15:19])" ] }, { "cell_type": "markdown", "metadata": { "id": "Y0JYDeuh4jD4" }, "source": [ "**List generators**: this is a very useful functionality that you will often need." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "h1YPdCx84jD4", "outputId": "9ced22e9-5946-43c4-ea91-cf4e9481fc24" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n" ] } ], "source": [ "L1 = list(n*2 for n in range(10))\n", "\n", "print(L1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "6knhqorH4jD4", "outputId": "1d1f6697-359b-4505-ac5e-0b051f2fe2b0" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n" ] } ], "source": [ "# Equivalently,\n", "L1 = [n*2 for n in range(10)]\n", "\n", "print(L1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "GY-arori4jD4", "outputId": "8fed86f3-da23-4def-e235-5f3098ac64f9" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "# Generates a list of indices for items in another list\n", "L2 = [L1.index(item) for item in L1]\n", "\n", "print(L2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "BsqhgJ9-4jD5", "outputId": "c789e91c-d635-43ba-8239-b7655258157b" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "[(0, 'a'), (1, 'b'), (2, 'c')]" ] }, "metadata": {}, "execution_count": 11 } ], "source": [ "# You can also generate a list of tuples in the following way using the function \"enumerate\":\n", "list(enumerate(['a','b','c']))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "ZdR0OKFg4jD5", "outputId": "17fc3a47-c61c-4d38-ca8b-6dea15518469" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "[(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]" ] }, "metadata": {}, "execution_count": 12 } ], "source": [ "# Another way to generate a list of tuples is by making all possible combinations of items from a set of lists:\n", "list((x,y) for x in range(1,4) for y in range(3,6))" ] }, { "cell_type": "markdown", "metadata": { "id": "rRaHx_Kx4jD5" }, "source": [ "**Tuples**: A tuple is very similar to list, in that it is also an indexed container used to store\n", "a variety of elements, but it is treated as an immutable data-type. You can have a list of tuples,\n", "for example, but you can’t append to a tuple after it is defined." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "eMzrLy5n4jD5", "outputId": "da77b944-7ef5-4790-ef3e-b84caa323565" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(2.5, 3.4)\n" ] } ], "source": [ "# Note the parantheses (square brackets for a list)\n", "T1 = (2.5, 3.4)\n", "\n", "print(T1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "ji2fUtIb4jD5", "outputId": "5879591a-143b-44df-d742-bb5c777b1bf7" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[(2.5, 3.4)]\n" ] } ], "source": [ "#To declare an empty list, you can also say: L = list()\n", "L = []\n", "\n", "# Appends a tuple to a list; note that there is no \"append\" available for a tuple\n", "L.append(T1)\n", "\n", "print(L)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "nzPCE1Fv4jD5", "outputId": "8a97c9d9-777d-40a4-82ee-f2580be16860" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(2.5, 3.4)\n" ] } ], "source": [ "print(L[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "QpjERUrI4jD5", "outputId": "2ddfc218-3a93-40fd-a4b6-64c0241a343e" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "((12, 14), 1.5, (12, 13, 54))\n" ] } ], "source": [ "# Tuple within a tuple; 2-D coordinates and velocity, for example\n", "T2 = ((12,14),1.5,(12,13,54))\n", "\n", "# Accessing the contents of a tuple is the same as for a list\n", "print(T2)" ] }, { "cell_type": "markdown", "metadata": { "id": "QYdUQpqs4jD7" }, "source": [ "**Dictionary**: It is defined as a set of \"keys\" and their corresponding \"values\".\n", "Given a key, you can retrieve its value from a dictionary. Dictionaries are convenient in\n", "defining relationships between entities, for example between alphabetic letters and numbers:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "-54uVrpH4jD7", "outputId": "216cf266-67f8-42d6-b2cc-4db3bb0da54d" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "10\n" ] } ], "source": [ "# Note the use of curly braces\n", "Char_to_Num = { 'A' : 10, 'B' : 36, 'C' : 21}\n", "\n", "# The 'key' is defined on the left of the colon, and its 'value' on the right\n", "print(Char_to_Num['A']) #retrieves the value of the key 'A'" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "_S0cTyu24jD7", "outputId": "90ffdafa-5a29-4f2a-97c3-ea01782dd012" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "dict_keys(['A', 'B', 'C'])\n" ] } ], "source": [ "# Retrieves keys only, and returns them in a list\n", "print(Char_to_Num.keys())" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "aOvLvsGM4jD7", "outputId": "a10850b5-3982-4c9e-f214-55612f32aa34" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "dict_values([10, 36, 21])\n" ] } ], "source": [ "# Retrieves values only, and returns them in a list\n", "print(Char_to_Num.values())" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "_rSrS1PV4jD7", "outputId": "f4e9c05e-8a57-4878-ff04-4947f1af9259" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "C\n" ] } ], "source": [ "print(list(Char_to_Num.keys())[list(Char_to_Num.values()).index(21)])" ] }, { "cell_type": "markdown", "metadata": { "id": "NLK7TTp-4jD7" }, "source": [ "**Strings**: They can be considered as arrays and indexed as you index an array" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "nre8hUCk4jD7", "outputId": "c295b9bc-d960-46d2-acb0-5b490021674f" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "y\n" ] } ], "source": [ "s = \"python is\"\n", "\n", "# The second character of the string\n", "print(s[1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "njjOd-_R4jD7", "outputId": "3ba8a229-b844-4d48-aecd-ba0b2c58539d" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "python is not a snake\n" ] } ], "source": [ "# The '+' concatenates the two strings\n", "s = s + \" not a snake\"\n", "\n", "print(s)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "VGNKifVz4jD7", "outputId": "afa09711-0839-488c-9707-eb746b0b6ea5" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "10\n" ] } ], "source": [ "# Index strings just as you index lists and tuples\n", "print(s.index('not'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "G2aaUQV74jD8", "outputId": "c39a0f67-f044-4139-93b6-cc4efd3d7d55" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "5\n" ] } ], "source": [ "# Retrieves the index of the first occurrence of 'n'\n", "print(s.index('n'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "6WvHr4l14jD8", "outputId": "76f3a0ef-4750-487a-9a35-067a7752885f" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "'a,b,c'" ], "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" } }, "metadata": {}, "execution_count": 53 } ], "source": [ "#A clever way of generating a string with characters separated by commas (notice that 'join' is not\n", "#a standalone command -- it is a function defined for string objects; in this example):\n", "','.join(['a','b','c'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "zzOjKC0x4jD8", "outputId": "ff423b2f-80cf-4d87-d537-09d50229712a" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "['s', 't', 'r', 'i', 'n', 'g']" ] }, "metadata": {}, "execution_count": 54 } ], "source": [ "# You can make a list out of the characters of a string\n", "list(\"string\")" ] }, { "cell_type": "markdown", "metadata": { "id": "SzXl3oR94jD8" }, "source": [ "**ASCII values**: Every keyboard character has a numerical ASCII value associated with it.\n", "Sometimes it is useful to have access to it, as it may be easier to deal with those numbers,\n", "rather than the original characters, in your program. Aside: 'ord' is short for ordinal." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "anXL5nrK4jD8", "outputId": "eb1effc6-1836-43c0-cdef-f6761da7b152" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "70\n" ] } ], "source": [ "# The ASCII value of upper case F\n", "print(ord('F'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "-VFh_SpW4jD8", "outputId": "d9de1545-db5d-4f2a-9a26-72b7d015e3c6" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "L\n" ] } ], "source": [ "# The character whose ASCII value is 76\n", "print(chr(76))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "pxFwZ4Ah4jD8", "outputId": "f0e2ff60-c436-4477-a564-45a0c687f084" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "s\n" ] } ], "source": [ "# Returns the lower case 's '\n", "print(chr(ord('s')))" ] }, { "cell_type": "markdown", "source": [ "**f-strings**" ], "metadata": { "id": "xy_9od4qL9Ks" } }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "m4pLG-Kb4jD8", "outputId": "703a03b0-1633-4b08-ce57-c59ae0b7c5c6" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "The velocity is: 9.5 +- 0.75\n" ] } ], "source": [ "# We can write template strings that can be populated in runtime when we obtain the information\n", "\n", "# Some heavy intensive computations results\n", "velocity = 9.5\n", "std = 0.7513657984651231\n", "\n", "# Template\n", "template = f'The velocity is: {velocity} +- {std:.2f}'\n", "print(template)" ] }, { "cell_type": "markdown", "source": [ "# Programming: A little less basic" ], "metadata": { "id": "zdI3ngWuGHki" } }, { "cell_type": "markdown", "metadata": { "id": "tsZLgLLC4jD8" }, "source": [ "**Files**: Reading and writing." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gn8vzNoh4jD8", "outputId": "a763771d-19f9-4890-a8f4-f133bb915524" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "/content\n" ] } ], "source": [ "# First set the working directory, where you want to read and write files\n", "import os\n", "\n", "# Retrieves current working directory\n", "print(os.getcwd())\n", "\n", "# Switch to a different working directory, if you want to access files from there\n", "# os.chdir('/Users/smanicka/Documents/My IU/Spring 2015/Teaching I485/Lab 0')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "CkaD0tAd4jD9" }, "outputs": [], "source": [ "# Creating a new file\n", "newf = open('text.txt', 'w')\n", "for i in range(10):\n", " newf.write(f'This is line {i}\\n')\n", "newf.close()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "WWq4B-TH4jD9", "outputId": "aa6b7d0d-0362-4876-8288-8dff7ea2cec4" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "10\n" ] } ], "source": [ "# Now move on to file operations\n", "\n", "# Open file for reading\n", "f = open(\"text.txt\",\"r\")\n", "\n", "# Stores each line of the text in 'lines'\n", "lines = f.readlines()\n", "\n", "# Number of lines in this file\n", "print(len(lines))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DJUA3dQw4jD9", "outputId": "5669e9ba-990c-4102-fd1f-5b1f2cd43093" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "This is line 3\n", "\n" ] } ], "source": [ "# Retrieves the 4th line, assuming there are that many lines\n", "print(lines[3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "oADsfxR94jD9", "outputId": "66abc16e-7019-4d7e-f967-670b00603f67" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "i\n" ] } ], "source": [ "# Retrieves the 6th character of the 3rd line\n", "print(lines[2][5])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "id": "iPn8H23Z4jD9", "outputId": "b96da418-31f5-4046-e697-8aaec703c759" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "'s'" ], "application/vnd.google.colaboratory.intrinsic+json": { "type": "string" } }, "metadata": {}, "execution_count": 64 } ], "source": [ "# If you want to do a fresh read, you should open the file again!\n", "f = open(\"text.txt\",\"r\")\n", "\n", "# Stores all characters of the text, not single lines, in 'chars'\n", "chars = f.read()\n", "\n", "# Retrieves the 124th character of the text.\n", "chars[123]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "t6c1hJzR4jD9" }, "outputs": [], "source": [ "# Open file for writing; append to existing contents\n", "f = open(\"text.txt\",\"a\")\n", "\n", "s = 'a string'\n", "\n", "f.write(s)\n", "\n", "# This is required after a write, else you won’t see the new contents\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": { "id": "oXIhjzmG4jD9" }, "source": [ "**Defining a function**: The following should be self-explanatory. Again, please pay\n", "attention to the indentation for the statement that follow after the first ‘def’ statement.\n", "To run the following code, make sure that the file “text.txt” exists in the working directory and has words in it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "lWxQYyCd4jD-", "outputId": "9ed376fa-d98c-4281-b19a-c77544ce5fd0" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "['This', 'is', 'line', '0']\n" ] } ], "source": [ "def getWords():\n", "\n", " f = open(\"text.txt\",\"r\")\n", "\n", " words = f.readline().split()\n", "\t#NOTE: readline() returns a string, while readlines() returns a list.\n", "\t#Also, split() works only on a string, NOT on a list, and returns a list.\n", "\n", " return words\n", "\n", "# To call a function, you can do the following, for example:\n", "words = getWords()\n", "\n", "print (words)" ] }, { "cell_type": "markdown", "source": [ "**Class**: You can think of a class as a convenient and self-contained wrapper of functions and data." ], "metadata": { "id": "28u1GCb-IJBX" } }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "kR2WC-Xk4jD_", "outputId": "17d9b66c-0f12-4fed-a5dd-4c7775fe1934" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "0\n", "1\n" ] } ], "source": [ "# Basic class management\n", "\n", "class SuperCounter():\n", "\n", " def __init__(self, x):\n", " self.x = x\n", "\n", " def __call__(self,):\n", " return self.x\n", "\n", " def increase(self):\n", " self.x += 1" ] }, { "cell_type": "code", "source": [ "# Creating an instance of a class.\n", "counter = SuperCounter(0)\n", "\n", "# Using the class.\n", "print(counter())\n", "counter.increase()\n", "print(counter())" ], "metadata": { "id": "WP7c3amZIald" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# Packages" ], "metadata": { "id": "l5GHUgt3Bqae" } }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "6W8J8Pjx4jDx", "outputId": "b4baa4f3-2d28-4796-92c0-2e000c6c64a9" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (1.23.5)\n" ] } ], "source": [ "# How to install a new package\n", "\n", "# From the terminal:\n", "# pip install numpy\n", "\n", "# Or alternatively, from a notebook:\n", "%pip install numpy" ] }, { "cell_type": "markdown", "metadata": { "id": "KDCJy8e04jDy" }, "source": [ "At the beginning of a program you might want to specify that you want to use certain “packages” in order to\n", "use their special features that python doesn’t automatically provide. Some packages like ‘math’ and ‘array’ come with python. Others like ‘pygame’ and ‘numpy’ need to be installed. To tell the program that you want to use a package, say, for example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "uBM5o0yf4jDz" }, "outputs": [], "source": [ "#'math' is the name of the package, 'm' is its alias that is easier to use\n", "import math as m\n", "\n", "#‘Random’ package: Use this package to pull random numbers from a given range.\n", "import random as rnd" ] }, { "cell_type": "markdown", "metadata": { "id": "LoSNo8_64jDz" }, "source": [ "Each package has its features implemented in the form of “modules” or \"functions\" to which\n", "you can pass parameters and get results in return. You can invoke the modules with the\n", "name of the package (or its alias) followed by a ‘.’ that is then followed by the name of the module (modules don’t have aliases). For example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "kTjmYTj64jDz", "outputId": "b96b7d23-7ab1-42f1-a070-3bc41b01d8a6" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "4.0\n" ] } ], "source": [ "# 'sqrt' is the square root module\n", "print(m.sqrt( 16 ))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7xgqdzbP4jD0", "outputId": "b37b4ef4-c8a2-451f-9390-c666089e4499" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "-1.0\n" ] } ], "source": [ "# Besides functions packages also have constants (e.g., 'pi') defined\n", "print(m.cos(m.pi))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Jqw3WQwk4jD1", "outputId": "936825f2-8621-4c8b-9517-0f37c7a35c7a" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "60\n" ] } ], "source": [ "# Randomly pull a number from the range 0 through 100\n", "print(rnd.randint(0,100))" ] }, { "cell_type": "markdown", "source": [ "# Packages: Numpy" ], "metadata": { "id": "VJ8VUdi-Ccz-" } }, { "cell_type": "markdown", "metadata": { "id": "rR9PBSPC4jD5" }, "source": [ "A popular package for using arrays is “numpy”.\n", "A nice tutorial is here - http://www.scipy.org/Tentative_NumPy_Tutorial." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "uwOhLVGZ4jD6", "outputId": "f2b8dc7d-1fb9-4393-d156-c3bb01b5bac5" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[ 30 23 100]\n" ] } ], "source": [ "import numpy as np\n", "\n", "# You don’t have to mention the datatype (e.g., integer)\n", "x = np.array([30,23,100])\n", "\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "GUTzK4Mj4jD6", "outputId": "c733407d-d0c8-4fde-ba62-364549190588" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "23\n" ] } ], "source": [ "# The second element of x: this is how you index an array\n", "print (x[1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "jc1gnLYV4jD6", "outputId": "de75ec46-6308-4356-ff87-80633a5b7ffe" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[ 90 69 300]\n" ] } ], "source": [ "# Multiplication of the entire array\n", "y = x * 3\n", "\n", "print(y)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "MVtO4dZS4jD6", "outputId": "d0c9c1c9-bf9b-4b66-d688-28cf38cdfca4" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "(array([2]),)\n" ] } ], "source": [ "# Retrieve the index of an element in array; notice that the result is a tuple of arrays\n", "print(np.where(x == 100))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "y21O6yk04jD6", "outputId": "9f62a8bc-bbd3-406b-bb0f-7d20d808c0e2" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "2\n" ] } ], "source": [ "ind = np.where(x == 100)\n", "print(ind[0][0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "s9Wis7i44jD6", "outputId": "2b0db594-237e-4c10-d90d-aac51bfc15d0" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0.]\n" ] } ], "source": [ "# Create an array of length 100 and store 0’s in it\n", "z = np.zeros(100)\n", "\n", "print(z)" ] }, { "cell_type": "markdown", "metadata": { "id": "YGxkKSHO4jD6" }, "source": [ "You can also use numpy to perform numerical calculations like logarithm, exponentiation etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "B40cwxzO4jD6", "outputId": "6425a8db-5b60-44e4-e1d5-a95dddc1f0e4" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "1.0\n" ] } ], "source": [ "# Base-2 logarithm of a single number\n", "print(np.log2(2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "DAY6Frm34jD7", "outputId": "c9a33d77-cdce-499a-d29f-abf7aec0a3bf" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[1. 5.08746284 8.83289001]\n" ] } ], "source": [ " # Compute the log of an array of numbers\n", "print(np.log2([2,34,456]))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "iy9lA2wy4jD7", "outputId": "48209f4d-7706-4973-f4ae-4d6934f08e2e" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "158\n" ] } ], "source": [ "# Arithmetic sum of an array\n", "print(np.sum([1,59,98]))" ] }, { "cell_type": "markdown", "metadata": { "id": "SdqxLUGW4jD7" }, "source": [ "Generally, matrices are two-dimensional arrays.\n", "You can also think of a matrix as an array of arrays. Use numpy to define them:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "9IUJdOhI4jD7", "outputId": "647402cf-c7b1-4a7a-c955-08c442920bb8" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "[[11 32]\n", " [ 3 94]]\n" ] } ], "source": [ "# Pass a list of equally-sized lists to define a matrix\n", "m = np.array([[11,32], [3,94]])\n", "print(m)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "oPYRKOnn4jD7", "outputId": "0940095b-23e6-4da7-de6f-9a4e40877b6c" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "32\n" ] } ], "source": [ "# Retrieves the element in the 0th row and 1st column of the matrix\n", "print(m[0,1])" ] }, { "cell_type": "markdown", "source": [ "# Packages: Matplotlib\n", "\n", "Matplotlib is perhaps one of the most widely used packages for plotting. A large amount of other packages that draw images use matplotlib on the backend." ], "metadata": { "id": "nqxsCXORGLPF" } }, { "cell_type": "code", "source": [ "# Basic tools for plotting\n", "import matplotlib.pyplot as plt\n", "\n", "# Creating some data points\n", "x = np.arange(10)\n", "y = x**2\n", "\n", "# Plotting the data\n", "plt.plot(x,y)\n", "\n", "# Adding basic format\n", "plt.xlabel('X')\n", "plt.ylabel('Y')\n", "plt.title('X vs Y')" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 489 }, "id": "AZZgimXt5LXR", "outputId": "3056839f-fa1a-4720-dc11-92fe0a0903db" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "Text(0.5, 1.0, 'X vs Y')" ] }, "metadata": {}, "execution_count": 69 }, { "output_type": "display_data", "data": { "text/plain": [ "
" ], "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAHHCAYAAACle7JuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABHXklEQVR4nO3deVxUhf7G8c+wI6uggCgorrjvImp1K8prZvbTzMrSyq4taCrVvdrNyrJsz0rNMtMyrbSyssUWKs1cUNx3zQ1FcGVGUAaYOb8/NG6UlgtwZpjn/XrN6zbnzBweLso8nu1rMQzDQERERMQNeZkdQERERORCqciIiIiI21KREREREbelIiMiIiJuS0VGRERE3JaKjIiIiLgtFRkRERFxWyoyIiIi4rZUZERERMRtqciIiIiI21KREZEKdeuttxIQEMC2bdv+tO6ZZ57BYrHwxRdfmJAMli5dipeXF6NHjz7j+meffRaLxcKXX35ZyclE5FxZNGtJRCrSwYMHSUxMpE2bNvzwww+ly3ft2kXz5s255ppr+Oijj0zLd++99zJt2jRWr15N8+bNS5fv2bOHZs2a0bNnT+bMmWNaPhH5ayoyIlLhpk6dypAhQ5gxYwaDBg0CoEePHixZsoRNmzZRu3Zt07JZrVaaNm1K/fr1+fnnn7FYLABcd911LFq0iM2bN1OrVi3T8onIX9OhJRGpcHfddRddu3blwQcf5MiRI3zwwQcsWLCAcePG/W2Jufbaa6lfv/4Z1yUnJ9OhQ4fS59999x3dunUjPDyc4OBgmjRpwsMPP/yX2w8LC+OVV17hl19+4a233gJg3rx5zJ8/n2eeeUYlRsTFaY+MiFSKjRs30rZtW66//np+/vln6tSpw/Lly/Hy+ut/T82cOZOBAweSkZFBx44dS5fv2bOHevXq8fzzz/Pggw+yceNG2rVrR6tWrbjtttvw9/dnx44dZGRksHDhwr/Nd+2117JkyRJWrlzJP/7xD+Li4li8eHHpHhoRcU0+ZgcQEc/QvHlzHnzwQcaPH4+3tzdffvnl35YYgN69e+Pv78+HH35YpsjMmTMHi8XCjTfeCJzaG1NUVMTXX39NjRo1zjvfpEmTaN68OR07duT48eN89dVXKjEibkCHlkSk0vxWMGJjY2nRosU5vSc0NJQePXowZ84cfr8D+cMPP6Rz587Ex8cDEB4eDsBnn32G0+k872x169blscce4+jRo6SlpZ1zPhExl4qMiFSKrKwsHnvsMVq0aEFWVhbPPffcOb+3f//+ZGVlsXTpUgB+/fVXMjMz6d+/f5nXdO3albvuuovo6Ghuuukm5syZc16l5rc9Pr8/70ZEXJuKjIhUiqFDhwLw9ddf069fP5566il27tx5Tu/t1asX1apVK70Mes6cOXh5edGvX7/S1wQGBrJo0SK+//57brvtNtatW0f//v256qqrcDgc5f8NiYhLUJERkQo3b948Pv/8c5588knq1KnDhAkT8PPzIzU19ZzeHxQUxLXXXsvcuXNxOp18+OGHXHLJJcTGxpZ5nZeXF1deeSUvvfQSmzZt4qmnnuKHH37gxx9/rIhvS0RcgIqMiFSo48ePc//999O2bVuGDRsGnDpH5sknn2TBggXMnTv3nLbTv39/srOzeeutt1i7dm2Zw0oAR48e/dN72rRpA4Ddbr+4b0JEXJYuvxaRCjV8+HAmTpzIsmXLylx15HA46NSpEzk5OWzZsoWQkJC/3E5hYSFRUVEAnDhxguzs7NLnACNGjGDRokX07NmTunXrcvDgQSZPnozFYmHDhg2EhYX9bdaffvqJyy+/nLlz53LDDTdc4HcsIpVJe2REpMJkZmYyadIk7rvvvjIlBsDb25spU6aQk5PDI4888rfbCggI4LrrruP48eNcfvnlZUoMnLoTb3x8PG+//TapqalMmjSJSy+9lB9++OGcSoyIuCftkRERERG3pT0yIiIi4rZUZERERMRtqciIiIiI21KREREREbelIiMiIiJuS0VGRERE3JaP2QEqmtPpJDs7m5CQECwWi9lxRERE5BwYhsHx48eJjY3Fy+vs+12qfJHJzs4mLi7O7BgiIiJyAbKysqhTp85Z11f5IvPbbc+zsrIIDQ01OY2IiIicC5vNRlxc3N+OL6nyRea3w0mhoaEqMiIiIm7m704L0cm+IiIi4rZUZERERMRtqciIiIiI21KREREREbelIiMiIiJuS0VGRERE3JaKjIiIiLgtFRkRERFxWyoyIiIi4rZUZERERMRtqciIiIiI21KREREREbelIiMiIiIXJN9ewtJfj5iaQUVGRERELsjjn2/k5qnLmLLwV9MymFpkHA4HY8aMISEhgcDAQBo0aMCTTz6JYRilrzEMg0cffZRatWoRGBhISkoK27dvNzG1iIiIfLEum48y9+FlgXbx1U3LYWqRefbZZ3n99deZOHEimzdv5tlnn+W5557jtddeK33Nc889x6uvvsqUKVNYvnw5QUFBdO/encLCQhOTi4iIeK7svJM8/Ml6AFIvb0inhAjTsviY9pWBJUuW0Lt3b3r27AlAvXr1eP/998nIyABO7Y2ZMGECjzzyCL179wbg3XffJTo6mk8//ZSbbrrJtOwiIiKeyOE0GPnhGmyFJbSOC+f+KxuZmsfUPTJdunQhPT2dbdu2AbB27VoWL15Mjx49ANi1axc5OTmkpKSUvicsLIykpCSWLl16xm3a7XZsNluZh4iIiJSPNxftZPmuo1Tz8+aV/m3w9Tb3dFtT98iMGjUKm81GYmIi3t7eOBwOnnrqKQYMGABATk4OANHR0WXeFx0dXbruj8aPH8/YsWMrNriIiIgHWr/PyovfbgXg8euaU69GkMmJTN4jM2fOHGbNmsXs2bNZtWoV77zzDi+88ALvvPPOBW9z9OjRWK3W0kdWVlY5JhYREfFMJ4pKGP7hakqcBte0jKFf+zpmRwJM3iPz0EMPMWrUqNJzXVq2bMmePXsYP348gwYNIiYmBoDc3Fxq1apV+r7c3FzatGlzxm36+/vj7+9f4dlFREQ8ybgvN7PzUAExoQE8/X8tsVgsZkcCTN4jc+LECby8ykbw9vbG6XQCkJCQQExMDOnp6aXrbTYby5cvJzk5uVKzioiIeKpvN+Ywe/leLBZ46cbWhFfzMztSKVP3yPTq1YunnnqK+Ph4mjdvzurVq3nppZe48847AbBYLIwYMYJx48bRqFEjEhISGDNmDLGxsVx//fVmRhcREfEIB22F/OfjdQAMuaQ+XRrWMDlRWaYWmddee40xY8Zw3333cfDgQWJjY7n77rt59NFHS1/z73//m4KCAoYMGUJeXh7dunVjwYIFBAQEmJhcRESk6nM6DR6Yu5ZjJ4ppHhtK2tWNzY70Jxbj97fRrYJsNhthYWFYrVZCQ0PNjiMiIuI2pi3exZNfbCLA14svhnWjYVRIpX3tc/381qwlERER+ZPNB2w8+/UWAB7p2axSS8z5UJERERGRMgqLHQz/YDVFDicpTaMYkBRvdqSzUpERERGRMp75egvbcvOpEezPs31bucyl1meiIiMiIiKlftx6kBlLdgPwQr9WRAa79r3ZVGREREQEgMP5dh6ae+pS69u71OMfTaJMTvT3VGREREQEwzD4z0frOJxvp0l0CKN6JJod6ZyoyIiIiAjvLd9L+paD+Pl48crNbQjw9TY70jlRkREREfFwOw4eZ9wXmwAY9c9EEmPc575rKjIiIiIezF7i4P7312AvcXJp45rc3qWe2ZHOi4qMiIiIB3vx221sOmAjIsiPF25ohZeX615qfSYqMiIiIh7qlx2HeXPRTgCe7duKqFD3m2OoIiMiIuKBjhUU8cCctQAMSIrnqmbRJie6MCoyIiIiHsYwDB6et54cWyH1awbxSM9mZke6YCoyIiIiHmbuyn18vSEHX28Lr97UlkA/97jU+kxUZERERDzIrsMFPD5/IwAPXN2EFrXDTE50cVRkREREPESxw8mID1ZzoshBcv1IhlxS3+xIF01FRkRExEO88v121u6zEhboy4s3tna7S63PREVGRETEAyzfeYRJP+0A4On/a0lseKDJicqHioyIiEgVZz1ZTNqctRgG9Gtfh56tapkdqdyoyIiIiFRxj362gf15J6kbWY3HrmtudpxypSIjIiJShX26ej+frcnG28vChP5tCPb3MTtSuVKRERERqaKyjp5gzKcbABh+ZSPaxlc3OVH5U5ERERGpgkocTkZ+uIbj9hI61K3Off9oYHakCqEiIyIiUgVN/ulXVu45Roi/Dy/3b4OPd9X8yK+a35WIiIgHW7X3GK+kbwfgyetbEBdRzeREFUdFRkREpArJt5cw4oM1OJwGvdvEcn3b2mZHqlAqMiIiIlXI459vZO/RE9QOD+SJ3i3MjlPhVGRERESqiC/XHeCjzH14WeDl/m0IC/Q1O1KFU5ERERGpArLzTjL6k3UApF7ekE4JESYnqhwqMiIiIm7O4TRIm7MGW2EJrePCuf/KRmZHqjSmFpl69ephsVj+9EhNTQWgsLCQ1NRUIiMjCQ4Opm/fvuTm5poZWURExOVM/Xkny3YepZqfNxP6t8G3il5qfSamfqcrVqzgwIEDpY/vvvsOgH79+gEwcuRI5s+fz9y5c1m4cCHZ2dn06dPHzMgiIiIuZf0+Ky9+uxWAx3s1J6FGkMmJKpepAxdq1qxZ5vkzzzxDgwYNuOyyy7BarUybNo3Zs2dzxRVXADB9+nSaNm3KsmXL6Ny5sxmRRUREXMaJohKGf7iaYodBjxYx9OtQx+xIlc5l9j0VFRXx3nvvceedd2KxWMjMzKS4uJiUlJTS1yQmJhIfH8/SpUtNTCoiIuIaxn25mZ2HCogJDWB8n5ZYLBazI1U6lxmB+emnn5KXl8ftt98OQE5ODn5+foSHh5d5XXR0NDk5OWfdjt1ux263lz632WwVEVdERMRU327MYfbyvVgs8NKNrQmv5md2JFO4zB6ZadOm0aNHD2JjYy9qO+PHjycsLKz0ERcXV04JRUREXMNBWyGjPlkPwJBL6tOlYQ2TE5nHJYrMnj17+P7777nrrrtKl8XExFBUVEReXl6Z1+bm5hITE3PWbY0ePRqr1Vr6yMrKqqjYIiIilc7pNHhg7lqOFhTRPDaUtKsbmx3JVC5RZKZPn05UVBQ9e/YsXda+fXt8fX1JT08vXbZ161b27t1LcnLyWbfl7+9PaGhomYeIiEhVMWPJbn7efhh/Hy9euakN/j7eZkcylennyDidTqZPn86gQYPw8flfnLCwMAYPHkxaWhoRERGEhoYybNgwkpOTdcWSiIh4pM0HbDzz9RYAHrm2GQ2jQkxOZD7Ti8z333/P3r17ufPOO/+07uWXX8bLy4u+fftit9vp3r07kydPNiGliIiIuQqLHYz4YA1FDidXJkZxa1K82ZFcgsUwDMPsEBXJZrMRFhaG1WrVYSYREXFbj3++kRlLdlMj2J8FIy6hRrC/2ZEq1Ll+frvEOTIiIiJydj9uPciMJbsBeKFfqypfYs6HioyIiIgLO5xv56G5p6Za396lHv9oEmVyIteiIiMiIuKiDMPgPx+t43C+nSbRIYzqkWh2JJejIiMiIuKiZi3fS/qWg/j5ePHKzW0I8PXsS63PREVGRETEBe04eJxxX24C4D//TCQxRhesnImKjIiIiIuxlzi4//01FBY7uaRRDe7oUs/sSC5LRUZERMTFvPTtNjYdsFG9mi8v9muNl5fnTbU+VyoyIiIiLuSXHYd5Y9FOAJ7t24qo0ACTE7k2FRkREREXcaygiAfmrAXglqR4rm5+9iHJcoqKjIiIiAswDIOH560nx1ZI/ZpBPNKzqdmR3IKKjIiIiAuYu3IfX2/Iwdfbwqs3taWan+njEN2CioyIiIjJdh8u4PH5GwF44OomtKgdZnIi96EiIyIiYqJih5PhH67hRJGDzvUj+Ncl9c2O5FZUZEREREz0avp21mblERrgw0s3tsFbl1qfFxUZERERk2TsOsqkH3cAML5PK2LDA01O5H5UZERERExgPVnMyA/X4DTghvZ16NmqltmR3JKKjIiIiAke/WwD+/NOEh9Rjceva252HLelIiMiIlLJPl29n8/WZOPtZWHCTW0I9tel1hdKRUZERKQSbT5gY/Qn6wEYfmUj2sVXNzmRe1ORERERqSR5J4oYMnMlJ4sdXNKoBvf9o4HZkdyeioyIiEglKHE4GTp7NVlHT50X89rNbfHx1sfwxdL/gyIiIpXg2QVbWLzjMIG+3rw5sD3h1fzMjlQlqMiIiIhUsE9X72fqz7sAePHG1iTGhJqcqOpQkREREalAG/Zb+c/H6wBIvbwB17TU/WLKk4qMiIhIBTmcb2fIuyuxlzi5IjGKtKuamB2pylGRERERqQDFDieps1aRbS2kfo0gXu6vOUoVQUVGRESkAjz15WaW7zpKsL8Pbw5sT1igr9mRqiQVGRERkXI2Z2UWM5bsBuDl/m1oGBVibqAqTEVGRESkHK3ee4xH5m0AYGRKY65qFm1yoqpNRUZERKScHLQVcs97mRQ5nFzdLJphVzQ0O1KVpyIjIiJSDuwlDu55L5Ncm51GUcG81L8NXjq5t8KZXmT279/PrbfeSmRkJIGBgbRs2ZKVK1eWrjcMg0cffZRatWoRGBhISkoK27dvNzGxiIjInz3++SZW7c0jNMCHNwd20ETrSmJqkTl27Bhdu3bF19eXr7/+mk2bNvHiiy9Svfr/JoE+99xzvPrqq0yZMoXly5cTFBRE9+7dKSwsNDG5iIjI/8xavof3M/ZiscCrN7cloUaQ2ZE8hsUwDMOsLz5q1Ch++eUXfv755zOuNwyD2NhYHnjgAR588EEArFYr0dHRzJgxg5tuuulvv4bNZiMsLAyr1UpoqG4JLSIi5WvF7qPcMnUZxQ6D//wzkXs10bpcnOvnt6l7ZD7//HM6dOhAv379iIqKom3btkydOrV0/a5du8jJySElJaV0WVhYGElJSSxduvSM27Tb7dhstjIPERGRinDAepJ731tFscOgZ6ta3HNZfbMjeRxTi8zOnTt5/fXXadSoEd988w333nsv999/P++88w4AOTk5AERHl710LTo6unTdH40fP56wsLDSR1xcXMV+EyIi4pEKix3cMzOTw/l2EmNCeP6GVlgsOrm3splaZJxOJ+3atePpp5+mbdu2DBkyhH/9619MmTLlgrc5evRorFZr6SMrK6scE4uIiJw69eG/8zawdp+V8Gq+TB3YgWp+OrnXDKYWmVq1atGsWbMyy5o2bcrevXsBiImJASA3N7fMa3Jzc0vX/ZG/vz+hoaFlHiIiIuVpxpLdfLxqH14WmHRLO+IiqpkdyWOZWmS6du3K1q1byyzbtm0bdevWBSAhIYGYmBjS09NL19tsNpYvX05ycnKlZhUREQFY8uthxn25GYCHr2lK14Y1TE7k2UzdDzZy5Ei6dOnC008/zY033khGRgZvvvkmb775JgAWi4URI0Ywbtw4GjVqREJCAmPGjCE2Npbrr7/ezOgiIuKBso6eIHXWKhxOg/9rW5vB3RLMjuTxTC0yHTt2ZN68eYwePZonnniChIQEJkyYwIABA0pf8+9//5uCggKGDBlCXl4e3bp1Y8GCBQQEBJiYXEREPM3JIgd3z8zk2IliWtYOY3yfljq51wWYeh+ZyqD7yIiIyMUyDIPhH6zh87XZRAb5MX9YN2LDA82OVaW5xX1kRERE3MGbi3by+dpsfLwsTB7QTiXGhajIiIiI/IWF2w7x7IItADzWqxlJ9SNNTiS/pyIjIiJyFrsPFzBs9iqcBvTvEMetneuaHUn+QEVGRETkDArsJQyZuRJbYQlt48N54vrmOrnXBanIiIiI/IFhGDwwZy3bcvOpGeLPlFvb4+/jbXYsOQMVGRERkT+Y9OMOFmzMwc/biym3tic6VLf8cFUqMiIiIr+TvjmXF7/bBsATvZvTvm51kxPJX1GREREROe3XQ/mM+GANhgG3da7LTZ3izY4kf0NFRkREBLAVFvOvd1dy3F5Cp3oRjLm22d+/SUynIiMiIh7P6TQY+cEadh4qoFZYAJMGtMPPRx+R7kA/JRER8XgTvt9G+paD+Pl48cZt7akZ4m92JDlHKjIiIuLRFmw4wKs/7ABg/P+1pFWdcHMDyXlRkREREY+1Nec4aXPWAnBn1wT6tq9jciI5XyoyIiLikawnihkycyUnihx0aRDJw9ckmh1JLoCKjIiIeByH02DYB6vZc+QEdaoHMvGWdvh46yPRHemnJiIiHue5b7awaNshAny9ePO2DkQE+ZkdSS6QioyIiHiUz9dm88bCnQA8f0NrmsWGmpxILoaKjIiIeIyN2Vb+/dGpk3vvuawBvVrHmpxILpaKjIiIeISjBUUMeTeTwmInlzauyUPdm5gdScqBioyIiFR5JQ4nqbNWsT/vJHUjq/HaTW3x9rKYHUvKgYqMiIhUeU9/tYWlO49Qzc+bqQM7EFbN1+xIUk5UZEREpEr7OHMfb/+yC4CXbmxD4+gQkxNJeVKRERGRKmvdvjxGz1sPwP1XNuKfLWJMTiTlTUVGRESqpEPH7dw9M5OiEicpTaMYcWUjsyNJBVCRERGRKqeoxMl9szI5YC2kQc0gXu7fBi+d3FslqciIiEiV88QXG1mx+xgh/j68ObADIQE6ubeqUpEREZEq5f2Mvby3bC8WC7xycxsa1Aw2O5JUIBUZERGpMjL3HOXRzzYA8MBVjbkiMdrkRFLRVGRERKRKyLUVcs97qyh2GPRoEUPq5Q3NjiSVQEVGRETcnr3Ewd0zMzl03E6T6BBe6Ncai0Un93oCU4vM448/jsViKfNITEwsXV9YWEhqaiqRkZEEBwfTt29fcnNzTUwsIiKuxjAMxny6gTVZeYQF+vLmwPYE+fuYHUsqiel7ZJo3b86BAwdKH4sXLy5dN3LkSObPn8/cuXNZuHAh2dnZ9OnTx8S0IiLiamYu28OclfvwssBrN7elbmSQ2ZGkEpleWX18fIiJ+fOdFq1WK9OmTWP27NlcccUVAEyfPp2mTZuybNkyOnfuXNlRRUTExSzbeYQn5m8CYFSPRC5tXNPkRFLZTN8js337dmJjY6lfvz4DBgxg7969AGRmZlJcXExKSkrpaxMTE4mPj2fp0qVmxRURERexP+8kqbNWUeI0uK51LP+6pL7ZkcQEpu6RSUpKYsaMGTRp0oQDBw4wduxYLrnkEjZs2EBOTg5+fn6Eh4eXeU90dDQ5OTln3abdbsdut5c+t9lsFRVfRERMUljs4O6ZKzlSUESzWqE827eVTu71UKYWmR49epT+d6tWrUhKSqJu3brMmTOHwMDAC9rm+PHjGTt2bHlFFBERF2MYBqM/Wc+G/TYigvx4c2B7Av28zY4lJjH90NLvhYeH07hxY3bs2EFMTAxFRUXk5eWVeU1ubu4Zz6n5zejRo7FaraWPrKysCk4tIiKVadriXcxbvR9vLwsTb2lLnerVzI4kJnKpIpOfn8+vv/5KrVq1aN++Pb6+vqSnp5eu37p1K3v37iU5Ofms2/D39yc0NLTMQ0REqobF2w/z9FebAXikZ1O6NKhhciIxm6mHlh588EF69epF3bp1yc7O5rHHHsPb25ubb76ZsLAwBg8eTFpaGhEREYSGhjJs2DCSk5N1xZKIiAfalG3j3lmZOA24oX0dbu9Sz+xI4gJMLTL79u3j5ptv5siRI9SsWZNu3bqxbNkyatY8dfncyy+/jJeXF3379sVut9O9e3cmT55sZmQRETHBrsMFDHw7g+OFJXSsV51x17fQyb0CgMUwDMPsEBXJZrMRFhaG1WrVYSYRETeUYy2k7+tL2J93kqa1QvlgSGfCAn3NjiUV7Fw/v13qHBkREZHfO1pQxK3TlrM/7yT1Iqvx7p2dVGKkDBUZERFxSfn2Eu6YnsGOg/nEhAYwc3ASNUP8zY4lLkZFRkREXE5hsYMh765k7T4r1av5MnNwJ+IidJm1/JmKjIiIuJQSh5P731/Nkl+PEOTnzYw7OtEoOsTsWOKiVGRERMRlOJ0Goz5Zz7ebcvHz8WLqoA60jgs3O5a4MBUZERFxCYZh8NRXm/koc9+pu/be3FY3vJO/pSIjIiIuYdKPO5i2eBcAz/ZtxdXNzz6ORuQ3KjIiImK6mcv28MK32wAYc20zbmhfx+RE4i5UZERExFSfrdnPo59tAOD+KxoyuFuCyYnEnajIiIiIaX7ccpAH5qzFMGBgcl1GXtXY7EjiZlRkRETEFBm7jnLPe5mUOA16t4nl8V7NNT9JzpuKjIiIVLoN+60MnrECe4mTKxKjeKFfa7y8VGLk/KnIiIhIpdp5KJ9Bb2dw3F5Cp3oRTB7QDl9vfRzJhdGfHBERqTQHrCe5bVoGRwqKaFYrlLdu70CAr7fZscSNqciIiEilOFpQxG3TMtifd5L6NYJ4d3AnQgM0yVoujoqMiIhUuHx7CbefnmRdKyyAdwd3okawJlnLxVORERGRClVY7OBf76xk3T4rEUF+zBycRJ3qmmQt5UNFRkREKkyJw8mw91ezdOcRgv19eOeOTjSMCjY7llQhKjIiIlIhnE6D/3y8nu9+m2Q9sAMt64SZHUuqGBUZEREpd4Zh8OSXm/h41alJ1pNuaUdyg0izY0kVpCIjIiLl7rUfdjD9l90APNe3FVc1izY3kFRZKjIiIlKu3l26m5e+OzXJ+tFrm9FXk6ylAqnIiIhIufl09X4e/WwjAMOvbMSdmmQtFUxFRkREykX65lwemLsWgNu71GNESiOTE4knUJEREZGLtnznEe6btQqH0+D/2tbm0WubaZK1VAoVGRERuSgb9lu5652V2EucpDSN4rkbWmmStVQaFRkREblgZSZZJ0Qw8RZNspbKpT9tIiJyQbLz/jfJukXtUN4apEnWUvnOuchkZ2dXZA4REXEjR/Lt3DZt+alJ1jWDeOcOTbIWc5xzkWnevDmzZ8+uyCwiIuIGjhcWc/v0Ffx6qIDYsABmDk4iUpOsxSTnXGSeeuop7r77bvr168fRo0crMpOIiLiowmIHd72zkvX7T0+yviuJ2uGBZscSD3bORea+++5j3bp1HDlyhGbNmjF//vxyDfLMM89gsVgYMWJE6bLCwkJSU1OJjIwkODiYvn37kpubW65fV0REzk2xw8nQ2atYvusowf4+vHtnJxrU1CRrMZfP+bw4ISGBH374gYkTJ9KnTx+aNm2Kj0/ZTaxateq8Q6xYsYI33niDVq1alVk+cuRIvvzyS+bOnUtYWBhDhw6lT58+/PLLL+f9NURE5MI5nQb/+Wgd328+iL+PF28N6kCL2ppkLeY7ryIDsGfPHj755BOqV69O7969/1Rkzld+fj4DBgxg6tSpjBs3rnS51Wpl2rRpzJ49myuuuAKA6dOn07RpU5YtW0bnzp0v6uuKiMi5MQyDJ77YxCer95dOsu5cX5OsxTWcVwuZOnUqDzzwACkpKWzcuJGaNWtedIDU1FR69uxJSkpKmSKTmZlJcXExKSkppcsSExOJj49n6dKlZy0ydrsdu91e+txms110RhERT/Zq+g5mLNkNwAv9WpGiSdbiQs65yPzzn/8kIyODiRMnMnDgwHL54h988AGrVq1ixYoVf1qXk5ODn58f4eHhZZZHR0eTk5Nz1m2OHz+esWPHlks+ERFPN+OXXbz8/alJ1o/3asb/tdUka3Et51xkHA4H69ato06d8vlDnJWVxfDhw/nuu+8ICAgol20CjB49mrS0tNLnNpuNuLi4ctu+iIinmLd6H4/P3wTAyJTG3N5Vk6zF9Zxzkfnuu+/K9QtnZmZy8OBB2rVrV7rM4XCwaNEiJk6cyDfffENRURF5eXll9srk5uYSExNz1u36+/vj76/7GYiIXIzvN+Xy4Nx1ANzRtR73X9nQ5EQiZ3ZxZ+pehCuvvJL169eXWXbHHXeQmJjIf/7zH+Li4vD19SU9PZ2+ffsCsHXrVvbu3UtycrIZkUVEPMLSX49w3+xTk6z7tK3NmJ6aZC2uy7QiExISQosWLcosCwoKIjIysnT54MGDSUtLIyIigtDQUIYNG0ZycrKuWBIRqSDr91n517srKSpxktI0mmc1yVpcnGlF5ly8/PLLeHl50bdvX+x2O927d2fy5MlmxxIRqZJ2HMxn0PQM8u0ldK4fwcRb2mqStbg8i2EYhtkhKpLNZiMsLAyr1UpoaKjZcUREXNL+vJP0e30J2dZCWtYOY/a/kgjREEgx0bl+fqtqi4h4uMP5dm57aznZ1kIa1Axixh0dVWLEbajIiIh4MFthMYPezmDn4QJqhwdqkrW4HRUZEREP9dsk643ZNiKD/Jg5uBOxmmQtbkZFRkTEAxU7nKTOWkXGrqOE+Pvwzp2dqK9J1uKGVGRERDyM02nw0Ny1pG/RJGtxfyoyIiIe5LdJ1p+uycbHy8Lrt7YjSZOsxY2pyIiIeJAJ329nxpLdWCzw4o2tuSJRk6zFvanIiIh4iLcX7+KV9O0AjL2uOb3b1DY5kcjFU5EREfEAH2fu44kvTk2yfuCqxgxMrmduIJFyoiIjIlLFzVy2hwc/WgvAnV0TGHqFJllL1eHSs5ZEROTCGYbBhO+3lx5OGpAUzyM9m2qStVQpKjIiIlWQw2nw2OcbeG/ZXgCGX9mIESmNVGKkylGRERGpYuwlDkZ+uIav1udgscAT1zXnNp0TI1WUioyISBVyvLCYIe9msnTnEfy8vXi5fxt6tqpldiyRCqMiIyJSRRw6buf26RlszLYR5OfN1IEd6NKwhtmxRCqUioyISBWw98gJbnt7OXuOnCAyyI8Zd3SiZR2NHZCqT0VGRMTNbcq2MWh6BoeO26lTPZCZg5NIqBFkdiyRSqEiIyLixpbtPMK/3lnJcXsJiTEhvHtnJ6JCA8yOJVJpVGRERNzUgg053P/BaopKnHRKiGDqwA6EBfqaHUukUqnIiIi4oQ8y9vLwvPU4Dbi6WTSv3tyWAF9vs2OJVDoVGRERN2IYBpN+3MEL324DoH+HOJ76vxb4eGvijHgmFRkRETfhdBo88cUmZizZDUDq5Q148OomuluveDQVGRERN1BU4uSBuWuZvzYbgMd6NeOOrgkmpxIxn4qMiIiLy7eXcO97mfy8/TA+XhZevLE1vdvUNjuWiEtQkRERcWFH8u3cMWMF6/ZZqebnzeu3tueyxjXNjiXiMlRkRERcVNbREwx6O4OdhwuoXs2X6Xd0ok1cuNmxRFyKioyIiAvakmNj0NsZ5Nrs1A4P5J07O9EwKtjsWCIuR0VGRMTFrNh9lMEzVmArLKFxdDDv3plETJju1ityJioyIiIu5PtNuaTOXoW9xEn7utWZNqgD4dX8zI4l4rJUZEREXMSclVmM/mQ9DqfBlYlRTLylHYF+uluvyF8x9VaQr7/+Oq1atSI0NJTQ0FCSk5P5+uuvS9cXFhaSmppKZGQkwcHB9O3bl9zcXBMTi4iUP8MwmLLwV/790TocToO+7eow5bb2KjEi58DUIlOnTh2eeeYZMjMzWblyJVdccQW9e/dm48aNAIwcOZL58+czd+5cFi5cSHZ2Nn369DEzsohIuXI6DZ76cjPPfL0FgLsvq88L/Vrhq5EDIufEYhiGYXaI34uIiOD555/nhhtuoGbNmsyePZsbbrgBgC1bttC0aVOWLl1K586dz2l7NpuNsLAwrFYroaGhFRldROS8FDuc/PujdcxbvR+A/17TlH9dWt/kVCKu4Vw/v13mHBmHw8HcuXMpKCggOTmZzMxMiouLSUlJKX1NYmIi8fHxf1lk7HY7dru99LnNZqvw7CIi5+tEUQn3zVrFT1sP4e1l4bm+rejbvo7ZsUTcjun7LtevX09wcDD+/v7cc889zJs3j2bNmpGTk4Ofnx/h4eFlXh8dHU1OTs5Ztzd+/HjCwsJKH3FxcRX8HYiInJ9jBUUMeGs5P209RICvF28N7KASI3KBTC8yTZo0Yc2aNSxfvpx7772XQYMGsWnTpgve3ujRo7FaraWPrKysckwrInJxsvNO0u+Npazem0dYoC+z7urM5YlRZscScVumH1ry8/OjYcOGALRv354VK1bwyiuv0L9/f4qKisjLyyuzVyY3N5eYmJizbs/f3x9/f/+Kji0ict625x5n4NsZHLAWEhMawLuDO9E4OsTsWCJuzfQ9Mn/kdDqx2+20b98eX19f0tPTS9dt3bqVvXv3kpycbGJCEZHzl7nnGP3eWMoBayENagbx8X1dVGJEyoGpe2RGjx5Njx49iI+P5/jx48yePZuffvqJb775hrCwMAYPHkxaWhoRERGEhoYybNgwkpOTz/mKJRERV/Dj1oPc+14mhcVO2sSF8/btHYkI0t16RcqDqUXm4MGDDBw4kAMHDhAWFkarVq345ptvuOqqqwB4+eWX8fLyom/fvtjtdrp3787kyZPNjCwicl7mrd7HQ3PXUeI0uKxxTV6/tR3V/Ew/qi9SZbjcfWTKm+4jIyJmeevnnYz7cjMA17eJ5fl+rXWjO5Fz5Hb3kRERqSoMw+CZBVt4Y+FOAAZ3S+C/1zTFy8ticjKRqkdFRkSkHJU4nIz+ZD1zM/cB8J9/JnLPZfWxWFRiRCqCioyISDk5WeRg2Pur+H7zQbws8EyfVtzYUTflFKlIKjIiIuXAeqKYwe+sYOWeY/j7eDHxlnZc1Sza7FgiVZ6KjIjIRcqxFjLo7Qy25h4nJMCHaYM60ikhwuxYIh5BRUZE5CL8eiifgdMy2J93kqgQf94d3InEGF0hKVJZVGRERC7Q2qw87pixgqMFRSTUCOLdOzsRF1HN7FgiHkVFRkTkAizadoh73svkRJGDlrXDmH5HR2oEa86bSGVTkREROU+frdnPg3PXUuww6NawBlNua0+wv36diphBf/NERM7D9F92MXb+JgCubVWLF29sjb+Pt8mpRDyXioyIyDkwDIMXv93GxB93ADAouS6P9Wquu/WKmExFRkTkb5Q4nIz5bAPvZ2QB8MBVjRl6RUPdrVfEBajIiIj8hcJiB/e/v5pvN+XiZYFx17fklqR4s2OJyGkqMiIiZ3HweCFDZ60mY/dR/Hy8ePWmNvyzRS2zY4nI76jIiIicweLthxnx4WoO5xcR7O/D1IEdSG4QaXYsEfkDFRkRkd8pcTh5JX07E3/cgWFAYkwIE29pR8OoYLOjicgZqMiIiJyWYy3k/g9Wk7HrKAA3d4rnsV7NCPDV5dUirkpFRkQE+GnrQdLmrOVoQRFBft6M79uK61rHmh1LRP6GioyIeLRih5MXv93GlIW/AtCsViiTBrQjoUaQyclE5FyoyIiIx9qfd5L7319N5p5jAAxMrsvD1zTVoSQRN6IiIyIe6ftNuTz40VryThQT4u/Dsze04pqWurRaxN2oyIiIRykqcfLcgi28tXgXAK3qhDHx5nbER1YzOZmIXAgVGRHxGFlHTzD0/dWszcoD4M6uCfynRxMNfRRxYyoyIuIRFmzI4aGP1nK8sITQAB9e6Neaq5vHmB1LRC6SioyIVGn2Egfjv9rCjCW7AWgbH85rN7elTnUdShKpClRkRKTK2n24gKHvr2LDfhsAd19anwe7N8HX28vkZCJSXlRkRKRK+mJdNqM+Xk++vYTq1Xx58cbWXJEYbXYsESlnKjIiUqUUFjt48otNzFq+F4CO9arz6s1tqRUWaHIyEakIKjIiUmX8eiif1Fmr2JJzHID7/tGAtKsa46NDSSJVloqMiFQJn67ez8Pz1nOiyEFkkB8v9W/DZY1rmh1LRCqYioyIuLWTRQ4e/3wjH67MAqBz/Qheuakt0aEBJicTkcpg6v7W8ePH07FjR0JCQoiKiuL6669n69atZV5TWFhIamoqkZGRBAcH07dvX3Jzc01KLCKuZHvucXpPWsyHK7OwWOD+Kxsx667OKjEiHsTUIrNw4UJSU1NZtmwZ3333HcXFxVx99dUUFBSUvmbkyJHMnz+fuXPnsnDhQrKzs+nTp4+JqUXEFcxdmcV1E39hW24+NYL9mTU4ibSrGuPtZTE7mohUIothGIbZIX5z6NAhoqKiWLhwIZdeeilWq5WaNWsye/ZsbrjhBgC2bNlC06ZNWbp0KZ07d/7bbdpsNsLCwrBarYSGhlb0tyAiFazAXsKYzzbwyar9AHRrWIOX+7ehZoi/yclEpDyd6+e3S50jY7VaAYiIiAAgMzOT4uJiUlJSSl+TmJhIfHz8WYuM3W7HbreXPrfZbBWcWkQqy5YcG6mzVvHroQK8LDAypTH3Xd5Qe2FEPJjLFBmn08mIESPo2rUrLVq0ACAnJwc/Pz/Cw8PLvDY6OpqcnJwzbmf8+PGMHTu2ouOKSCUyDIMPVmTx+OcbsZc4iQ7155Wb2tK5fqTZ0UTEZC5TZFJTU9mwYQOLFy++qO2MHj2atLS00uc2m424uLiLjSciJsm3l/DwJ+v5fG02AJc1rslLN7YmMliHkkTERYrM0KFD+eKLL1i0aBF16tQpXR4TE0NRURF5eXll9srk5uYSE3PmqbX+/v74++sXnEhVsGG/laGzV7H7yAm8vSw8eHUT7r60Pl46lCQip5l61ZJhGAwdOpR58+bxww8/kJCQUGZ9+/bt8fX1JT09vXTZ1q1b2bt3L8nJyZUdV0QqiWEYzFy6mz6vL2H3kRPEhgUw5+7O3PuPBioxIlKGqXtkUlNTmT17Np999hkhISGl572EhYURGBhIWFgYgwcPJi0tjYiICEJDQxk2bBjJycnndMWSiLgfW2Exoz5ex1frT/0+SGkaxfM3tKZ6kJ/JyUTEFZl6+bXFcuZ/WU2fPp3bb78dOHVDvAceeID3338fu91O9+7dmTx58lkPLf2RLr8WcR/r9uUxdPZq9h49gY+XhVE9EhncLeGsvytEpOo6189vl7qPTEVQkRFxfYZhMP2X3Yz/ejPFDoPa4YFMvKUtbeOrmx1NREzilveRERHPYz1RzEMfreXbTadGj3RvHs1zfVsTVs3X5GQi4g5UZETENKv2HmPY7NXszzuJn7cXD1+TyKAu9XQoSUTOmYqMiFQ6p9PgrcU7eW7BVkqcBvER1Zh0Szta1gkzO5qIuBkVGRGpVMcKinhg7lp+2HIQgJ6tajG+T0tCA3QoSUTOn4qMiFSaFbuPcv/7qzlgLcTPx4tHr23GgKR4HUoSkQumIiMiFc7pNHh94a+89N02HE6DhBpBTLylLc1jdShJRC6OioyIVKjD+XbS5qxl0bZDAPRuE8tT/9eSYH/9+hGRi6ffJCJSYZbtPML976/m4HE7Ab5ejL2uOTd2iNOhJBEpNyoyIlLuikqcTP5pB6+mb8dpQMOoYCbd0o4mMSFmRxORKkZFRkTKjWEY/Lj1IE9+sZldhwsAuKF9HZ7o3Zxqfvp1IyLlT79ZRKRc7DiYz5NfbGLh6XNhagT780jPplzftrbJyUSkKlOREZGLYj1ZzKvp23lnyW5KnAa+3hbu7JbA0MsbEqJ7w4hIBVOREZEL4nAazFmZxQvfbOVIQREAKU2j+G/PZiTUCDI5nYh4ChUZETlvGbuO8vjnG9l0wAZAg5pBPNqrOZc1rmlyMhHxNCoyInLO9uedZPxXm/li3QEAQgJ8GJnSmNuS6+Lr7WVyOhHxRCoyIvK3ThY5eGPRr0xZ+CuFxU4sFri5UzwPXNWYyGB/s+OJiAdTkRGRszIMgy/WHWD8V5vJthYC0Ckhgsd6NdN4ARFxCSoyInJGG/ZbeWL+JjJ2HwWgdnggD1/TlGtaxujOvCLiMlRkRKSMI/l2Xvh2Kx+syMIwIMDXi3sva8iQS+sT6OdtdjwRkTJUZEQEODVW4N2lu3klfTvHC0sAuK51LKN6JBIbHmhyOhGRM1ORERF+2nqQJ77YxM5Dp8YKNI8N5fHrmtOxXoTJyURE/pqKjIgH23kon3FfbuaHLQcBiAzy46HuTejXIQ5vL50HIyKuT0VGxAPZCouZ+MMOpv+yi2KHgY+XhTu61mPYlY0I1VgBEXEjKjIiHsTpNPgocx/PfbOFw/mnxgpc3qQmj1zbjAY1g01OJyJy/lRkRDxE5p6jPP75JtbvtwJQv0YQY65txuWJUSYnExG5cCoyIlXcAetJnvl6C5+tyQYgxN+H4SmNGJhcDz8fjRUQEfemIiNSRRUWO5i6aCeTf/qVk8UOLBbo3yGOB65uQs0QjRUQkapBRUakijEMgwUbcnjqq83sO3YSgI71qvNYr+a0qK2xAiJStajIiFQhmw/YGDt/I8t2nhorUCssgNHXNKVXq1oaKyAiVZKKjEgVcLSgiBe/3cr7GXtxGuDv48XdlzXgnsvqU81Pf81FpOoy9Uy/RYsW0atXL2JjY7FYLHz66adl1huGwaOPPkqtWrUIDAwkJSWF7du3mxNWxAUVO5xM/2UX/3j+R2YtP1VieraqRfoDl5F2VWOVGBGp8kwtMgUFBbRu3ZpJkyadcf1zzz3Hq6++ypQpU1i+fDlBQUF0796dwsLCSk4q4np+3n6Ia175mbHzN2ErLKFprVA+GNKZSbe0o071ambHExGpFKb+c61Hjx706NHjjOsMw2DChAk88sgj9O7dG4B3332X6OhoPv30U2666abKjCriMnYfLmDcl5v5fnMuANWr+fJg9ybc1DFeYwVExOO47H7nXbt2kZOTQ0pKSumysLAwkpKSWLp06VmLjN1ux263lz632WwVnlWkMuTbS5j4ww7eXryLIocTHy8LA5PrMfzKRoRV01gBEfFMLltkcnJyAIiOji6zPDo6unTdmYwfP56xY8dWaDaRyuR0Gnyyej/PLtjCoeOnSvoljWrwWK9mNIwKMTmdiIi5XLbIXKjRo0eTlpZW+txmsxEXF2diIpELt2rvMcbO38TarDwA6kVWY8y1zbgiMUqXU4uI4MJFJiYmBoDc3Fxq1apVujw3N5c2bdqc9X3+/v74++uupeLecm2FPPv1Fj5ZvR+AYH8fhl3RkNu71sPfx9vkdCIirsNli0xCQgIxMTGkp6eXFhebzcby5cu59957zQ0nUkGsJ4qZuWw3k3/6lRNFDgD6ta/DQ/9sQlRIgMnpRERcj6lFJj8/nx07dpQ+37VrF2vWrCEiIoL4+HhGjBjBuHHjaNSoEQkJCYwZM4bY2Fiuv/5680KLVIAN+63MXLqHz9bup7DYCUC7+HAe69Wc1nHh5oYTEXFhphaZlStXcvnll5c+/+3clkGDBjFjxgz+/e9/U1BQwJAhQ8jLy6Nbt24sWLCAgAD9y1TcX2Gxgy/XHWDmsj2sOX0ODEBiTAj3/qMB17WO1XkwIiJ/w2IYhmF2iIpks9kICwvDarUSGhpqdhwR9hwpYPbyvcxZmcWxE8UA+HpbuKZlLW7rXJf2daurwIiIxzvXz2+XPUdGpCpxOA1+2nqQmcv2sHDbIX7750Pt8EBuSYqnf8c4agTrJHURkfOlIiNSgQ7n25mzMotZy/ayP+9k6fLLGtfkts51uTwxSnfjFRG5CCoyIuXMMAwy9xxj5rI9fLX+AMWOU7tfwqv5cmOHOG7pFE+9GkEmpxQRqRpUZETKSYG9hM/WZDNz2R42H/jfaIzWceHc1rku17aqRYCv7gEjIlKeVGRELtL23OO8t2wPn6zaz3F7CQD+Pl70bhPLrZ3r0qpOuLkBRUSqMBUZkQtQ7HDy7cZcZi7bzbKdR0uXJ9QIYkBSPDe0r0N4NT8TE4qIeAYVGZHzcMB6kvczsvggYy8HTw9w9LJAStNobkuuS9cGNfDSybsiIpVGRUbkbxiGwZJfjzBz6R6+25yLw3nq5N0awf7c3CmOmzvFExseaHJKERHPpCIjchbWk8V8nLmP95bvYeehgtLlnRIiuK1zXbo3j8HPx8vEhCIioiIj8gcb9lt5b9kePluTzcniU4Mbg/y86dOuDrd2rkuTmBCTE4qIyG9UZEQ4Nffoq/Wn5h6t3ptXurxJdAi3Jtfl/9rWJthff11ERFyNfjOLR9t75ASzMvYwZ0XZuUc9WtTituS6dNDcIxERl6YiIx7H4TRYuO0gM5fu4affzT2KDQvglqR4buwYR1SIJqyLiLgDFRnxGEfy7cxZuY9Zy/ew79j/5h5d2rgmtybFc0ViFD7eOnlXRMSdqMhIlWYYBqv25vHesj18ue4ARQ4nAGGBvtzYoQ63JNUlQXOPRETcloqMVEknik7PPVq6h02/m3vUqk4Yt3WuS6/WsZp7JCJSBajISJWy42A+7y3bw8eZ+8rMPbqu9am5R63jws0NKCIi5UpFRtxascPJhv1Wlu86yo9bDrJ81//mHtWLrMatnetq7pGISBWmIiNupdjhZP1+K8t2HmHZzqNk7j5KQZGjdL2XBa5sGs1tnevSraHmHomIVHUqMuLSikqcrN+fx7KdR1m28wiZe45x4nfFBU6duNspIYKkhAj+2SKGOtWrmZRWREQqm4qMuBR7iYN1+6ws/22Py55jpWMCfhNezZekhAiSEiLpXD+SxJgQ7XkREfFQKjJiKnuJg7VZvx0qOsKqvccoLHaWeU1EkB+d6kXQuX4EnRtE0jhKxUVERE5RkZFKVVjsYE1WHst2HmH5zqOs2nsMe0nZ4hIZ5EdS/Qg6148kKSGSRlHBKi4iInJGKjJSoQqLHazae4zlp89xWZ2VR9EfikuNYD+S6kfSOeFUeWkYFaz5RiIick5UZKRcnSxysHrvsdKritZk5ZXeTfc3NUP8STpdWjrXj6RBzSAVFxERuSAqMnJRThSVsGrP6UNFu46wJiuPYodR5jVRIf6lpSWpfgT1a6i4iIhI+VCRkfNSYC8hc88xlu86tcdl3b4/F5eY0AA61484dbiofiT1IqupuIiISIVQkZG/VGAvYeWeY6dPzj3Cun1WSpxli0utsIDTe1xOHS6Kj1BxERGRyqEiI2UcLyz+XXE5yvr9Vhx/KC61wwNLryrqnBBJXESgiouIiJhCRcZDFZU4OVpQxJECOwfyClmx+9RVRRuybX8qLnWqB56+FPpUeYmL0J1zRUTENajIVBGFxQ6OFhSdLidFHC2wcyT/9H/n/27Z6ee/TYY+k/iIaqWlJal+hG75LyIiLsstisykSZN4/vnnycnJoXXr1rz22mt06tTJ7FgVqrDYwZGCIo7k/698/FZSjuTbf1dYTj3y/6KYnI23l4Xq1fyoEexH6zrhJJ0+Qbd2eGAFfEciIiLlz+WLzIcffkhaWhpTpkwhKSmJCRMm0L17d7Zu3UpUVJTZ8c7ZiaISjpSWEXvpf5+tnPxxMOK58PGyEBHkR0SQH5HBfkQE+RMZ5EdkkB8Rwaf/N8ifiKBT5SU0wFd3zBUREbdmMQzD+PuXmScpKYmOHTsyceJEAJxOJ3FxcQwbNoxRo0b97fttNhthYWFYrVZCQ0PLLdeJohIOHz9VSv5XRn53+Oa3kpJ/6jV/nB90Lny9TxWTyCD/08XkdEkJ8iMy2L/0v397TWigj066FRGRKuFcP79deo9MUVERmZmZjB49unSZl5cXKSkpLF269Izvsdvt2O320uc2m61Csv133gbmrd5/Xu/x8/EqLR6n9or4lyknEacLym97UEL8VUxERET+iksXmcOHD+NwOIiOji6zPDo6mi1btpzxPePHj2fs2LEVni0yyA9/H6+/LiO/O6QTGexPkJ+3iomIiEg5cukicyFGjx5NWlpa6XObzUZcXFy5f51RPRL5b8+mKiYiIiImcukiU6NGDby9vcnNzS2zPDc3l5iYmDO+x9/fH39//wrP5uPtVeFfQ0RERP6aS38a+/n50b59e9LT00uXOZ1O0tPTSU5ONjGZiIiIuAKX3iMDkJaWxqBBg+jQoQOdOnViwoQJFBQUcMcdd5gdTUREREzm8kWmf//+HDp0iEcffZScnBzatGnDggUL/nQCsIiIiHgel7+PzMWqqPvIiIiISMU5189vlz5HRkREROSvqMiIiIiI21KREREREbelIiMiIiJuS0VGRERE3JaKjIiIiLgtFRkRERFxWyoyIiIi4rZUZERERMRtufyIgov1242LbTabyUlERETkXP32uf13AwiqfJE5fvw4AHFxcSYnERERkfN1/PhxwsLCzrq+ys9acjqdZGdnExISgsViKbft2mw24uLiyMrK0gwnF6GfiWvRz8O16OfhWvTz+HuGYXD8+HFiY2Px8jr7mTBVfo+Ml5cXderUqbDth4aG6g+hi9HPxLXo5+Fa9PNwLfp5/LW/2hPzG53sKyIiIm5LRUZERETclorMBfL39+exxx7D39/f7Chymn4mrkU/D9ein4dr0c+j/FT5k31FRESk6tIeGREREXFbKjIiIiLitlRkRERExG2pyIiIiIjbUpG5QJMmTaJevXoEBASQlJRERkaG2ZE80vjx4+nYsSMhISFERUVx/fXXs3XrVrNjyWnPPPMMFouFESNGmB3Fo+3fv59bb72VyMhIAgMDadmyJStXrjQ7lkdyOByMGTOGhIQEAgMDadCgAU8++eTfzhOSs1ORuQAffvghaWlpPPbYY6xatYrWrVvTvXt3Dh48aHY0j7Nw4UJSU1NZtmwZ3333HcXFxVx99dUUFBSYHc3jrVixgjfeeINWrVqZHcWjHTt2jK5du+Lr68vXX3/Npk2bePHFF6levbrZ0TzSs88+y+uvv87EiRPZvHkzzz77LM899xyvvfaa2dHcli6/vgBJSUl07NiRiRMnAqfmOcXFxTFs2DBGjRplcjrPdujQIaKioli4cCGXXnqp2XE8Vn5+Pu3atWPy5MmMGzeONm3aMGHCBLNjeaRRo0bxyy+/8PPPP5sdRYBrr72W6Ohopk2bVrqsb9++BAYG8t5775mYzH1pj8x5KioqIjMzk5SUlNJlXl5epKSksHTpUhOTCYDVagUgIiLC5CSeLTU1lZ49e5b5eyLm+Pzzz+nQoQP9+vUjKiqKtm3bMnXqVLNjeawuXbqQnp7Otm3bAFi7di2LFy+mR48eJidzX1V+aGR5O3z4MA6Hg+jo6DLLo6Oj2bJli0mpBE7tGRsxYgRdu3alRYsWZsfxWB988AGrVq1ixYoVZkcRYOfOnbz++uukpaXx8MMPs2LFCu6//378/PwYNGiQ2fE8zqhRo7DZbCQmJuLt7Y3D4eCpp55iwIABZkdzWyoyUmWkpqayYcMGFi9ebHYUj5WVlcXw4cP57rvvCAgIMDuOcKrgd+jQgaeffhqAtm3bsmHDBqZMmaIiY4I5c+Ywa9YsZs+eTfPmzVmzZg0jRowgNjZWP48LpCJznmrUqIG3tze5ublllufm5hITE2NSKhk6dChffPEFixYtok6dOmbH8ViZmZkcPHiQdu3alS5zOBwsWrSIiRMnYrfb8fb2NjGh56lVqxbNmjUrs6xp06Z8/PHHJiXybA899BCjRo3ipptuAqBly5bs2bOH8ePHq8hcIJ0jc578/Pxo37496enppcucTifp6ekkJyebmMwzGYbB0KFDmTdvHj/88AMJCQlmR/JoV155JevXr2fNmjWljw4dOjBgwADWrFmjEmOCrl27/umWBNu2baNu3bomJfJsJ06cwMur7Eevt7c3TqfTpETuT3tkLkBaWhqDBg2iQ4cOdOrUiQkTJlBQUMAdd9xhdjSPk5qayuzZs/nss88ICQkhJycHgLCwMAIDA01O53lCQkL+dH5SUFAQkZGROm/JJCNHjqRLly48/fTT3HjjjWRkZPDmm2/y5ptvmh3NI/Xq1YunnnqK+Ph4mjdvzurVq3nppZe48847zY7mvgy5IK+99poRHx9v+Pn5GZ06dTKWLVtmdiSPBJzxMX36dLOjyWmXXXaZMXz4cLNjeLT58+cbLVq0MPz9/Y3ExETjzTffNDuSx7LZbMbw4cON+Ph4IyAgwKhfv77x3//+17Db7WZHc1u6j4yIiIi4LZ0jIyIiIm5LRUZERETcloqMiIiIuC0VGREREXFbKjIiIiLitlRkRERExG2pyIiIiIjbUpERERERt6UiIyJuxeFw0KVLF/r06VNmudVqJS4ujv/+978mJRMRM+jOviLidrZt20abNm2YOnUqAwYMAGDgwIGsXbuWFStW4OfnZ3JCEaksKjIi4pZeffVVHn/8cTZu3EhGRgb9+vVjxYoVtG7d2uxoIlKJVGRExC0ZhsEVV1yBt7c369evZ9iwYTzyyCNmxxKRSqYiIyJua8uWLTRt2pSWLVuyatUqfHx8zI4kIpVMJ/uKiNt6++23qVatGrt27WLfvn1mxxERE2iPjIi4pSVLlnDZZZfx7bffMm7cOAC+//57LBaLyclEpDJpj4yIuJ0TJ05w++23c++993L55Zczbdo0MjIymDJlitnRRKSSaY+MiLid4cOH89VXX7F27VqqVasGwBtvvMGDDz7I+vXrqVevnrkBRaTSqMiIiFtZuHAhV155JT/99BPdunUrs6579+6UlJToEJOIB1GREREREbelc2RERETEbanIiIiIiNtSkRERERG3pSIjIiIibktFRkRERNyWioyIiIi4LRUZERERcVsqMiIiIuK2VGRERETEbanIiIiIiNtSkRERERG3pSIjIiIibuv/AWOzZN5G9r1/AAAAAElFTkSuQmCC\n" }, "metadata": {} } ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.12" }, "colab": { "provenance": [] } }, "nbformat": 4, "nbformat_minor": 0 }