
from functools import reduce


# Boucle sans boucle

def foo(x):
  def foo_rec(i,v): 
    if not (i <= v): return i * v
    else:
      return foo_rec (i + x, v - x)
  return foo_rec(0, x * x)


def bar2(x, y): 
  def bcl1(i,r):
    return r if i==10 else bcl1 (i + 1,r + x) 
  def bcl2(j,r): 
    return r if j ==0 else bcl2 (j - 1,r - y)
  rp = bcl1(0,0)
  return bcl2(rp,rp)


# Ensembles comme fonctions

def car_S1(x):
    return x > 0

def car_S2(x):
    return x >= 0 and x % 2 == 0

def car_S3(x):
    return x == 0 or x == 3 or x == 7 or x == 9

def car_S4(x):
    return 10 < x and x < 1000

def cas_S5(x): return False
  
def union (f1, f2):
    return lambda x: f1(x) or f2(x)

def inter(f1, f2):
    return lambda x: f1(x) and f2(x)
                         
def ajout(x, f):
    return lambda y: y == x or f(y)

def ensemble(l):
  def lrec(i, s):
    if i == len(l): return s
    else:
        return ajout(l[i],lrec(i+1, s))
  return lrec (0, lambda x:False)

def ensemble(l):
  return reduce (lambda s, x: ajout(x,s), l, lambda x:False)


# Récursion sans récursion

fr = lambda f,x: 1 if x == 0 else x * f(f, x-1)
fact = lambda x: fr(fr,x)

                           
# Exo itérateurs
                           
def somme_des_carres(l) :
    return (reduce ((lambda acc,x : acc + x*x),l,0))

l = [3,5,10,6,2]

print(somme_des_carres(l))

def maximum(l) :
    return reduce(lambda x,y: max(x,y), l)

print(maximum(l))

def fst(l):
    return list(map(lambda c: c[0], l))

print(fst([(1,2), (3,4), (5,6)]))

def permute(l):
    return list(map(lambda x: 0 if x==1 else 1,l))

l2 = [1,1,0,1,0,0,1,0,0,0,1]
print(permute(l2))

def compte0(l):
    return reduce((lambda x,y: x+1 if y == 0 else x),l,0)

print(compte0(l2))

def pgs(v,l):
    f = lambda c,x: (c[0],c[1]+1) if x ==v else (max(c),0)
    return max(reduce(f,l,(0,0)))

print(pgs('a',['a','b','a','a','b','b','a','a','a','b']))
               
