#########################################
######## TP informatique bio-sép ########
########        2025-2026        ########
#########################################


#########################################
######### Thème 7 : Polynômes ###########
#########################################

import numpy as np
N = 20 # valeur par défaut

## Q1 : adapter la longueur de la liste
## représentant un polynôme

def RN(L,d=N) :
    while len(L) < d+1 :
        L.append(0)
    return L

## Q2 : fonction donnant le degré

def deg(P) :
    d = len(P)
    while d > 0 :
        if P[d-1] != 0 :
            return d-1
        d -= 1
    return d-1

## Q3 : évaluation d'un polynôme en a

def eval(P,a) :
    s = 0
    for k in range(len(P)) :
        s += P[k]*a**k
    return s

## Q4 : multiplication scalaire

def dot(alpha,P) :
    Q = []
    for elt in P :
        Q.append(alpha*elt)
    return Q

## Q5 : somme de polynômes avec des listes de taille N

def somme1(P,Q) :
    P2 = RN(P)
    Q2 = RN(Q)
    S = []
    for k in range(N) :
        S.append(P2[k]+Q2[k])
    return S

## Q6 : somme de polynômes avec des listes de tailles adaptées

def somme2(P,Q) :
    d1 = deg(P)
    d2 = deg(Q)
    S = []
    M = max(d1,d2)
    for k in range(M+1) :
        if k > d1 :
            S.append(Q[k])
        elif k > d2 :
            S.append(P[k])
        else :
            S.append(P[k]+Q[k])
    return S

## Q7 : Produit de deux polynômes

def produit(P,Q) :
    P1 = RN(P)
    Q1 = RN(Q)
    d1 = deg(P1)
    d2 = deg(Q1)
    Prod = []
    for k in range(d1+d2+1) :
        ck = 0
        for j in range(k+1) :
            ck += P1[j]*Q1[k-j]
        Prod.append(ck)
    return Prod

## Q8 : Autre façon pour le produit

def shift(k,L) :
    return [0]*k + L

def produit2(P,Q) :
    d = deg(P)
    PQ = []
    for k in range(d+1) :
        PQ = somme2(PQ, dot(P[k],shift(k,Q)))
    return PQ

## Q9 : triangle de Pascal obtenu
## grâce aux puissances de (1+X)

def pascal(n) :
    T = []
    Lt = [1]
    for _ in range(n) :
        T.append(RN(Lt,n))
        Lt = produit(Lt.copy(),[1,1])
    return T

## Q11 : Méthode de Horner

def horner(P,a) :
    d = deg(P)
    S = P[d]
    for k in range(d-1,-1,-1) :
        S = a*S + P[k]
    return S

## Q12 : Factorisation d'un polynôme

def factorise(P,a) :
    z = eval(P,a)
    if abs(z) > 10**(-12) :
        return "a n'est pas racine de P"
    d = deg(P)
    u = P[d]
    Q = [u]
    for k in range(1,d) :
        u = a*u + P[d-k]
        Q = [u]+Q
    return Q

## Q13 : Un test

N = 20
P = [-69,6,7,9,1,6,2,2,7,5,6,2,1,2,4,9]
Q = factorise(P,1)
print("La factorisation de P par X-1 donne le polynôme :")
print(Q)

print("\n")
print("On vérifie en calculant Q*(X-1) - P :")
print(somme2(produit(Q,[-1,1]),dot(-1,P)))









