# |------------------------------------------------------------------|
# |                                                                  |
# | BCPST2, 2022-2023                                                |
# | Séances de TD d'informatique (P. Roux)                           |
# |                                                                  |
# |------------------------------------------------------------------|

import time as tm
from math import pi

## TD 1 : Itérations simples

## Question I

##  (I.1)

def Fact(N):
    r = 1
    for k in range(2, N+1):
        r = r * k
    return r

print(Fact(6))
print(Fact(11))

def Fact_recursif(N):
    # Ici une définition récursive est logique mais elle
    # n'est surtout pas à recommander: plus lente, elle
    # sature si N est assez grand
    if N <= 1:
        return 1
    else:
        return N*Fact_recursif(N-1)
    return r

print(Fact_recursif(6))
print(Fact_recursif(11))

## Chronométrage

t0 = tm.time()
X = Fact(800)
t1 = tm.time()
X = Fact_recursif(800)
t2 = tm.time()
print(t1-t0,'s de temps de calcul itératif,')
print(t2-t1,'s de temps de calcul récursif...')

## Blocage

print(Fact_recursif(1000))

## (I.2)

def SumPow(N, p):
    r = 0
    for k in range(1, N+1):
        r = r + k**p
    return r

print(SumPow(7,0))
print(SumPow(7,2))

def SumPow(N, p):
    # ça n'est pas ce qui est attendu!
    # n'utilisez JAMAIS la fonction sum sauf si
    # l'énoncé l'autorise explicitement.
    return sum([(k+1)**p for k in range(N)])

print(SumPow(7,0))
print(SumPow(7,2))

## (I.3)

def Fib(N):
    F0 = 0
    F1 = 1
    for k in range(N):
        F0, F1 = F1, F1 + F0
    return F0

print(Fib(40))

## (I.4)

def A(n):
    k = n
    s = 0
    while s < 1:
        s += 1/k
        k = k + 1
    return k - 1

for n in range(1,11):
    print(n,A(n))

## Question II

L = [7, 3, 9, 2, 4, 3, 1, 0, 9]

def Pos(x,L):
    k = 0
    n = len(L)
    while k < n:
        if L[k] == x:
            return k
        k = k + 1

print(Pos(3,L))
print(Pos(4,L))
print(Pos(5,L))

def Pos(x,L):
    # ça n'est pas ce qui est attendu!
    # n'utilisez JAMAIS la méthode index sauf
    # si l'énoncé l'autorise explicitement.
    if x in L:
        return L.index(x)

print(Pos(3,L))
print(Pos(4,L))
print(Pos(5,L))

##

def PosMax(L):
    k = 0
    n = len(L)
    r = 0
    for k in range(1,n):
        if L[k] > L[r]:
            r = k
    return r

print(PosMax(L))

def Pos(x,L):
    # ça n'est pas non plus ce qui est attendu!
    return L.index(max(L))

print(PosMax(L))

## Question III

## (III.1)

def ListeDiv(n):
    r = []
    for k in range(1, n+1):
        if 0 == n%k:
            r.append(k)
    return r

print(ListeDiv(720))
print(ListeDiv(97))

def ListeDiv(n):
    return [ k for k in range(1,n+1) if 0 == n%k ]

print(ListeDiv(720))
print(ListeDiv(97))

## (III.2)

def ListePremiers(n):
    r = []
    for k in range(2, n+1):
        if 2 == len(ListeDiv(k)):
            r.append(k)
    return r

print(ListePremiers(100))

def ListePremiers(n):
    return [ k for k in range(2,n+1) if 2 == len(ListeDiv(k)) ]

print(ListePremiers(100))

