# here is a list holding all even numbers between 10 and 20
L = [10, 12, 14, 16, 18, 20]

# let's print the list
print(L)

# let's print each element by using its index but in reverse order
print(L[5],L[4],L[3],L[2],L[1],L[0])

# let's print the length (size) of list
print(len(L))

# let's print each element and its index in the list
# we use a for-loop, and the number of iteration is determined by the length of the list
# everthing is automatical :-)

L = [10, 12, 14, 16, 18, 20]

for i in range(len(L)):
    print(L[i],"is the element in our list with the index",i)

# let's replace each number in the above list with its double value
# L = [10, 12, 14, 16, 18, 20]

# let's print the list before doubling operation
print("the list before doubling operation is",L)

for i in range(len(L)):
    current_element=L[i] # get the value of the i-th element
    L[i] = 2 * current_element # update the value of the i-th element
    # let's shorten the code as
    #L[i] = 2 * L[i]
    # or
    #L[i] *= 2
    
# let's print the list after doubling operation
print("the list after doubling operation is",L)

# after each execution of this cell, the latest values will be doubled
#     so the values in the list will be exponentially increased 

# let's define two lists
L1 = [1,2,3,4]
L2 = [-5,-6,-7,-8]

# two lists can be concatenated 
# the result is a new list

print("the concatenation of L1 and L2 is",L1+L2)

# the order of terms is important
print("the concatenation of L2 and L1 is",L2+L1) # this is a different list than L1+L2

# we can add a new element to a list, which increases its length/size by 1

L = [10, 12, 14, 16, 18, 20]

print(L,"the current length is",len(L))

# we add two values by showing two different methods

# L.append(value) directly adds the value as a new element to the list

L.append(-4)

# we can also use concatenation operator +

L = L + [-8] # here [-8] is a list having a single element

print(L,"the new length is",len(L))

# a list can be multiplied with an integer
L = [1,2]

# we can consider the multiplication of L by an integer as a repeated summation (concatenation) of L by itself
# L * 1 is the list itself
# L * 2 is L + L (the concatenation of L with itself)
# L * 3 is L + L + L (the concatenation of L with itself twice)
# L * m is L + ... + L (the concatenation of L with itself m-1 times)
# L * 0 is the empty list

# L * i is the same as i * L

# let's print the different cases
for i in range(6):
    print(i,"* L is",i*L)

# this operation can be useful when initializing a list with the same value(s)

# let's create a list of prime numbers less than 100

# here is a function that determines whether a given number is prime or not
def prime(number):
    if number < 2: return False
    if number == 2: return True 
    if number % 2 == 0: return False
    for i in range(3,number,2):
        if number % i == 0: return False 
    return True
# end of a function

# let's start with an empty list
L=[] 
# what can the length of this list be?
print("my initial length is",len(L))

for i in range(2,100): 
    if prime(i):
        L.append(i)
        # alternative methods:
        #L = L + [i]
        #L += [i]

# print the final list
print(L)
print("my final length is",len(L))

# let's define the list with S(0) 
L = [0]

# let's iteratively define n and S

# initial values
n = 0
S = 0

# the number of iterations
N = 20 

while n <= N: # we iterate all values from 1 to 20
    n = n + 1
    S = S + n
    L.append(S)
    
# print the final list
print(L)

#
# your solution is here
# the first and second elements are 1 and 1
F = [1,1]

for i in range(2,30):
    F.append(F[i-1] + F[i-2])

# print the final list
print(F)

# the following list stores certain information about Asja
#   name, surname, age, profession, height, weight, partner(s) if any, kid(s) if any, the creation date of list
ASJA = ['Asja','Sarkane',34,'musician',180,65.5,[],['Eleni','Fyodor'],"October 24, 2018"]

print(ASJA)

# Remark that an element of a list can be another list as well.

#
# your solution is here
#
# define an empty list
N = []

for i in range(11):
    N.append([ i , i*i , i*i*i , i*i + i*i*i ]) # a list having four elements is added to the list N
    # Alternatively:
    #N.append([i , i**2 , i**3 , i**2 + i**3]) # ** is the exponent operator
    #N = N + [ [i , i*i , i*i*i , i*i + i*i*i] ] # Why using double brackets?
    #N = N + [ [i , i**2 , i**3 , i**2 + i**3] ] # Why using double brackets?
    # In the last two alternative solutions, you may try with a single bracket, 
    #     and then see why double brackets are needed for the exact answer.

# print the final list
print(N)

# let's print the list N element by element
for i in range(len(N)):
    print(N[i])

# let's print the list N element by element by using an alternative method
for el in N: # el will iteratively takes the values of elements in N 
    print(el)

# let's define a dictionary pairing a person with her/his age

ages = {
    'Asja':32,
    'Balvis':28,
    'Fyodor':43
}

# let print all keys
for person in ages:
    print(person)
    
# let's print the values
for person in ages:
    print(ages[person])

