# sintetitza: solució recursiva lineal

def sintetitza_1(acumula, seq, neutre):
    if len(seq) == 0:
        r = neutre
    else:
        r_0 = sintetitza_1(acumula, seq[:-1], neutre)
        r = acumula(r_0, seq[-1])
    return r

# sintetitza: solució amb immersió d'eficiència

def sintetitza_2(acumula, seq, neutre):
    return sintetitza_2_i(acumula, seq, neutre, range(len(seq)))

def sintetitza_2_i(acumula, seq, neutre, llesca):
    if len(llesca) == 0:
        r = neutre
    else:
        r_0 = sintetitza_2_i(acumula, seq, neutre, llesca[:-1])
        r = acumula(r_0, seq[llesca[-1]])
    return r

# sintetitza: tria

sintetitza = sintetitza_2


# aplica: solució recursiva lineal

def aplica_1(funcio, seq):
    if len(seq) == 0:
        r = []
    else:
        r = aplica_1(funcio, seq[1:])
        r.insert(0, funcio(seq[0]))
    return r

# aplica: solució amb immersió d'eficiència

def aplica_2(funcio, seq):
    return aplica_2_i(funcio, seq, range(len(seq)))

def aplica_2_i(funcio, seq, llesca):
    if len(llesca) == 0:
        r = []
    else:
        r = aplica_2_i(funcio, seq, llesca[1:])
        r.insert(0, funcio(seq[llesca[0]]))
    return r

# aplica: tria

aplica = aplica_2


# filtra: solució recursiva lineal

def filtra_1(condicio, seq):
    if len(seq) == 0:
        r = []
    else:
        r = filtra_1(condicio, seq[1:])
        if condicio(seq[0]):
            r.insert(0, seq[0])
    return r

# filtra: solució amb immersió d'eficiència

def filtra_2(condicio, seq):
    return filtra_2_i(condicio, seq, range(len(seq)))

def filtra_2_i(condicio, seq, llesca):
    if len(llesca) == 0:
        r = []
    else:
        r = filtra_2_i(condicio, seq, llesca[1:])
        if condicio(seq[llesca[0]]):
            r.insert(0, seq[llesca[0]])
    return r

# filtra: tria

filtra = filtra_2
