
# Create an empty list.
aList = []
print( aList )

# Create a list with small number of values.
aList = [4, 3, 2, 1, 451 ]
print( aList )

# -----------------------------------------------------------
# Create a list with generally more values,
# the list is filled in various systematic ways.LS_BE5B33PGE_1221873813405@fel.cvut.cz

# Create a list with 7 copies of value 11
aList = [11] * 7
print( aList )

# Create lists containing ranges of values.
aList1 = list( range(6) )
aList2 = list( range(2, 6) )
aList3 = list( range(4, 10) )
aList4 = list( range(-20, 100, 17) )
aList5 = list( range( 20, 9, -1 ) )
aList6 = list( range( 20, 0, -4 ) )

print( aList1 )
print( aList2 )
print( aList3 )
print( aList4 )
print( aList5 )
print( aList6 )

# -----------------------------------------------------------
# Hard copy of a list
aList1 = [6,5,4,3,2]
aList2 = aList1.copy()
print(aList1)
print(aList2)

# -----------------------------------------------------------
#   LIST COMPREHENSION

# List of 3rd powers
aList = [ n*n*n for n in range(0,11) ]
print( aList )

# List of 3rd powers, only divisible by 3
aList = [ n*n*n for n in range(0,11) if n % 3 == 0 ]
print( aList )

# List of values taken from another list, multiplied by 100,
# but only of those which are less then 10
aList1 = [18, 7, 16,  3, 12, 1  ]
aList2 = [ x*100 for x in aList1 if x < 10]
print(aList1)
print(aList2)

# -----------------------------------------------------------
# Various solutions of an example task:
#    Print the number of such elements in list L which values
#    are strictly between two given values xLow and xHigh

# Classical solution 1
def ff_classic( L, xLow, xHigh ):
    counter = 0
    for val in L:
        if xLow < val and val < xHigh:
            counter += 1
    print( counter )

# Classical solution 1
def ff_superClassic( L, xLow, xHigh ):
    counter = 0
    for i in range(0, len(L)):
        if xLow < L[i] and L[i] < xHigh < 10:
            counter += 1
    print( counter )

# List comprehension and indicator vector
# (sometimes indicator vector is also called a characteristic vector)
def ff1( L, xLow, xHigh ):
    # create an indicator vector of chosen values
    indicator = [ int( xLow < val and val < xHigh ) for val in L  ]
    print( indicator )
    print( sum(indicator) )
# Note that int(True) == 1, int(False) == 0.
# Indicator vector is sometimes a handy tool, typically
# more on conceptual level that on implementation level

# List comprehension and list of ones for each chosen value
def ff2( L, xLow, xHigh  ):
    # create a vector containg only 1s,
    # each 1 stands for one chosen value
    ones = [1  for val in L if xLow < val and val < xHigh ]
    print( ones )
    print( sum(ones) )

# List comprehension
def ff3( L, xLow, xHigh ):
    print( sum(1 for val in L if  xLow < val and val < xHigh ) )

L = [ 48, 10, 20, 51, 90, 80, 53, 70 ]
xLow = 45
xHigh = 60
print()
print( L )

ff_classic( L, xLow, xHigh )
ff_superClassic( L, xLow, xHigh )
ff1( L, xLow, xHigh )
ff2( L, xLow, xHigh )
ff3( L, xLow, xHigh )

