import numpy as np
#EXERCICE 1
#1
def multiple(n):
    lst=[]
    i=1
    while i*7 <= n:
        lst.append(i*7)
        i+=1
    return(lst)

#2
def isprime(n):
    s=int(n**.5)
    t=True
    i=2
    while i <= s and t==True:
        if n%i == 0:
            t=False
        i+=1
    return(t)

#Cette fonction vérifie qu'aucun des entiers compris entre 2 et sqrt(n) ne sont pas des diviseurs de n.
#Si aucun de ces entiers n'est un diviseur de n, alors n est premier car sqrt(n) est un majorant de l'ensemble des diviseurs de n

#3
def premiers(n):
    lst=[2]
    i=3
    while i <= n:
        if isprime(i):
            lst.append(i)
        i+=2
    return lst

#4
def npremiers(n):
    lst=[2]
    c=1
    i=3
    while c<n:
        if isprime(i):
            lst.append(i)
            c+=1
        i+=2
    return lst

#5
def jumeaux(n):
    lst=[]
    for i in range(2,n):
        if isprime(i) and isprime(i+2):
            lst.append((i, i+2))
    return lst

#6
def fermat():
    k=0
    while True:
        if not isprime(2**(2**k) + 1):
            return k
        k+=1

#7

def repartition(n):
    return len(premiers(n)) * np.log(n)/n

#On peut en conclure que sur les nombres qu'on a pu tester, la conjecture semble vraie.

#Exercice 2
#1
def u(n):
    if n==0:
        return 1
    pre=u(n-1)
    return 1/2*(pre + 2/pre)

premiers = lambda n: [u(n) for n in range(n)]
#2
premiers2 = lambda n: [u(n)**2 - 2 for n in range(n)]
# On pourrait. (ici, u(n)**2 tend vers 2, donc u(n) tend  vers sqrt(2))

#3
def approx():
    un=1
    i=0
    while abs(un**2 - 2) >= 2*1e-5:
        un = 1/2*(un + 2/un)
        i+=1
    return i
#4
#Uq doit converger vers sqrt(q), donc on pose q=l², on inverse et on utilise le fait que (l/q) + (q-1)*l = l pour retrouver une récurrence de la même forme que la première.
def uq(n, q):
    if n==0:
        return 1
    pre=uq(n-1, q)
    return (1/q)*((q-1)*pre + q/pre)


#Exercice 3
#1, a)
def fact(n):
    res=1
    for i in range(2,n+1):
        res *= i
    return res
#1, b)
def binome(n, p):
    return fact(n)/(fact(p)*(fact(n-p)))

#2
def binomes(n):
    lastl=[1, 0]
    for i in range(n+1):
        l = [1]
        for j in range(i):
            l.append(lastl.pop(0) + lastl[0])
        lastl=l+ [0]
    return(l)

#Exercice bonus : Conjecture de Syracuse
def syracuse(n):
    if n%2:
        return 3*n + 1
    return n>>1


def NbrEtapes(n, quiet=True):
    l=n
    i=0
    while l!=1:
        if not quiet:
            print(l)
        l=syracuse(l)
        i+=1
    return i
def printNbrEtapes(n):
    a=[NbrEtapes(i) for i in range(1, n+1)]
    print(a)
    return a

def test(n):
    for i in range(n):
        print(NbrEtapes(3**i), NbrEtapes(3**i + 1))

#Exercice bonus : Palindromes et nombres de Lychrel

def palindrome(l):
    return l == l[::-1]

def ldec(n):
    return list(map(int, str(n)))

def NbrPal(N):
    #Methode ~bourrin~:
    return sum([palindrome(ldec(i)) for i in range(N)])

def f(n):
    return n + int(str(n)[::-1])

def hauteur(n):
    N = n
    c = 0
    while not palindrome(ldec(N)):
        N = f(N)
        c += 1
        if c>4999 and c%5000==0 and not input("continuer ? (oui/non) >").lower().startswith('o'):
            break
    print(N)
    return c

