# ---------------------- List comprehension -------------------------------

#_________________________________________
print [i for i in range(10)]
# >>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print [i for i in range(20) if i%2 == 0]
# >>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

nums = [1,2,3,4]
fruit = ["Apples", "Peaches", "Pears", "Bananas"]

print [(i,f) for i in nums for f in fruit]
# >>>[(1, 'Apples'), (1, 'Peaches'), (1, 'Pears'), (1, 'Bananas'),
#     (2, 'Apples'), (2, 'Peaches'), (2, 'Pears'), (2, 'Bananas'),
#     (3, 'Apples'), (3, 'Peaches'), (3, 'Pears'), (3, 'Bananas'),
#     (4, 'Apples'), (4, 'Peaches'), (4, 'Pears'), (4, 'Bananas')]
 
print [(i,f) for i in nums for f in fruit if f[0] == "P"]
# >>>[(1, 'Peaches'), (1, 'Pears'),
#     (2, 'Peaches'), (2, 'Pears'),
#     (3, 'Peaches'), (3, 'Pears'),
#     (4, 'Peaches'), (4, 'Pears')]

print [(i,f) for i in nums for f in fruit if f[0] == "P" if i%2 == 1]
# >>>[(1, 'Peaches'), (1, 'Pears'), (3, 'Peaches'), (3, 'Pears')]
    
print [i for i in zip(nums,fruit) if i[0]%2==0]
# >>>[(2, 'Peaches'), (4, 'Bananas')]
#__________________________________________



#__________________________________________
## Versione imperativa
numbers = range(10)
size = len(numbers)
evens = []
i = 0
while i < size:
    if i % 2 == 0:
    evens.append(i)
    i += 1

# evens -> [0, 2, 4, 6, 8]


## List comprehension
[i for i in range(10) if i % 2 == 0]
#[0, 2, 4, 6, 8]
#_________________________________________


#_________________________________________
## Versione imperativa
i = 0
seq = ["uno", "due", "tre"]
for element in seq:
    seq[i] = '%d: %s' % (i, seq[i])
    i += 1
# seq -> ['0: uno', '1: due', '2: tre']

## enumerate
seq = ["uno", "due", "tre"]
for i, element in enumerate(seq):
    seq[i] ='%d: %s' % (i, element)
# seq -> ['0: uno', '1: due', '2: tre']

## List comprehension 
def _treatment(pos, element):
    return '%d: %s' % (pos, element)

seq = ["uno", "due", "tre"]
[_treatment(i, el) for i, el in enumerate(seq)]
#seq -> ['0: uno', '1: due', '2: tre']
#_________________________________________

#_________________________________________
print [i for i in range(10)]
# >>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print [i for i in range(20) if i%2 == 0]
# >>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

nums = [1,2,3,4]
fruit = ["Apples", "Peaches", "Pears", "Bananas"]

print [(i,f) for i in nums for f in fruit]
# >>>[(1, 'Apples'), (1, 'Peaches'), (1, 'Pears'), (1, 'Bananas'),
#     (2, 'Apples'), (2, 'Peaches'), (2, 'Pears'), (2, 'Bananas'),
#     (3, 'Apples'), (3, 'Peaches'), (3, 'Pears'), (3, 'Bananas'),
#     (4, 'Apples'), (4, 'Peaches'), (4, 'Pears'), (4, 'Bananas')]
 
print [(i,f) for i in nums for f in fruit if f[0] == "P"]
# >>>[(1, 'Peaches'), (1, 'Pears'),
#     (2, 'Peaches'), (2, 'Pears'),
#     (3, 'Peaches'), (3, 'Pears'),
#     (4, 'Peaches'), (4, 'Pears')]

print [(i,f) for i in nums for f in fruit if f[0] == "P" if i%2 == 1]
# >>>[(1, 'Peaches'), (1, 'Pears'), (3, 'Peaches'), (3, 'Pears')]
    
print [i for i in zip(nums,fruit) if i[0]%2==0]
# >>>[(2, 'Peaches'), (4, 'Bananas')]
#__________________________________________


#_________________________________________
## Versione imperativa
xs = (1,2,3,4)
ys = (10,15,3,22)
bigmuls = []
for x in xs:
    for y in ys:
        if x*y > 25:
            bigmuls.append((x,y))
print bigmuls

## Versione funzionale
bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, combine(xs,ys))
combine = lambda xs,ys: map(None, xs*len(ys), ripelms(ys,len(xs)))
ripelms = lambda lst,n: reduce(lambda s,t:s+t, map(lambda l,n=n: [l]*n, lst))               

# Versione funzionale piĆ¹ semplice
combine = lambda xs, ys: map(lambda i: map(lambda j: (i,j), ys), xs)
flat = lambda lol: reduce(lambda l1,l2: l1 + l2, lol)
bigmuls = lambda xs,ys: filter(lambda (x,y):x*y > 25, flat(combine(xs,ys)))


print bigmuls((1,2,3,4),(10,15,3,22))

## List comprehension
[(x,y) for x in xs for y in ys if x*y > 25]
#_________________________________________




#_________________________________________
# Definizione di una matrice identitą
def identity(n):
    map(lambda i: map(lambda j: i==j and 1 or 0, range(n)), range(n))
# per passi
# map (lambda j: (0,j), range(n))
# map(lambda i: map(lambda j: (i,j), range(n)), range(n))  

identity = lambda n: [[ i==j and 1 or 0 for j in range(n)] for i in range(n)]
flat_identity = lambda n: [ i==j and 1 or 0 for j in range(n) for i in range(n)]
#_________________________________________
