import matplotlib.pyplot as plt
import numpy as np
import random
import math

# =============================================
# Exercice 1 : Polygones réguliers (racines de l'unité)
# =============================================

def racines_unite(n):
    """Renvoie les coordonnées des racines n-ièmes de l'unité"""
    x = []
    y = []
    for k in range(n):
        theta = k * 2 * math.pi / n
        x.append(math.cos(theta))
        y.append(math.sin(theta))
    return x, y


print("1. Polygone à 10 côtés :")
x10, y10 = racines_unite(10)
plt.plot(x10, y10, 'b-o', label="10 côtés")
plt.axis("equal")
plt.grid()
plt.title("Polygone régulier à 10 côtés")
plt.show()


# 2. Plusieurs polygones sur le même graphique
plt.figure(figsize=(8,8))
for p in range(2, 11):
    n = 2 * p
    x, y = racines_unite(n)
    plt.plot(x, y, label="p = " + str(p))

plt.axis("equal")
plt.grid()
plt.legend(loc="upper right")
plt.title("Polygones réguliers")
plt.show()


# 4. Exemple avec n=24 et m=7 (étoile)
n = 24
m = 7
x = []
y = []
for k in range(n+1):                     # +1 pour fermer la courbe
    theta = k * 2 * m * math.pi / n
    x.append(math.cos(theta))
    y.append(math.sin(theta))

plt.plot(x, y, 'r-', linewidth=2)
plt.title("Un joli dessin")
plt.axis("equal")
plt.grid()
plt.show()


# =============================================
# Module Numpy - Manipulations de base
# =============================================

print("\n=== Tests Numpy ===")

LA = [0, 2, 4]
LB = [1, 1, 5]
TA = np.array([0, 2, 4])
TB = np.array([1, 1, 5])

print("Liste + Liste :", LA + LB)
print("Tableau + Tableau :", TA + TB)
print("5 * Liste :", 5 * LA)
print("5 * Tableau :", 5 * TA)


# =============================================
# Exercice : Fonctions vectorielles
# =============================================

L = np.linspace(0, 10, 11)
print("\nlinspace(0,10,11) :", L)
print("sin(L) avec numpy :", np.sin(L))


# =============================================
# Exercice : Tracer f(x) = x² - 1
# =============================================

def f(x):
    return x**2 - 1

L = np.linspace(0, 6, 200)      # beaucoup de points pour une belle courbe
plt.plot(L, f(L), 'b-', label="f(x) = x² - 1")
plt.grid()
plt.legend()
plt.title("Tracé d'une fonction avec numpy")
plt.show()


# =============================================
# Exercice : Cercle + fonction f(x) = x √(1-x²)
# =============================================

# 1. Cercle trigonométrique
theta = np.linspace(0, 2*np.pi, 200)
x_cercle = np.cos(theta)
y_cercle = np.sin(theta)

plt.plot(x_cercle, y_cercle, 'b-', label="Cercle trigonométrique")
plt.axis("equal")
plt.grid()
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.legend()
plt.title("Cercle trigonométrique")
plt.show()


# 2. Cercle + courbe f(x)
def f(x):
    return x * np.sqrt(1 - x**2)

x = np.linspace(-1, 1, 200)
plt.plot(x_cercle, y_cercle, 'b-', label="Cercle")
plt.plot(x, f(x), 'r-', label="f(x) = x √(1-x²)")
plt.axis([-1.2, 1.2, -1.2, 1.2])
plt.grid()
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.legend()
plt.title("Cercle et courbe f(x)")
plt.show()


# 3. Version épaisse noire sans fioritures
plt.plot(x_cercle, y_cercle, 'k-', linewidth=16)
plt.plot(x, f(x), 'k-', linewidth=16)
plt.axis("equal")
plt.axis("off")          # supprime les axes
plt.show()


# =============================================
# Cardioïde
# =============================================

t = np.linspace(0, 2*np.pi, 300)
x = np.sin(t) * (1 - np.cos(t))
y = np.cos(t) * (1 - np.sin(t))

plt.plot(x, y, 'r-', linewidth=2)
plt.axis("equal")
plt.title("Cardioïde")
plt.grid()
plt.show()


# =============================================
# Approximations de sin(x) par polynômes de Taylor
# =============================================

x = np.linspace(-3, 3, 300)

f0 = np.sin(x)
f1 = x
f2 = x - (x**3)/6
f3 = x - (x**3)/6 + (x**5)/120

plt.plot(x, f0, 'b-', label="sin(x)")
plt.plot(x, f1, 'r--', label="x")
plt.plot(x, f2, 'g-.', label="x - x³/6")
plt.plot(x, f3, 'k:', label="x - x³/6 + x⁵/120")
plt.grid()
plt.legend()
plt.title("Approximations de Taylor de sin(x)")
plt.show()


# =============================================
# Jeu de pile ou face - Gains cumulés
# =============================================

def gains_pile_ou_face(g, p, n):
    """Renvoie la liste des gains cumulés"""
    gain = 0
    evolution = [0]          # on commence à 0
    
    for i in range(n):
        if random.randint(0,1) == 1:   # pile = gain
            gain += g
        else:
            gain -= p
        evolution.append(gain)
    return evolution


# Tracé pour différentes configurations
plt.figure(figsize=(10,6))

for i in range(4):
    evolution = gains_pile_ou_face(g=5, p=3, n=100)
    plt.plot(evolution, label=f"Partie {i+1}")

plt.grid()
plt.xlabel("Nombre de parties")
plt.ylabel("Gain cumulé (€)")
plt.title("Évolution des gains au pile ou face")
plt.legend()
plt.show()
