# TP 05 correction : Listes
# BCPST1B 2026-2027
# Lycée Hoche, Versailles
# L.-C. LEFÈVRE

#%% exercice 1

repas = ["risotto aux truffes", "parmesan fraichement râpé", "fromage de chèvre fermier", "tiramisù aux fraises de saison"]
print(repas)

#%% exercice 2

suite = ["hareng mariné à la menthe et au citron vert", "riz", "salade de petit pois", "kouign amann breton pur beurre"]
print(repas + suite)

#%% exercice 4

repas.append("part de pizza")
# pour la tomate
repas.append("tarte au citron")
# c'est un fruit
print(repas)

#%% partie II

def double(L):
    for i in range(len(L)):
        print(2 * L[i])

L = [1, 3, 5]
double(L)

#%% exercice 4

def signe(L):
    for i in range(len(L)):
        if L[i] > 0:
            print("positif")
        elif L[i] < 0:
            print("négatif")
        else:
            print("nul")

# test
signe([4, 0, 7, -5])

#%% section III

def puissances2(n):
    L = [0] * n
    L[0] = 1
    for i in range(1, n):
        L[i] = 2 * L[i-1]
    return L

print(puissances2(5))

#%% exercice 5

def factoriel(n):
    L = [0] * n
    L[0] = 1
    for i in range(1, n):
        L[i] = i * L[i-1]
    return L

print(factoriel(10))

#%% exercice 6

def fibonacci(n):
    L = [0] * n
    L[0] = 0
    L[1] = 1
    # démarrage à 2 car L[0] et L[1] sont déjà remplis
    for i in range(2, n):
        # plus facile qu'avant ! pas de variables intermédiaires !
        L[i] = L[i-1] + L[i-2]
    return L

print(fibonacci(12))

#%% partie IV

def garde_positifs(L):
    P = []
    for i in range(len(L)):
        if L[i] >= 0:
            P.append(L[i])
    return P

P = garde_positifs([4, -8, -2, -5, 0, 1, 1, 6, 6, -2, 2, 1])
print(P)

#%% exercice 7.1

# version 1 : énumérer et afficher les solutions, sans se préoccuper des listes
def pell_fermat(N):
    for x in range(N+1):
        for y in range(N+1):
            if x**2 - 3*y**2 == 1:
                print(x, y)

pell_fermat(100)

#%% exercice 7.2

# version 2 : une fois que ça marche, on met les solutions trouvées dans une liste
def pell_fermat_liste(N):
    L = []
    for x in range(N+1):
        for y in range(N+1):
            if x**2 - 3*y**2 == 1:
                L.append((x, y))
                # deux parenthèses ! c'est la fonction append() appliquée au tuple (x, y)
    return L

L = pell_fermat_liste(100)
print(L)

#%% exercice 8

def acronyme(s):
    L = []
    for i in range(len(s)):
        if s[i].isupper():
            L.append(s[i])
    return L

# test
print(acronyme("Biologie, Chimie, Physique et Sciences de la Terre"))

#%% amélioration

def acronyme2(s):
    L = []
    for i in range(len(s)):
        if s[i].isupper():
            L.append(s[i])
    return "".join(L)

# test
print(acronyme2("Biologie, Chimie, Physique et Sciences de la Terre"))

#%% exercice 9

L = [1 + k/10 for k in range(0, 11)]
print(L)

#%% exercice 10

def rebours(n):
    return [n-i for i in range(n+1)]

print(rebours(10))

#%% exercice 11

s = "J'aime la biologie, la chimie et les mathématiques"
print(s[:7] + s[-17:])

#%% exercice 12

def garde_positifs_2(L):
    return [x for x in L if x >= 0]

# Python niveau expert
def pell_fermat_2(N):
    return [(x, y) for x in range(N+1) for y in range(N+1) if x**2 - 3*y**2 == 1]

def acronyme_2(s):
    return [x for x in s if x.isupper()]

# toujours plus expert
def acronyme_3(s):
    return "".join(x for x in s if x.isupper())

#%% exercice 13.1

def crible(n):
    # 3 lignes pour initialiser
    L = [True] * (n+1)
    L[0] = False
    L[1] = False
    # début du criblage
    for i in range(2, n+1):
        # Jusqu'ici le programme traduit exactement l'algorithme décrit :
        # si i est barré il suffit de continuer la boucle, sinon…
        if L[i] == True:
            # i n'est pas encore coché : c'est un nombre premier
            # Alors éliminer tous les multiples de i : j saute de i en i, en commençant au premier multiple de i suivant
            j = i + i
            while j < n+1: # pas plus loin que le bout de la liste
                L[j] = False
                j = j + i
    return L

# test (vérifiable à la main)
print(crible(20))

#%% exercice 13.2

# la fonction est de la même forme que garde_positifs (on garde les indices des True)
def liste_premiers(n):
    L = crible(n)
    P = []
    for i in range(len(L)):
         if L[i] == True:
             P.append(i)
    return P

print(liste_premiers(100))

#%% expert

def liste_premiers_2(n):
    L = crible(n)
    return [i for i in range(len(L)) if L[i] == True]
