Code:
from dataclasses import dataclass
from typing import Optional


# Exercise 3 (a)
def count_divisors_of(n: int) -> int:
    num_divisors = 1
    for m in range(2, n + 1):
        if n % m == 0:
            num_divisors += 1
    return num_divisors


# Exercise 3 (b)
def divisors_of(n: int) -> list[int]:
    divisors = [1]
    for m in range(2, n + 1):
        if n % m == 0:
            divisors.append(m)
    return divisors


# Exercise 3 (c)
def sum_of(ints: list[int]) -> int:
    sum = 0
    for i in ints:
        sum += i
    return sum


# Exercise 3 (d)
def is_perfect(n: int) -> bool:
    return sum_of(divisors_of(n)) - n == n


# Exercise 3 (e)
def show_perfect_numbers_up_to(max: int) -> None:
    num_found = 0
    candidate = 1
    while candidate <= max:
        if is_perfect(candidate):
            num_found += 1
            print(f"Nombre parfait numéro {num_found}: {candidate}")
        candidate += 1
    print(f"{num_found} nombres parfaits plus petits que {max} ont été trouvés")


print("--------------------")
print("---- Exercice 3 ----")
print("--------------------\n")

print(f"24 a {count_divisors_of(24)} diviseurs")
divisors_of_24 = divisors_of(24)
print(f"Les diviseurs de 24 sont {divisors_of_24}")
print(f"Leur somme est {sum_of(divisors_of_24)}")

show_perfect_numbers_up_to(1000)

print("\n")
print("--------------------")
print("---- Exercice 4 ----")
print("--------------------\n")


@dataclass
class Person:
    id: int
    name: str
    age: int
    best_friend: Optional["Person"] = None
    worst_enemy: Optional["Person"] = None
    # Optional["Person"] est le moyen correct de le faire; ce
    # serait compté juste de faire simplement Person à la place


luke = Person(0, "Luke", 19)
han = Person(1, "Han", 29)
chewie = Person(2, "Chewbacca", 200)
anakin = Person(3, "Anakin", 42)
yoda = Person(4, "Yoda", 896)
jabba = Person(5, "Jabba", 600)

han.best_friend = chewie
han.worst_enemy = jabba
chewie.best_friend = han
luke.worst_enemy = anakin
anakin.worst_enemy = anakin
jabba.worst_enemy = han

# Exercise 4 (c)
people = [luke, han, chewie, anakin, yoda, jabba]

for p in people:
    print(p)

# Exercise 4 (d)
for p in people:
    if p.best_friend is not None and p.worst_enemy is not None:
        print(
            f"{p.name} a aussi bien un meilleur ami ({p.best_friend.name}) qu'un pire ennemi ({p.worst_enemy.name})"
        )


# Exercise 4 (e)
for p in people:
    if p.worst_enemy == p:
        print(f"{p.name} est son propre pire ennemi")

# Exercise 4 (f)
for p in people:
    if p.best_friend is None and p.worst_enemy is None:
        print(f"{p.name} est-il apathique?")

# Exercise 4 (g)
for p in people:
    if p.best_friend is not None and p.best_friend.best_friend == p and p.id < p.best_friend.id:
        print(f"{p.name} et {p.best_friend.name} sont meilleurs amis symétriquement")

# Exercise 4 (h)
num_without_best_friend = 0
age_sum_witout_best_friend = 0
for p in people:
    if p.best_friend is None:
        num_without_best_friend += 1
        age_sum_witout_best_friend += p.age

age_avg_without_best_friend = age_sum_witout_best_friend / num_without_best_friend
print(f"La moyenne d'âge des personnages sans meilleur ami est de {age_avg_without_best_friend} ans")

# Exercise 4 (i)
num_below_avg = 0
num_above_avg = 0
for p in people:
    if p.best_friend is None:
        if p.age > age_avg_without_best_friend:
            num_above_avg += 1
        elif p.age < age_avg_without_best_friend:
            num_below_avg += 1

if num_below_avg == num_above_avg:
    print("La moyenne est valable comme médiane")
else:
    print("La moyenne n'est pas valable comme médiane")
Last modified: Monday, 25 March 2024, 17:04