"""
Le conseil donné dans l'énoncé de l'exercice :
Dans cet exercice, il faudra veiller à optimiser le programme
diviseursStricts afin d'éviter de faire des calculs inutiles. 
"""

def diviseursStricts(n):
    """
    On construit deux listes de diviseurs delimitees par la
    racine carree de n.  Par la suite on nettoie les listes et
    on prend leur somme.
    """
    avant = []
    apres = []
    for d in range(1, int(n**.5) + 1):
        if n % d == 0:
            avant.append(d)
            apres = [n//d] + apres
    if avant[-1] == apres[0]:  # \sqrt{n} apparait dans les deux listes
        avant.pop(-1)
    return avant + apres[:-1]  # on enleve n


def nombresParfaits(n):
    """
    Renvoie la liste des nombres parfaits inférieurs ou égaux à $n$.
    """
    P = []
    for k in range(2, n + 1):
        s = sum(diviseursStricts(k))
        if k == s:
            P.append(k)
    return P


def nombresAmicaux(n):
    """
    Renvoie la liste des couples de nombres amicaux inférieurs à $n$.
    """
    L = []
    for a in range(2, n + 1):
        b = sum(diviseursStricts(a))
        if a < b:
            s = sum(diviseursStricts(b))
            if a == s:
                L.append([a, b])
    return L


n = 256
print(f"la liste des diviseurs stricts de {n} est {diviseursStricts(n)}")

n = 50000
print(f"\nla liste des nombres parfaits plus petits ou egaux a {n} est"
      + f"\n{nombresParfaits(n)}")


print(f"\nla liste des nombres amicaux plus petits ou egaux a {n} est"
      + f"\n{nombresAmicaux(n)}")
