# Noemi Cabrera
# 2 December 2021
# In this lesson, I learned how to test whether a list contains a certain element using the 'in' operator, test whether a string is contained in another string
# using the 'in' operator, test whether objects (i.e. int, float, lists, string) are equal and identical using "==" and "in", and use my knowledge on operator
# precedence (including assignment (=), relational (<, >=,...),Boolean (and, or, not), arithmetic (/ // % * + -), identity (is), and containment (in)) to write
# effective code that displays the desired outcome.
# I didn't have any major difficulties in this lesson.

# In this code, the 'in' operator is used to check if the value of x is in the 'lst_container' list. If this is true, then
# a print statement saying so displays. If this is false, a print statement saying so displays.
# Two values, 5 and 10, are tested. SInce 5 is in the list, a statement saying so displays. Since 10 is not on the list,
# a statement saying so displays.
lst_container = [4, 8, 5, 6]
x = 5
if (x in lst_container):
print(x, "is contained in list")
else:
print(x, "is NOT contained in list")
x = 10
if (x in lst_container):
print(x, "is contained in list")
else:
print(x, "is NOT contained in list")

# In this code, the 'in' operator is used to check if the value of x is in the 'lst_container' list. This is done
# all in one print statement.
# Three values (4, 7, and [7,3]) are tested. SInce 4 is in the list, True displays.
# Since 'in' only checks the list and not its elements, 7 is not found on the list and false displays.
# Since [7, 3] is found on the list, True displays.
# a statement saying so displays.
lst_container = [4, [7, 3], 'string element']
# 4 is an element in lst_container
x = 4
print(x, "contained in lst_container:", x in lst_container)
# 7 is an element of a list inside lst_container, but it is NOT an element of the lst_container
x = 7
print(x, "contained in lst_container:", x in lst_container)
# [7, 3] is an element of lst_container
x = [7, 3]
print(x, "contained in lst_container:", x in lst_container)

# In this code, the 'in' operator is used to check if the string in word1 is in the 'sentence' variable. If this is true, then
# a print statement saying so displays. If this is false, a print statement saying so displays.
# The same check is done with the string in the 'word2' variable.
sentence = "This is a test sentence"
word1 = "test"
word2 = "something"
# testing if word1 is a substring of sentence
if (word1 in sentence):
print(word1, "is contained in:", sentence)
else:
print(word1, "is not contained in:", sentence)
# testing if word2 is a substring of sentence
if (word2 in sentence):
print(word2, "is contained in:", sentence)
else:
print(word2, "is not contained in:", sentence)
# another method to test if word2 is a substring of sentence
# using the not operator
if (word2 not in sentence):
print(word2, "is not contained in:", sentence)
else:
print(word2, "is contained in:", sentence)

# In this code, the user is asked to enter a number between 0 and 100. Then, the "in" operator is used
# in the if/else statement to check if the entered number is in the created list. If true, a statement
# saying so displays. If false, a statement saying so displays.
# [ ] Write a program to prompt the user for an integer input between 0 and 100
# then print if the number is contained in `lst`
lst = [22, 89, 69, 78, 58, 22, 56, 13, 74, 8, 32, 58, 8, 63, 46, 79, 9, 38, 25, 96]
num = int(input("Enter a number between 0 and 100: "))
if (num in lst):
print(num, "is contained in",lst)
else:
print(num, "is not contained in",lst)

# In this code, the "in" operator is used in the if/else statement to check if the list contained in applicant
# is found in the records variable. If the applicant is in the records, a statement saying so displays. If applicant
# is not in the records, a statement saying so displays.
# [ ] The `records` list contains information about a company's employees
# each of the elements in `records` is a list containing the name and ID of an employee.
# Write a program to test if `applicant` is contained in `records` and display an appropriate message
# Records of names and IDs
records = [['Colette', 22347], ['Skye', 35803], ['Alton', 45825], ['Jin', 24213]]
applicant = ['Joana', 20294]
if applicant in records:
print(applicant, "is in the company's employees record")
else:
print(applicant, "is not in the company's employees record")

# In this code, the user is asked to enter a letter. The "in" operator is used in the if/else statement
# to check if the letter is in the variable 'vowels', which contains all the vowels.
# If this is true, a statement saying letter is a vowel displays. If this is false, a statement saying
# letter is not a vowel displays.
# [ ] Write a program to prompt the user for a letter (capital or small) then print if the letter is a vowel
# HINT: Use a string containing all the vowels and the `in` or `not in` operator
letter = input("Enter a letter (capital or small): ").lower()
vowels = "aeiou"
if letter in vowels:
print(letter,"is a vowel")
else:
print(letter,"is not a vowel")

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since both variables equal 5, they are equal. They are also identical because they are saved in the
# same memory location.
# x, y: equal, identical
x = 5
y = 5
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since the value of the variables are different, they are not equal, neither identical.
# x, y: not equal, not identical
x = 5
y = 6
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since both variables equal 5.6, they are equal. However, they are not identical because float numbers are
# saved in different memory locations.
# x, y: equal, not identical
x = 5.6
y = 5.6
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since the variables have different values, they are not equal, neither identical.
# x, y: not equal, not identical
x = 5.6
y = 10.6
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since both variables equal [4, 9, 8], they are equal. However, they are not identical because they are
# saved in different memory locations.
# Different lists containing the same data
x = [4, 9, 8]
y = [4, 9, 8]
# x and y are equal, because they contain the same data
# x and y are NOT identical, because they are saved in different memory locations
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)
# Because they are not identical, changing x does not affect y
x[1] = 5
print()
print("After changing x[1]")
print("x =", x)
print("y =", y)
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==' and 'is' operators are used to test if variable x and y are equal and identical.
# Since both variables equal [4, 9, 8], they are equal. They are also identical because they are saved in the same memory location.
# The variable 'y' contains the list 'x'. So, when a value in the 'x' list is changed, it's also changed in the y list and they are
# still identical.
# Identical list
x = [4, 9, 8]
y = x
# x and y are equal, because they contain the same data
# x and y are identical, because they are saved in the same memory location
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)
# Because they are identical, changing x also changes y
x[1] = 5
print()
print("After changing x[1]")
print("x =", x)
print("y =", y)
print("x equal y ? ", x == y)
print("x is identical to y ?", x is y)

# In this code, the '==', 'is', and 'is not' operators are used to test if variable s1 and s2 are equal and identical.
# Since both variables equal "whole milk", they are equal. However, they are not identical because they are saved in
# different memory locations.Changing one doesn't affect the other.
# s1, s2: equal, not identical
s1 = 'whole milk'
s2 = 'whole milk'
print("s1 equal s2 ? ", s1 == s2)
print("s1 is identical to s2 ?", s1 is s2)
print("s1 is not identical to s2 ?", s1 is not s2)

# In this code, the '==', 'is', and 'is not' operators are used to test if variable s1 and s2 are equal and identical.
# Since both variables equal "whole milk", they are equal. They are also identical because they are saved in the same memory
# location. Changing one affects the other because 's2' contains the 's1' variable.
# s1, s2: equal, identical
s1 = 'whole milk'
s2 = s1
print("s1 equal s2 ? ", s1 == s2)
print("s1 is identical to s2 ?", s1 is s2)
print("s1 is not identical to s2 ?", s1 is not s2)

# In this code, the '==', 'is', and 'is not' operators are used to test if variable s1 and s2 are equal, identical or not identical.
# Since both variables equal "python", they are equal. However, they are not identical because they are saved in
# different memory locations. Changing one doesn't affect the other.
# s1, s2: equal, identical (after interpreter optimization)
s1 = 'python'
s2 = 'python'
print("s1 equal s2 ? ", s1 == s2)
print("s1 is identical to s2 ?", s1 is s2)
print("s1 is not identical to s2 ?", s1 is not s2)

# In this code, the '==', 'is', and 'is not' operators are used to test if variable s1 and s2 are equal and identical.
# The value of both variable is different so they are not equal. Therefore, they cannot be identical.
# s1, s2: not equal, not identical
s1 = 'python'
s2 = 'java'
print("s1 equal s2 ? ", s1 == s2)
print("s1 is identical to s2 ?", s1 is s2)
print("s1 is not identical to s2 ?", s1 is not s2)

# In this code, the '==', 'is', and 'is not' operators are used to test if variables s, e, or i are equal, identical, and not identical.
# Since s and e equal "Whole wheat bread", they are equal. However, they are not identical because they are saved in different memory locations.
# Changing one doesn't affect the other.
# Since s and i equal "Whole wheat bread", they are equal.They are also identical because they are saved in the same memory location. Changing one affects
# the other.
# Lastly, e and i equal "Whole wheat bread", so they are equal. However, they are not identical because they are saved in different memory locations.
# [ ] Write a program to:
# 1) Create a variable `e` that is equal but NOT identical to `s`
# 2) Test the equality and identity of `s` and `e` and print the results
# 3) Create a variable `i` that is equal and identical to `s`
# 4) Test the equality and identity of `s` and `i` and print the results
# 5) Test the equality and identity of `e` and `i` and print the results
s = "Whole Wheat Bread"
#TODO
e = "Whole Wheat Bread"
print("s equal e ? ", s == e)
print("s is identical to e ?", s is e)
print("s is not identical to e ?", s is not e)
print()
i = s
print("s equal i ? ", s == i)
print("s is identical to i ?", s is i)
print("s is not identical to i ?", s is not i)
print()
print("e equal i ? ", e == i)
print("e is identical to i ?", e is i)
print("e is not identical to i ?", e is not i)

# In this code, the '==', 'is', and 'is not' operators are used to test if variables x, e, or i are equal, identical, and not identical.
# Since x and e equal "Whole wheat bread", they are equal. However, they are not identical because they are saved in different memory locations.
# Changing one doesn't affect the other.
# Since x and i equal "Whole wheat bread", they are equal. They are also identical because they are saved in the same memory location. Changing one affects
# the other.
# Lastly, e and i equal "Whole wheat bread", so they are equal. However, they are not identical because they are saved in different memory locations.
# [ ] Write a program to:
# 1) Create a variable `e` that is equal but NOT identical to `x`
# 2) Test the equality and identity of `x` and `e` and print the results
# 3) Create a variable `i` that is equal and identical to `x`
# 4) Test the equality and identity of `x` and `i` and print the results
# 5) Test the equality and identity of `e` and `i` and print the results
x = [[-1, 2],[3, 4],[-5, 6]]
#TODO
e = [[-1, 2],[3, 4],[-5, 6]]
print("x equal e ? ", x == e)
print("x is identical to e ?", x is e)
print("x is not identical to e ?", x is not e)
print()
i = x
print("x equal i ? ", x == i)
print("x is identical to i ?", x is i)
print("x is not identical to i ?", x is not i)
print()
print("e equal i ? ", e == i)
print("e is identical to i ?", e is i)
print("e is not identical to i ?", e is not i)

# In this code, the multiplication is done first because it has a higher precedence than a sum.
# * has higher precedence
2 + 3 * 6

# In this code, the sum is done first because it has parentheses, which have a higher precedence than a multiplication.
# To change precedence, we add ( )
(2 + 3) * 6

# In this code, the multiplication is done first, and the result is tested to see if it is less than 10. Since 6 is less than 10, True displays.
# Arithmetic and relational operations
3 * 2 < 10

# In this code, the exponential number is evaluated first, and the result is added 1. Lasltly, this result is tested to see if it's equal to 16 using ==.
# Since 9 is not equal to 16, False displays.
# Exponentiation has a higher precedence
2**3 + 1 == 16

# In this code, what's in parentheses is evaluated first, and then the exponential number 2 raised to the fourth power is evaluated. Lastly, this result
# is tested to see if it's equal to 16 using ==. Since 16 is equal to 16, True displays.
# Adding () changes the precedence of 3 + 1 and the exponentiation operator
2 ** (3 + 1) == 16

# In this code, what's in parentheses is evaluated first, and then the exponential number 2 raised to the fourth power is evaluated. This result
# is tested to see if it's equal to 16 using ==. Then, what's after the "and" operator is performed. The multiplication is done first and then the
# comparison. Since both statements on each side of the 'and' operator are true, True displays.
# Arithmetic, relational, and Boolean operators
2 ** (3 + 1) == 16 and 3 * 2 < 10

# In this code, what's in parentheses is evaluated first, and then the exponential number 2 raised to the fourth power is evaluated. This result
# is tested to see if it's not equal to 16 using !=. Then, what's after the "or" operator is performed. The multiplication is done first and then the
# result is tested to see if it's in the list created. Since one statement of the 'or' operator is true, True displays.
# Arithmetic, relational, Boolean, and containment operators
2 ** (3 + 1) != 16 or 3 * 2 in [5, 6, 3]

# In this code, the' 10 != True' is done first because it has a higher precedence. So True will display no matter what.
# Unexpected outcome!
6 < 10 != True

# In this code, the' 10 != False' is done first. So False will display no matter what.
# Unexpected outcome!
6 < 10 != False

# In this code, the comparison is done first because it's now in parentheses, which have a higher precedence. Then, the test to see if the comparison is not
# equal True will execute. Since True is equal to True, false displays.
# Expected outcome after adding ()
(6 < 10) != True

# The error in this code was that the espression before the == True was not in parentheses. The 9 was being compared to True, so False displayed.
# To fix this, I added parentehses to 6 + 2 < 9.
# [ ] Correct the following expression so the answer is `True`
(6 + 2 < 9) == True

# The error in this code was that the espressions before and after the >= didn't contain any parentheses. The 3 was being raised to the second and then added 1.
# The 3 was multiplied by 8 and then added 1. At the end these 2 were compared and since they were not equal, False displayed. Ti fix this, I placed
# parentheses on 2 + 1 and 8 + 1, so that 3 raised to the thrid is 27 and 9 times 3 is 27 as well. This displays True because they are greater or equal to
# each other. To fix this, I added parentehses to 6 + 2 < 9.
# [ ] Correct the following expression so the answer is `True`
3 ** (2 + 1) >= 3 * (8 + 1)

# The error in this code was that the expression before the == 16 didn't contain any parentheses. The 3 was being multiplied with 2 and then added 5, which
# equals 11 and not 16. To fix this, I added parentehses to 5+3, so that the sum was done first and then the multiplication.
# [ ] Correct the following expression so the answer is `True`
(5 + 3) * 2 == 16

# The error in this code was that the espression before the == True was not in parentheses. The 7 was being compared to True, so False displayed.
# To fix this, I added parentehses to '4 > 3 and 5 + 6 > 7'.
# [ ] Correct the following expression so the answer is `True`
(4 > 3 and 5 + 6 > 7) == True