# flake8: noqa

from __future__ import annotations


# %%

# Écrire une fonction qui pour un entier entre 1 et 3999 retourne sa
# représentation sous forme de nombre romain.
# Rappel: I (1), V (5), X (10), L (50), C (100), D (500), M (1000)


def romain(n: int) -> str:
    assert 1 <= n <= 3999
    cumul = ""

    while n >= 1000:
        cumul += "M"
        n -= 1000

    if n >= 900:
        cumul += "CM"
        n -= 900

    if n >= 500:
        cumul += "D"
        n -= 500

    if n >= 400:
        cumul += "CD"
        n -= 400

    while n >= 100:
        cumul += "C"
        n -= 100

    if n >= 90:
        cumul += "XC"
        n -= 90

    if n >= 50:
        cumul += "L"
        n -= 50

    if n >= 40:
        cumul += "XL"
        n -= 40

    while n >= 10:
        cumul += "X"
        n -= 10

    if n >= 9:
        cumul += "IX"
        n -= 9

    if n >= 5:
        cumul += "V"
        n -= 5

    if n >= 4:
        cumul += "IV"
        n -= 4

    while n >= 1:
        cumul += "I"
        n -= 1

    return cumul


print(romain(476))  # CDLXXVI
print(romain(778))  # DCCLXXVIII
print(romain(1229))  # MCCXXIX
print(romain(1453))  # MCDLIII
print(romain(1492))  # MCDXCII
print(romain(1515))  # MDXV
print(romain(1789))  # MDCCLXXXIX
print(romain(1945))  # MCMXLV
print(romain(1989))  # MCMLXXXIX
print(romain(2019))  # MMXIX

# %%

# Le *mélange de Monge* d'un paquet de cartes numérotées de 2 à 2n consiste à
# démarrer un nouveau paquet avec la carte 1, à placer la carte 2 au-dessus de
# cenouveau paquet, puis la carte 3 au-dessous du nouveau paquet et ainsi de
# suite en plaçant les cartes paires au dessus du nouveau paquet et les cartes
# impaires au dessous.
# Écrire une fonction qui retourne le paquet initial et le paquet mélangé.
# https://docs.python.org/3/tutorial/datastructures.html?highlight=list


def monge(n: int):
    initial = list(range(1, 2 * n + 1))
    monge = [1]
    for i in range(2, 2 * n + 1):
        if i % 2 == 0:  # pair
            monge.insert(0, i)
        else:
            monge.append(i)

    return initial, monge


print(monge(5))
# ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 8, 6, 4, 2, 1, 3, 5, 7, 9])

# %%

# Soit une liste contenant des tuples de valeurs (nom, masse, volume), où nom
# est le nom d'un élément chimique, masse est une valeur flottante en grammes et
# volume une valeur flottante en cm3


lst: list[tuple[str, float, float]] = [
    ("Arsenic", 17.8464, 3.12),
    ("Aluminium", 16.767, 6.21),
    ("Or", 239320, 12400),
]

# Enregistrer les données de lst dans un fichier texte dont chaque ligne
# correspond à un élément, avec le format: nom = masse volumique g/cm3
# Par exemple:
# Arsenic = 5.72 g/cm3

from pathlib import Path

with Path("elements.txt").open("w") as fh:
    for nom, masse, volume in lst:
        mvol = masse / volume
        fh.write("{} = {:.2f} g/cm3\n".format(nom, mvol))


def calcule_masse(volume: float) -> None:
    with Path("elements.txt").open("r") as fh:
        for line in fh:
            items = line.split("=")
            nom = items[0].strip()
            mvol = float(items[1].split()[0])
            print("{}: {:.2f} g".format(nom, mvol * volume))


calcule_masse(5)

# %%

# Écrire un programme qui approche la valeur de la constante mathématique e pour
# n assez grand en utilisant la formule $e = \sum_{i=0}^{n} \frac{1}{i!}$


def calcule_e(n: int) -> float:
    e = 1.0
    fact = 1
    for i in range(1, n + 1):
        fact *= i
        e += 1 / fact
    return e


import math

(math.e - calcule_e(15)) / math.e

# Écrire un programme qui approche la valeur de la constante mathématique $\pi$
# pour n assez grand en utilisant la formule d'Euler $\pi = 1 + \frac{1}{3} +
# \frac{1 · 2}{1 · 3} + \frac{1 · 2 · 3}{1 · 3 · 5}  + \cdots$


def calcule_pi(n: int) -> float:
    pi2 = 1.0
    num = 1
    denum = 1
    for i in range(1, n + 1):
        num *= i
        denum *= 2 * i + 1
        pi2 += num / denum
    return 2 * pi2


(math.pi - calcule_pi(30)) / math.pi

# flake8: noqa

from __future__ import annotations


# %%

# Écrire une fonction qui pour un entier entre 1 et 3999 retourne sa
# représentation sous forme de nombre romain.
# Rappel: I (1), V (5), X (10), L (50), C (100), D (500), M (1000)


def romain(n: int) -> str:
    assert 1 <= n <= 3999
    cumul = ""

    while n >= 1000:
        cumul += "M"
        n -= 1000

    if n >= 900:
        cumul += "CM"
        n -= 900

    if n >= 500:
        cumul += "D"
        n -= 500

    if n >= 400:
        cumul += "CD"
        n -= 400

    while n >= 100:
        cumul += "C"
        n -= 100

    if n >= 90:
        cumul += "XC"
        n -= 90

    if n >= 50:
        cumul += "L"
        n -= 50

    if n >= 40:
        cumul += "XL"
        n -= 40

    while n >= 10:
        cumul += "X"
        n -= 10

    if n >= 9:
        cumul += "IX"
        n -= 9

    if n >= 5:
        cumul += "V"
        n -= 5

    if n >= 4:
        cumul += "IV"
        n -= 4

    while n >= 1:
        cumul += "I"
        n -= 1

    return cumul


print(romain(476))  # CDLXXVI
print(romain(778))  # DCCLXXVIII
print(romain(1229))  # MCCXXIX
print(romain(1453))  # MCDLIII
print(romain(1492))  # MCDXCII
print(romain(1515))  # MDXV
print(romain(1789))  # MDCCLXXXIX
print(romain(1945))  # MCMXLV
print(romain(1989))  # MCMLXXXIX
print(romain(2019))  # MMXIX

# %%

# Le *mélange de Monge* d'un paquet de cartes numérotées de 2 à 2n consiste à
# démarrer un nouveau paquet avec la carte 1, à placer la carte 2 au-dessus de
# cenouveau paquet, puis la carte 3 au-dessous du nouveau paquet et ainsi de
# suite en plaçant les cartes paires au dessus du nouveau paquet et les cartes
# impaires au dessous.
# Écrire une fonction qui retourne le paquet initial et le paquet mélangé.
# https://docs.python.org/3/tutorial/datastructures.html?highlight=list


def monge(n: int):
    initial = list(range(1, 2 * n + 1))
    monge = [1]
    for i in range(2, 2 * n + 1):
        if i % 2 == 0:  # pair
            monge.insert(0, i)
        else:
            monge.append(i)

    return initial, monge


print(monge(5))
# ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 8, 6, 4, 2, 1, 3, 5, 7, 9])

# %%

# Soit une liste contenant des tuples de valeurs (nom, masse, volume), où nom
# est le nom d'un élément chimique, masse est une valeur flottante en grammes et
# volume une valeur flottante en cm3


lst: list[tuple[str, float, float]] = [
    ("Arsenic", 17.8464, 3.12),
    ("Aluminium", 16.767, 6.21),
    ("Or", 239320, 12400),
]

# Enregistrer les données de lst dans un fichier texte dont chaque ligne
# correspond à un élément, avec le format: nom = masse volumique g/cm3
# Par exemple:
# Arsenic = 5.72 g/cm3

from pathlib import Path

with Path("elements.txt").open("w") as fh:
    for nom, masse, volume in lst:
        mvol = masse / volume
        fh.write("{} = {:.2f} g/cm3\n".format(nom, mvol))


def calcule_masse(volume: float) -> None:
    with Path("elements.txt").open("r") as fh:
        for line in fh:
            items = line.split("=")
            nom = items[0].strip()
            mvol = float(items[1].split()[0])
            print("{}: {:.2f} g".format(nom, mvol * volume))


calcule_masse(5)

# %%

# Écrire un programme qui approche la valeur de la constante mathématique e pour
# n assez grand en utilisant la formule $e = \sum_{i=0}^{n} \frac{1}{i!}$


def calcule_e(n: int) -> float:
    e = 1.0
    fact = 1
    for i in range(1, n + 1):
        fact *= i
        e += 1 / fact
    return e


import math

(math.e - calcule_e(15)) / math.e

# Écrire un programme qui approche la valeur de la constante mathématique $\pi$
# pour n assez grand en utilisant la formule d'Euler $\pi = 1 + \frac{1}{3} +
# \frac{1 · 2}{1 · 3} + \frac{1 · 2 · 3}{1 · 3 · 5}  + \cdots$


def calcule_pi(n: int) -> float:
    pi2 = 1.0
    num = 1
    denum = 1
    for i in range(1, n + 1):
        num *= i
        denum *= 2 * i + 1
        pi2 += num / denum
    return 2 * pi2


(math.pi - calcule_pi(30)) / math.pi

# flake8: noqa # %% # Écrire une fonction qui pour un entier entre 1 et 3999 retourne sa # représentation sous forme de nombre romain. # Rappel: I (1), V (5), X (10), L (50), C (100), D (500), M (1000) # CDLXXVI # DCCLXXVIII # MCCXXIX # MCDLIII # MCDXCII # MDXV # MDCCLXXXIX # MCMXLV # MCMLXXXIX # MMXIX # %% # Le *mélange de Monge* d'un paquet de cartes numérotées de 2 à 2n consiste à # démarrer un nouveau paquet avec la carte 1, à placer la carte 2 au-dessus de # cenouveau paquet, puis la carte 3 au-dessous du nouveau paquet et ainsi de # suite en plaçant les cartes paires au dessus du nouveau paquet et les cartes # impaires au dessous. # Écrire une fonction qui retourne le paquet initial et le paquet mélangé. # https://docs.python.org/3/tutorial/datastructures.html?highlight=list # pair # ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 8, 6, 4, 2, 1, 3, 5, 7, 9]) # %% # Soit une liste contenant des tuples de valeurs (nom, masse, volume), où nom # est le nom d'un élément chimique, masse est une valeur flottante en grammes et # volume une valeur flottante en cm3 # Enregistrer les données de lst dans un fichier texte dont chaque ligne # correspond à un élément, avec le format: nom = masse volumique g/cm3 # Par exemple: # Arsenic = 5.72 g/cm3 # %% # Écrire un programme qui approche la valeur de la constante mathématique e pour # n assez grand en utilisant la formule $e = \sum_{i=0}^{n} \frac{1}{i!}$ # Écrire un programme qui approche la valeur de la constante mathématique $\pi$ # pour n assez grand en utilisant la formule d'Euler $\pi = 1 + \frac{1}{3} + # \frac{1 · 2}{1 · 3} + \frac{1 · 2 · 3}{1 · 3 · 5}  + \cdots$