<jupyter_start><jupyter_text>_____ 02. Python Control Flow_____Certain code blocks conditionally and/or repeatedly, and such control flow allows to create surprisingly sophisticate programs. The following notebook will cover these Python control flow topics:- `input()`- *conditional statements* (including "``if``", "``elif``", and "``else``")- *loop statements* (including "``for``" and "``while``")- accompanying statements, such as ``break``", "``continue``", and "``pass``"._____Go through the notebook, play around with the cells and their outputs, attempt to complete the exercises.  User inputs with `input()` Essentially, allows to pass a value to some variable via user inputting.<jupyter_code>my_name = input("What is your name? ")
secret_key = input("Enter the key ")<jupyter_output><empty_output><jupyter_text>`Exercise 1 - Input Formatting`Write a one-liner, which:- Gets the user's first name, last name, and age via `input()`.- Formats these values to a nice-looking strings.- Prints out the string.<jupyter_code>print(f'Your name is {input("First name: ")} {input("Last name: ")}. You are {input("Age: ")} years old.')<jupyter_output><empty_output><jupyter_text>Conditional Statements: ``if``-``elif``-``else``:Conditional statements, often referred to as *if-then* statements, allow the programmer to execute certain pieces of code depending on some Boolean condition. A basic example of a Python conditional statement is this:<jupyter_code>x = -15

if x == 0:
    print(x, "is zero")
elif x > 0:
    print(x, "is positive")
elif x < 0:
    print(x, "is negative")
else:
    print(x, "is unlike anything I've ever seen...")<jupyter_output><empty_output><jupyter_text>Note the use of colons (``:``) and whitespace to denote separate blocks of code.Python adopts the ``if`` and ``else`` often used in other languages; its more unique keyword is ``elif``, a contraction of "else if". In these conditional clauses, ``elif`` and ``else`` blocks are optional, you can include as many/few as you like;Let's dissect this into pieces for simplicity:<jupyter_code>if 1 < 2:
    print('Hi!')
if 1 > 2:
    print('Hi!')
if 1 < 2:
    print('Hi!')
else:
    print('Bye!')
if 1 < 2: print('Hi!')
else: print('Bye!')
if 1 > 2:
    print('Hi!')
else:
    print('Bye!')
if 1 == 2:
    print('Hey!')
elif 3 == 3:
    print('Hello, there!')
else:
    print('Hi!')
if 1 == 2:
    pass
elif 3 == 3:
    print('Hello, there!')
else:
    print('Hi!')
if 1 == 1:
    print('There')
elif 1 == 1:
    print('can be')
else:
    print('only one')
x = -0

if x == 0:
    print(f"x is zero")
elif x > 0:
    print(f"x is positive: {x}")
else:
    print(f"x is negative: {x}")<jupyter_output><empty_output><jupyter_text>`for` loopsLoops in Python are a way to repeatedly execute some code statement, and the `for` loop is arguably the simplest. To be specific, we only have to specify the variable we want to use, the sequence we want to loop over, and use the "``in``" operator to link them together in an intuitive and readable way.E.g., to print each of the items in a list:<jupyter_code>seq = [20, 23, 26, 29, 32, 35, 38]
for x in seq:
    print(x)<jupyter_output><empty_output><jupyter_text>More precisely, the object to the right of the "``in``" can be any Python *iterator*, which can be thought of as of a generalized sequence (for more info, check [iterators](10-Iterators.ipynb). For example, one of the most commonly-used iterators in Python is the ``range`` object discussed earlier (generates a sequence of numbers).   `Exercise 2 - Sequence & Indices`Print `seq` items with their indices, e.g.:    Index: 0	Value: 20    Index: 1	Value: 23    ...  `Exercise 3 - Err...Multiplication Table?...What for?`Write a Python program to create the multiplication table (from 1 to 10) of a single number given by `input()`. Expected Output:    Input a number: 6                                                           6 x 1 = 6                                                                   6 x 2 = 12                                                                  6 x 3 = 18                                                                  6 x 4 = 24                                                                  6 x 5 = 30                                                                  6 x 6 = 36                                                                  6 x 7 = 42                                                                  6 x 8 = 48                                                                  6 x 9 = 54                                                                  6 x 10 = 60   `Exercise 4 - Err...Multiplication Table?...Again?`Using `for` and what you've learnt about Python printing, recreate the full multiplication table (from 1 to 10).    1   2   3   4 ..                                                    2   4   6   8 ..    3   6   9 ......      4   ............    5   ............    ................  ``break`` and ``continue``: Fine-Tuning Your LoopsThere are two useful statements that can be used within loops to fine-tune how they are executed:- The ``break`` statement breaks-out of the loop entirely- The ``continue`` statement skips the remainder of the current loop, and goes to the next iterationThese can be used in both ``for`` and ``while`` loops.<jupyter_code>for something in seq:
    print(something + something)
    if something + something == 52:
        break
for x in seq:
    if x ** 2 < 900: 
        continue
    print(x)
for x in seq: print(x)
for x in seq:
    print(x)
else:
    print('All done!')
for x in seq:
    print(x)
    if x == 26:
        print('Oh no! We encountered 26!')
        break
else:
    print('All done!')
# Buil-in library import
import random

# Define the haystack size and choose a secret index at which the needle may appear
haystack_length = 1000
haystack = [0] * haystack_length
secret_index = random.randint(0, haystack_length - 1)

# Needle appears within the secret haystack index randomly (coin flip)
if random.random() > 0.5:
    haystack[secret_index] = 1

for i, x in enumerate(haystack):
    if x:
        print(f'Needle\'s position in the haystack is {i}')
        break

# else clause happens if no break was encountered
else:
    print('Needle is not in the haystack')
x = 1, 4, 10, -10
the_sum = 0

for value in x:
#     the_sum += value
    the_sum = the_sum + value
    
the_sum
for c in 'My favourite color is blue':
    if c in 'color':
        print("c is in the string color")
    elif c in ['f', 'b']:
        print("c is either f or b")
        print(c)<jupyter_output><empty_output><jupyter_text>`Exercise 5 - Palindrome`Write a python program that checks if the `input()` string is a **palindrome** - word, number, phrase, or other sequence of characters which reads the same backward as forward, e.g.: madam, bob, 12121.    Input string: abc    Expected output:        String 'abc' is not a palindrome.        String '121' is a palindrome.  `Exercise 6 - Moving Averages`Write a python program iterates over a list of numbers and calculates 3 different means throughout the `for` cycle:- Cumulative mean - the current average (up to the current `for` iteration), should be printed during each cycle.- Moving average - mean of the last three itegers observed within the `for` cycle, should be printed during each cycle- Total average - should be printed at the end of the cycle.E.g.:    input_list = [10, 15, 30, 40]    Expected output:        Iterating over `input_list`...        Index: 0    Number: 10    Cumulative Mean: 10    Moving:   10      Index: 1    Number: 20    Cumulative Mean: 15    Moving:   15      Index: 2    Number: 30    Cumulative Mean: 20    Moving:   20      Index: 3    Number: 40    Cumulative Mean: 25    Moving:   30          Total Mean: 25  ``while`` loopsThe other type of loop in Python is a ``while`` loop, which iterates until some condition is met:<jupyter_code>i = 1
while i < 5:
    print(f'i is {i}')
    i = i + 1
def calculate_gradient(a, b):
    return b-a

a = int(input('Enter A: '))
b = int(input('Enter B: '))

grad = calculate_gradient(a, b)
grad += 100
grad /= 10

while a < b:
    grad = calculate_gradient(a, b)
    grad += 100
    grad /= 10

print(grad)<jupyter_output><empty_output><jupyter_text>`while` with `break` and `continue`<jupyter_code>i = 100

while True:
    print(i)
    if i >= 10:
        break
    i += 1
# continue start a new loop cycle
for n in range(12):
    if n % 2 == 0:
        continue
    print(n, end=', ')<jupyter_output><empty_output><jupyter_text>`else` for `while` and `for` loops<jupyter_code>for i in range(5):
    print(i)
#     if i == 3: break
else:
    print('I\'m done')
loss = 10
target_loss = 5
while target_loss < loss:
    print('Training: current loss is {}'.format(loss))
    loss -= 1
else:
    print('Finished training')
l = []
n = 15

for i in range(2, n):
    for factor in l:
        if i % factor == 0:
            break
    else:
#         this only happens if there was no break
        l.append(i)

print(l)<jupyter_output><empty_output><jupyter_text>`Exercise 7 - Factorial While`Write a python program to print out the factorials for all of the numbers up to `N` using `while`. E.g.:    Your input number: 3        1! = 1    2! = 2    3! = 6    4! = 24    ...  `Hint` Don't input high values (e.g., `>100`), it gets messy real quick. Even better, add a `break` statement at some chosen threshold value, or use `input()` with `if` and `then` to guide the user in providing an input that is small enough if necessary.  `Exercise 8 - While There is a Needle in the Haystack`Adapt the needle in the haystack example above using `while`. The program should go through the haystack indices until the needle is found. If so, it should print out where, or otherwise state that the needle was not found.   `Exercise 9 - Token Count`In this example, you should create a Python script that would read the contents of a given text file and calculate the amount of times each word occurs within it. Then, it should print `N` most commonly occuring values. To make it simpler, you already have a provided backbone script for reading the file and obtaining a list of tokens from it.<jupyter_code>input_file_path = 'data/clinton_trump_corpus/Trump/Trump_2016-11-09.txt'

with open(input_file_path, 'r') as inputfile:
    tokens = inputfile.read().lower().split()
    tokens = [t.strip() for t in tokens if t.isalpha()]

# TODO: COUNT THE TOKENS<jupyter_output><empty_output><jupyter_text>_____ ComprehensionsComprehensions are one of the Pythons features that allow to compress large functions with many control flow statements into a single, short, and readable line._____ List comprehensionsHere is a basic loop that constructs a list of squares for the numbers provided in `nums`:<jupyter_code>nums = [1, 2, 3, 4]
results = []
for item in nums:
    results.append(item**2)

results
results = [item ** 2 for item in nums]
results<jupyter_output><empty_output><jupyter_text>`Exercise 10 - Ra(n)ging Comprehension`Use list comprehension to obtain the following given input `5`:    [[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]  `Exercise 11 - Flatten`Write a script that would flatten the list obtained in `Exercise 10`. E.g., when given a list of lists as an input, you should return a single list containing all of the elements.  `Exercise 12 - Flatten Comprehension`Recreate the `Exercise 11`, as well as the functions given below in a list comprehension form.<jupyter_code>flat_list = []

for inner_list in data:
    if len(inner_list) % 2 == 1:
        for item in inner_list:
            flat_list.append(item)
        
flat_list
flat_list = [
    item
    for inner_list in data
    if len(inner_list) % 2 == 1
    for item in inner_list
]
flat_list
flat_list = []

for inner_list in data:
    if len(inner_list) % 2 == 1:
        for item in inner_list:
            if item % 2 == 0:
                flat_list.append(item)
        
flat_list
flat_list = [
    item
    for inner_list in data
    if len(inner_list) % 2 == 1
    for item in inner_list
    if item % 2 == 0
]
flat_list<jupyter_output><empty_output><jupyter_text>Dictionary comprehensions<jupyter_code>keys = list('abcdefg')
values = list(range(1, len(keys)))
keys, values
alphabet = {}
for key, value in zip(keys, values):
    alphabet[key] = value
    
alphabet
alphabet = {key: value for key, value in zip(keys, values)}
alphabet<jupyter_output><empty_output><jupyter_text>`Exercise 13 - Better than comprehension?`Comprehensions are amazing, but sometimes there are better solutions. Make the previous version shorted and more Pythonic.  Set comprehensions<jupyter_code>alphabet = {letter for letter in 'alphabet_alphabet'}
alphabet<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10530029794574251, 'fraction_numerical': 0.023365218754900424, 'mean_word_length': 2.783743696232572, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '348328', 'license': 'Apache-2.0', 'n_tokens_mistral': 4032, 'n_tokens_neox': 3694, 'n_words': 1597, 'path': '01_Python_Crash_Course/02_Control_Flow_and_Comprehensions.ipynb', 'repo_name': 'udemeudofia/CA_AI_2020', 'size': '12754'}