def add_together(one, two):
    one = one + two
    return one

def mutiply_and_add(one, two):
    one = add_together(one, two)
    return one * one

temparary_value = mutiply_and_add(2, 3)

print(temparary_value)
print(mutiply_and_add(2, 3))

"""
Explanation: Calling Functions from Functions
End of explanation
"""


number_1 = 10
number_2 = 30
print(len(str(number_1 * number_2)))
print(len(number_1 * number_2))

some_string = 'cow'

print(some_string)

some_string = some_string + ' town'

print(some_string)

print('\n\n\n\n')

print('meow cats'.ljust(10))

words = ['one', 'two']
words_two = words

words[0] = 'dinasour'

print(words)
print(words_two)

print(ord('z'))
print(ord('a'))
print(ord('z') - ord('a'))

import math

# Cannot range over infinity
for i in range(math.inf):
    print(i)

def get_rows():
    return [1,2,3,4,5,6,7,8,9,10,11,12]

def get_columns():
    return [1,2,3,4,5,6,7,8,9,10,11,12]

def get_max_width(first_number, second_number):
    """
    Return the widest a given mutiplication times table cell should be
    """
    highest_value_str = str(first_number * second_number)
    
    return len(highest_value_str) + 2 # Add two to make it appear to be one bigger on each side


rows = get_rows()
columns = get_columns()
max_width = get_max_width(max(rows), max(columns))
output = ''

# Go over the numbers to produce each row in the times table
for row_value in rows:
    
    # Create each column in the times table with this for loop
    for col_value in columns:
        product_str = str(row_value * col_value)
        output = output + product_str.rjust(max_width)
    
    # Add a new line after each set of numbers to ensure the next
    # number in the times table gets its own row.
    output += '\n'

print(output)

"""
Explanation: Interating over a collection
Make the 12 x 12 times table
End of explanation
"""


# For each word in our list of words I want to "translate" it
from random import shuffle

new_alphabet = ['l', 'i', 'g', 'a', 'f', 'x', 'o', 'e', 'v',
                'y', 'r', 'b', 'd', 'h', 'm', 'p', 'k', 'u',
                'w', 'j', 's', 'q', 'c', 'z', 't', 'n']

words = ['The', 'quick', 'brown', 'fox',
         'jumps', 'over', 'the', 'lazy', 'dog']

# Normalize the words
position = 0
for word in words:
    words[position] = word.lower()
    position += 1

# Go over each word and replace it with the 'modified' word
# Create a new list so that we do not modify the original
word_index = 0
new_words = list(words)
for word in words:
    # Initialize the new word
    new_words[word_index] = ''
    
    # Go over and setup each new word replacing the old letters
    for letter in word:
        new_alphabet_position = ord(letter) - ord('a')
        new_words[word_index] += new_alphabet[new_alphabet_position]
    
    # Increase the word index so we populate the word in the list correctly
    word_index += 1
        

print('Existing words: ', words)
print('New words: ', new_words)


"""
Explanation: Iterating over a list of strings
Shows how to iterate over strings and that you can iterate over sub collections as well
End of explanation
"""


import math

def times_x(value, x=10):
    return value * x

def divide_x(value, x=None):
    if x == None:
        return 0
    
    elif x == 0:
        return math.inf # This is infinity
    
    return value / x


print('one', times_x(10))
print('two', times_x(10,5))
print('two', divide_x(20, 10))
print('two', divide_x(20, 0))
print('one', divide_x(20))

def broken_times(x, y):
    if y == None:
        y = 10
    return x * y

# print(broken_times(10))

def x_times_y(x, y):
    if type(x) == int and type(y) == int:
        return x * y
    return None


product = x_times_y(2, 4)
print(product)

product = x_times_y(None, 2)
if type(product) == type(None):
    print('I have no product')
else:
    print(product)


"""
Explanation: Default Parameters
End of explanation
"""


def test_values(first_value, second_value):
    """
    Asserts that the first and second parameters have the same value
    
    Raises an AssertionError if they are different with a message
    """
    failed_message = "{0} is not equal to {1}".format(first_value, second_value)
    assert first_value == second_value, failed_message

    
def is_prime(x):
    if x in [1,2,3,5,7,11,13,15,17]:
        return True
    return False


primes = [1,2,3,5,7,11,13,15,17,19,23]
for prime in primes:
    print(prime)
    test_values(is_prime(prime), True)

"""
Explanation: Bonus: Testing your code
Here is an easy way to test that your code does what you want
End of explanation
"""


