import numpy as np
import matplotlib.pyplot as plt


print("\n\nEXERCICE 1")
print("\n1)")
def somme(n, a):
    s = 0.0
    for k in range(1, n+1):
        s += 1/(k**a)
    return s


a = .5
for N in [100, 1000, 10000]:
    S = somme(N, a)
    print(f"pour a = {a} and N = {N} on obtient S = {S}")  

    
print("")
a = .9
for N in [100, 1000, 10000]:
    S = somme(N, a)
    print(f"pour a = {a} et N = {N} on obtient S = {S}")  

    

print("\n\n2)")
def indicePourBorne(B, a):
    s = 0.0
    n = 0
    while s < B:
        n += 1
        s += 1/(n**a)
    return n


for L in [[700, .5], [50, .8]]:
    B, a = L
    print(f"pour a = {a} et B = {B} on obtient l'indice {indicePourBorne(B, a)}")


print("")
a = .5
for B in [100*k for k in range(1, 7)]:
    n = indicePourBorne(B, a)
    print(f"pour a = {a} et B = {B} on obtient n = {n}")  

    
print("")
a = .8
for B in [10*k for k in range(1, 6)]:
    n = indicePourBorne(B, a)
    print(f"pour a = {a} et B = {B} on obtient n = {n}")  


print("\n\n3)")
nbOfSteps = 15
aa = np.linspace(.1, .9, nbOfSteps)

B = 20
NN20 = np.zeros(nbOfSteps)
for k in range(nbOfSteps):
    a = aa[k]
    NN20[k] = indicePourBorne(B, a)


B = 30
NN30 = np.zeros(nbOfSteps)
for k in range(nbOfSteps):
    a = aa[k]
    NN30[k] = indicePourBorne(B, a)


fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)
ax.set_title("Les indices en fonction de a pour differentes bornes")
# ax.set_yscale('log')

ax.plot(aa, NN20, label='B=20')
ax.plot(aa, NN30, label='B=30')

ax.set_xlabel('a')
# ax.set_ylabel('log10(N_{B,a})')
ax.grid(True)
ax.legend()
plt.show()


fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)
ax.set_title("Les log des indices en fonction de a pour differentes bornes")
ax.set_yscale('log')

ax.plot(aa, NN20, label='B=20')
ax.plot(aa, NN30, label='B=30')

ax.set_xlabel('a')
ax.set_ylabel('log10(N_{B,a})')
ax.grid(True)
ax.legend()
plt.show()



print("\n\nEXERCICE 2\n")

def melange(stg):
    if len(stg) <= 3:
        return stg
    else:  # stg[5:9] devant, puis le reste
        # (sans les 3 premiers et sans [5:9]),
        # puis on met les 3 premiers à la fin
        return stg[5:9] + stg[3:5] + stg[9:] + stg[:3]


for stg in ["aaabbccccddee", "philosophie", "avion", "cravatte"]:
    print(f"{stg} devient {melange(stg)}")
    

s_ini = "avion"
s = "avion"
for n in range(1, 50):
    s = melange(s)
    if s == s_ini:
        print(f"\nretour à {s_ini} pour n =", n)
        break


print("")
s_ini = "cravattes"
s = s_ini
for n in range(1, 50):
    print(s)
    s = melange(s)
    if s == s_ini:
        print(f"retour à {s_ini} pour n =", n)
        break


print("")
s_ini = "philosophie"
s = s_ini
for n in range(1, 50):
    print(s)
    s = melange(s)
    if s == s_ini:
        print(f"retour à {s_ini} pour n =", n)
        break

    
    
print("\n\nEXERCICE 3")

N = 1000
L = list(np.random.randint(1, 11, size=N))  # 1..10
# print(L)


def apparitions(N):
    L = np.random.randint(10, 21, size=N)
    # on suppose lst contient des entiers de 11 à 20
    valeurs = np.arange(10, 21)   # 11..20
    counts = np.zeros(11, dtype=int)
    for x in L:
        counts[x - 10] += 1
    return np.vstack([valeurs, counts])

# exemple
N = 22000
test = apparitions(N)
print(f"pour N = {N} on obtient la matrice \n{test}")

plt.plot(test[0, :], test[1, :])
plt.show()

print("\nOn remarque que les apparitions varient assez peu autour de N/11 = {N/11}.") 
