import math
from functools import reduce

#Exercicio 4.1
impar = lambda num: num % 2 != 0

#Exercicio 4.2
positivo = lambda num: num >= 0

#Exercicio 4.3
comparar_modulo = lambda x, y: abs(x) < abs(y)

#Exercicio 4.4
cart2pol = lambda x, y: (math.sqrt(x**2 + y**2), math.atan2(y, x))

#Exercicio 4.5
ex5 = lambda f, g, h: (lambda x, y, z: h(f(x, y), g(y, z)))


#Exercicio 4.6

def quantificador_universal(lista, f):
    return all(map(f, lista))  #map() aplica uma função a cada elemento de um iterável

#Exercicio 4.8
def subconjunto(lista1, lista2):
    return all(map(lambda x: x in lista2, lista1))

#Exercicio 4.9
def menor_ordem(lista, f):
    return reduce(lambda x, y: x if f(x, y) else y, lista) #reduce percorre a lista dois elementos de cada vez

#Exercicio 4.10
def menor_e_resto_ordem(lista, f):
    menor = reduce(lambda x, y: x if f(x, y) else y, lista)
    restantes = lista.copy()
    restantes.remove(menor)
    return (menor, restantes)

#Exercicio 5.2
def ordenar_seleccao(lista, ordem):
    if len(lista) <= 1:
        return lista
    
    pivot = lista[0]
    menores = list(filter(lambda x: ordem(x, pivot), lista[1:]))
    maiores = list(filter(lambda x: not ordem(x, pivot), lista[1:]))
    
    return ordenar_seleccao(menores, ordem) + [pivot] + ordenar_seleccao(maiores, ordem)
