# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     name: python3
# ---

# + [markdown] id="view-in-github" colab_type="text"
# <a href="https://colab.research.google.com/github/davidkant/mai/blob/master/tutorial/1_1_Hello_Python.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>

# + [markdown] id="-bEMPSTz3c60" colab_type="text"
# # Welcome to Python!
# Welcome to **Python** and the **Google Colaboratory**. Google Colaboratory is a Python environment that runs in the cloud and integrates with Google Drive. It allows us to write, run, and view the results of Python code all in the browser. Notebooks are accessed, stored, and shared via Google Drive and run using a desktop web browser — I recommend Chrome. Google Colaboratory is a cloud-based version of [**Jupyter Notebook**](https://jupyter.org/), which doesn't run in the cloud. 

# + [markdown] id="-hZnrJZAbwvA" colab_type="text"
# ## About Python
#
# Python is a general purpose, high-level, dynamic programming language that emphasizes human readable code and supports multiple programming paradigms. Python is interpreted; we can run code line by line, rather than all at once, which is useful for stepping through complex algorithms. If you're familiar with languages like Java or C, you'll notice an absence of semicolons and curly braces in Python. That's because in Python whitespace is meaninful! More on that later.

# + [markdown] id="gHDduaHP3iIc" colab_type="text"
# # Cells 
# Code lives in individual blocks called *cells*. You write code within a cell and then execute that cell by selecting "Run focused" from the "Runtime" dropdown menu above. Alternatively, use the keyboard shortcut Ctrl+Enter. Navigate to the cell below and run it. 

# + id="wPPRZzHo5wro" colab_type="code" outputId="adb083b9-8fa2-498e-e451-e95994535ac2" colab={"base_uri": "https://localhost:8080/", "height": 35}
print("Hello 80L!")

# + [markdown] id="Aab8CsAP1TBc" colab_type="text"
# # Hello World
# The first thing we usually do in any programming language is write the program *Hello World*, which prints the text "Hello World" to the console. In Python, use the `print()` function, placing what you want to display inside of the parenthesis `()`. Note: the quotation  marks `""` do not print.

# + id="eeZ8-R3Tn57s" colab_type="code" outputId="21d015df-1cee-4169-9e07-61f268097c3d" colab={"base_uri": "https://localhost:8080/", "height": 35}
print("Hello 80L!")

# + [markdown] id="4sUGm87K6LNu" colab_type="text"
# # The Python Interpreter
# `Print()` isn't the only way to see the resuls of your code. Code cells allow you to interact with the Python *interpreter*, which is what we call the program that executes your code. By default, whenever you execute a cell, the interpreter returns the result of that execution. Execute the cell below and you should see the result of your computation.

# + id="9Zbek0s67Jos" colab_type="code" outputId="f1cfc1ae-d4b1-4f26-8677-8d3b938ce820" colab={"base_uri": "https://localhost:8080/", "height": 35}
1 + 2

# + [markdown] id="bBoyHmSY8QKg" colab_type="text"
# What do you think we'll see when we run the cell below?... If the cell contains multiple lines of code, the interpreter executes *all* of the lines, but displays the result of the *last line only*.

# + id="3TWCbDp88HFK" colab_type="code" outputId="50f08243-c473-4771-ac09-af70918696b8" colab={"base_uri": "https://localhost:8080/", "height": 35}
1 + 2
2 + 3
3 + 4
4 + 5

# + [markdown] id="J8jsw1-o1xBR" colab_type="text"
# Use `print()` to see the result of each line.

# + id="BdEAbr6m12VZ" colab_type="code" outputId="74fcb7d4-23e3-4562-848c-70a37021d368" colab={"base_uri": "https://localhost:8080/", "height": 87}
print(1 + 2)
print(2 + 3)
print(3 + 4)
print(4 + 5)

# + [markdown] id="rBf6aj861XgS" colab_type="text"
# # Comments
# A comment is code that is not executed by the interpreter. Comments are indicated by the pound symbol `#`. We'll use comments to make notes to ourselves about what our code does. Remember, comments are there for the computer programmer — that's you! — not the computer program.

# + id="Wz9EoVEJ1YiI" colab_type="code" outputId="084cac02-dc3b-4c2d-dfd2-b5cdffa3a062" colab={"base_uri": "https://localhost:8080/", "height": 35}
# note to self, you can write anything here!
print("Hello 80L!")

# + [markdown] id="dWUEuRAy_xWI" colab_type="text"
# # Python as a Calculator
# Computers are great for doing math, and Python is capable of performing all of the standard arithmetic operations: addition, subtraction, multiplication, division, and exponentiation.

# + id="UHzDbq4kAPiy" colab_type="code" outputId="36951c14-a9bb-4850-cfff-64df32f2d157" colab={"base_uri": "https://localhost:8080/", "height": 156}
# addition
print(79 + 1)

# subtraction
print(100 - 1)

# multiplication
print(2 * 5)

# division
print(33 / 11)

# floor division (quotient)
print(10 // 8)

# modulo division (remainder)
print(10 % 8)

# exponents
print(2**3)

# complex expressions (order of operations)
print(-2 + 3 * 4 - 10)

# + [markdown] id="eUeLEcFdsZ1M" colab_type="text"
# One of these numbers looks different than the others... Any idea why?

# + [markdown] id="BWHaHw-8-XMS" colab_type="text"
# # Variables
# A fundmental concept in computer programming is the *variable*. Variables allow us to keep track of data by storing it for later. Variables have both a *name* and a *value*. The process of *variable assignment* associates a variable name with a given value.

# + [markdown] id="S5Ap4i3pDT2o" colab_type="text"
# In the cell below, `my_first_variable` is the variable name, `9` is the variable value, and the equals sign `=` assigns the value `9` to the name `my_first_variable`.

# + id="XG70D1ASDFya" colab_type="code" colab={}
# declare my variable
my_first_variable = 9

# + [markdown] id="OYNELlanD8dC" colab_type="text"
# We can declare our variable in one cell and recall it in another. Variables *persist* between cells. In fact, variables persist throughout an entire notebook, allowing us to keep track of data from one cell to the next. BUT once you close the notebook, it's all over... 

# + id="rN9BYog0DoJ0" colab_type="code" outputId="2bb08145-3ba1-4013-8484-817cf0aed66a" colab={"base_uri": "https://localhost:8080/", "height": 35}
# recall my variable
print(my_first_variable)

# + [markdown] id="2_GS7trSnRDV" colab_type="text"
# Note that when we print `my_first_variable` the *value* is printed, not the variable *name*.

# + [markdown] id="2lXwf5VnV882" colab_type="text"
# The value of a variable *can* be modified once it's declared.

# + id="sXqvzK2FWFda" colab_type="code" outputId="b62726ec-a980-4ae7-e950-f45c43b2e46a" colab={"base_uri": "https://localhost:8080/", "height": 35}
# change the value of my variable to 1
my_first_variable = 1

# and then print it
print(my_first_variable)

# + [markdown] id="bfRnCTykWR6Y" colab_type="text"
# We can even use the value of a variable to modify itself!

# + id="rFqxcUHIWWX6" colab_type="code" outputId="8fda486b-1551-4492-a9f9-a52585f4235d" colab={"base_uri": "https://localhost:8080/", "height": 35}
# increment value of my variable by 1
my_first_variable = my_first_variable + 1

# and then print it
print(my_first_variable)

# + [markdown] id="ecXxoU6tpDrP" colab_type="text"
# # Errors
# What happens if we use a variable name *before* we declare it? ...Say hello to your first *Error*. We'll definitely see a lot of these, so don't let all of that red text induce too much fear. The best way to become a better programmer is to get friendly with errors. Think of them as friendly reminders of what went wrong. In this case, the error message is telling us exactly what the problem is: we used a varaible name that is not defined.

# + id="6qcM4njapHLj" colab_type="code" outputId="cc61ef68-ba7e-4959-b022-c25b2b97012b" colab={"base_uri": "https://localhost:8080/", "height": 167}
print(my_second_variable)

# + [markdown] id="29R_xkdpWwgC" colab_type="text"
#
# # Numbers come in a few varieties
# A few cells up, when we divided `33` by  `11`, we got `3.0`, which looked a bit different because of the decimal point. Python distinguished between *integers* and *floating point* (or decimal) numbers. Integers (called *ints*) can only take on whole number values, where as floating point numbers (called *floats*) can take on fractional values as well. When we divided `33` by `11`, Python automatically converted the result to a float, because division often produces fractional results. For example: 

# + id="g7NbueSVW7Pw" colab_type="code" outputId="90e4d4a8-f994-47d1-b2e8-4db69073a275" colab={"base_uri": "https://localhost:8080/", "height": 35}
33 / 10

# + [markdown] id="_STHMFqcZ48E" colab_type="text"
# # Data Types
# The difference between `ints` and `floats` is an example of a more general computer science concept called *data types*. Data is classified into different  types, which determine the possible values the data can represent and the possible operations that can be performed on them. There are many data types, but we'll just need a few:
#
# * integers (`int`) represent whole numbers
# * floating point numbers (`float`) represent fractional numbers
# * booleans (`bool`) can take on either of two values, `True` or `False`
# * strings (`str`) is a sequence of characters, often used to represent words

# + id="JfQprtTqZ1-0" colab_type="code" outputId="c77d0ca6-aae0-439e-8b5c-2cb6cf9d0d2f" colab={"base_uri": "https://localhost:8080/", "height": 87}
# an intger
print(1)

# a boolean
print(True)

# a floating point
print(1.0)

# a string
print("Hello 80L!")

# + [markdown] id="_rmb0FwM5xMT" colab_type="text"
# In Python 3, we don't need to be super aware of basic data types because the interpreter infers much of it for us. This isn't the case, however, with many other programming languages, where you  need to be very careful with your data types!

# + [markdown] id="7CMNl9B96f7h" colab_type="text"
# # Strings vs variable names
# Strings are written with quotation makes `""` to distinguish them from variable names. Why *doesn't* the following cell print? 

# + id="pmbe0e4u7Gq4" colab_type="code" outputId="afb54577-43f1-4926-9696-8552b9e0b266" colab={"base_uri": "https://localhost:8080/", "height": 167}
print(Hello_80L)

# + [markdown] id="MJWDWie-70ps" colab_type="text"
# Since `Hello_80L` is written *without* quotation marks, the interpreter treats it as a *variable name*. That variable name, however, has not be defined yet, so we get an error. How would you fix the code to print "Hello_80L"? One option would be to add quotation marks, making it a *string*.

# + id="xDhu3zhP7M1A" colab_type="code" outputId="a97ab26a-3066-48ad-8c98-69bb127afb2f" colab={"base_uri": "https://localhost:8080/", "height": 35}
print("Hello_80L")

# + [markdown] id="KgBLhNtv-dik" colab_type="text"
# # Lists
# A *data structure* is a way of organzing, storing, and structuring data within a computer program. Often we'll want to collect together many values in order represent something — a piece of music, for example! Data structures define relationships among a collection of values, as well as operations on them, and different data structures reflect different ideas about how to represent information. 
#
# There are many many ways of reprsenting data, but throughout this course the *list* will be the most commonly used. A list is an ordered set of elements. It is delimitted by square brackets `[]` and the elements are separated by commas `,`.

# + id="dYCjuONqZCrg" colab_type="code" outputId="44625ff7-2c22-4652-c6fe-ddf47cfaedef" colab={"base_uri": "https://localhost:8080/", "height": 35}
# a simple list of numbers
my_first_list = [1, 2, 3, 4, 5]

# and print it
print(my_first_list)

# + [markdown] id="XSpO4vc6Zlg8" colab_type="text"
# The elements of a list do not have to all be the same type.

# + id="Mgy87n0RbTiK" colab_type="code" outputId="8771048b-77f4-4934-f408-adc1a2354fa7" colab={"base_uri": "https://localhost:8080/", "height": 35}
# a simple list of mixed types
my_mixed_type_list = [1, True, 1.0, "Hello 80L!"]

# and print it
print(my_mixed_type_list)

# + [markdown] id="vzEmkGAscEvc" colab_type="text"
# ## Accessing list elements 
# You can access individual elements of a list according to their position (called *index*), written using square brackets. Note, compuer scientists like to  **count from 0!**

# + id="ZqVaibTwcEZa" colab_type="code" outputId="c888ba02-cd8b-4c20-9bb0-7221dd5d26d0" colab={"base_uri": "https://localhost:8080/", "height": 69}
# accesss the first element of my list (index 0)
print(my_first_list[0])

# accesss the second element of my list (index 1)
print(my_first_list[1])

# accesss the third element of my list (index 2)
print(my_first_list[2])

# + [markdown] id="a-PzXnx3cuuK" colab_type="text"
# What happens if you try to access an element that does not exist? Here's error number two...

# + id="OgdNiKx6cyaU" colab_type="code" outputId="9cea6b60-0e58-4cbf-916a-3961818fb800" colab={"base_uri": "https://localhost:8080/", "height": 167}
# accesss the sixth element of my list
print(my_first_list[5])

# + [markdown] id="1UxCRh7FBg31" colab_type="text"
# Often you'll need the last (most recently added) element of your list. You can access the last element using the index `-1`.

# + id="iV1cjc8XBoT8" colab_type="code" outputId="6d5208c0-fda0-4138-c80d-1eb4223eeb28" colab={"base_uri": "https://localhost:8080/", "height": 35}
# last element of the list
print(my_first_list[-1])

# + [markdown] id="QTHGH8zydDwC" colab_type="text"
# ## Adding elements to a list
# We can add an element to our list after it is created.

# + id="SabSuHh9dIbq" colab_type="code" outputId="397cabe2-a1e4-47f7-8ae7-c3565faaf17f" colab={"base_uri": "https://localhost:8080/", "height": 35}
# add a sixth element to my list
my_first_list = my_first_list + [6]

# and print it
print(my_first_list)

# + [markdown] id="X3_GUTUWrdEv" colab_type="text"
# We'll do this so much that often you'll see it written using the shortcut `+=`

# + id="cs6LtOkHriTx" colab_type="code" outputId="20f4147e-d89c-4fdf-8f64-d150d5c33dd7" colab={"base_uri": "https://localhost:8080/", "height": 35}
# add a seventh element to my list
my_first_list += [7]

# and print it
print(my_first_list)

# + [markdown] id="ZSvu64FcdSbw" colab_type="text"
# For all you set theorists out there, the empty list exists! Often we'll start with an empty list and incrementally add more and more elements to it.

# + id="4_9VMUYxZWuo" colab_type="code" outputId="429380cf-2009-4d2c-c42e-8668783e3289" colab={"base_uri": "https://localhost:8080/", "height": 52}
# start from an empty list
empty_list = []
print(empty_list)

# and add elements to it
empty_list += ["Not so empty anymore"]
print(empty_list)

# + [markdown] id="Nd5wadPRCXwa" colab_type="text"
# ##Other useful list properties
# You can get the length of your list by writing `len()`. Note, in this cell, `len()` is a *function* and your list is passed as an *argument* to that function, but we'll learn about functions and arguments next week.

# + id="JAyR-QscCxIF" colab_type="code" outputId="d4f2f9b5-2093-4720-899a-8ef612472295" colab={"base_uri": "https://localhost:8080/", "height": 35}
# length of my list
print(len(my_first_list))

# + [markdown] id="TIrTUPuHckuO" colab_type="text"
# Other useful list functions include `min()` and `max()`,  which give the minimum and maximum elements.

# + id="fJ-g9GZ9csg9" colab_type="code" outputId="2fc0a9db-5ffb-4272-9009-6f8cb4c28f08" colab={"base_uri": "https://localhost:8080/", "height": 52}
# max element
print(max(my_first_list))

# min element
print(min(my_first_list))

# + [markdown] id="Nz9Q9SDile1L" colab_type="text"
# ## Generating Lists
# You can always write a list explicitly, which means writing out all of the values between square brackets `[1,2,3,4]`, but what if you want to generate a list using an algorithm or procedure? Python has a nifty *list comprehension* feature (which is really a clever version of a very classic computer science structure called a *for loop* but more on *for loops* next time). Try the next few cells to see if you can intuit what is going on here...

# + id="W1Qh_JrGmEbC" colab_type="code" outputId="4f288de1-84de-464b-8e05-7998f53e3c7b" colab={"base_uri": "https://localhost:8080/", "height": 35}
[x for x in range(5)]

# + id="PZ2ZE4p_ZyLN" colab_type="code" outputId="621f2f50-b90a-41f4-8581-0fce289c9f2b" colab={"base_uri": "https://localhost:8080/", "height": 35}
[x for x in range(10)]

# + id="1bRkQ89amIC_" colab_type="code" outputId="1efb8e1e-e8f0-43de-95d8-c99fba70bbe9" colab={"base_uri": "https://localhost:8080/", "height": 35}
[x**2 for x in range(10)]

# + [markdown] id="JO-Z44Bbse6i" colab_type="text"
# OKSO, the value between the parenthesis of `range()` determines the highest number in the list, and the expression `x**2` applies a function to each item in the list. Basically, we're looping through the values `0` to whatever-our-highest-value-is, applying a function to each element, and collecting it all back together into a new list. Pretty nifty.

# + [markdown] id="IyDGXrwVuIDq" colab_type="text"
# # But how is this music?
# Here's the big question of the clas: how do we turn these lists of numbers into music? See the next section to find out.

# + [markdown] id="cN7LqUNf2j2-" colab_type="text"
# # Getting Help
# There are a few ways to get help with Python, including Python's built-in `help()` function, the [Python Documentation](https://docs.python.org/3.7/), and the internet, including Google, but [Stack Overflow](https://stackoverflow.com/) is also a great place to search for answers. To use the built-in help, write `help()` and put whatever you're curious about between the parenthesis.

# + id="QSwKqsijFYcn" colab_type="code" outputId="dbe9a607-6ccc-47b3-d2d7-810ebc3557a4" colab={"base_uri": "https://localhost:8080/", "height": 2083}
help([1,2])

StarcoderdataJupyterScriptsDedupFiltered