######### Chap 1 - Algorithmie ############

# Algoithmes du cours


# 3 Programmation
# 3.2 Les Fonctions
# 3.2.1 Définitions et synyaxes

def Fibonacci(n:int) -> int :
	x1=0
	x2=1
	x=1
	for i in range(2,n+1):
		x=x1+x2
		x1=x2
		x2=x
	print(x)
	return(x)

def Somme(n:int) -> int:
	S=0
	for k in range(1,n) :
		S=S+k
		return(S)

def Somme2(n:int) -> int:
	S=0
	for k in range(1,n) :
		S=S+k
		print(S)
		
##########################

# 3.2.2 Variables locales vs. Variables globales
# 3.2.2.1 Variables locales

def somme(n:int) -> float : 
	S=n*(n+1)/2
	return(S)

def sommeCarre(n:int) -> float:
	S=n*(n+1)*(2*n+1)/6
	return(S)

##########################

# 3.2.4 Procédures

#Ceci est une fonction
def fctttc(val:float, taux:float) -> float :
	ttc=val*(1+taux/100)
	return(ttc)
#Ceci est une procédure
def procttc(val:float, taux:float) -> None :
	ttc=val*(1+taux/100)
	print(ttc)

##########################

# 3.3 Interactivité

def FortBoyard() -> None:
    import random as rand
    L="|"*20
    print(L)
    NbCoupJoueur=[]
    NbCoupOrdi=[]
    Triche=False
    while len(L)>0 :
        print("Il reste ",len(L)," batons")
        print("A vous de jouer")
        Joueur=int(input("Enlever combien de batons ? (1, 2 ou 3)\n"))
        if Joueur not in [1,2,3] :
            print("Vous trichez !! Vous avez perdu.")
            Triche=True
            break
        NbCoupJoueur=NbCoupJoueur+[Joueur]
        L=L[0:len(L)-Joueur]
        if len(L)==0 :
            print("Vous avez perdu !!")
            break
        else :
            print("A l'ordinateur de jouer.")
            Ordi=rand.randint(1,min(len(L),3))
        NbCoupOrdi=NbCoupOrdi+[Ordi]
        L=L[0:len(L)-Ordi]
        print("L'ordinateur enleve ",Ordi," baton(s)")
        print(L)
    if len(NbCoupJoueur)<=len(NbCoupOrdi) and Triche==False:
        print("Vous avez gagne !! Bravo !")
        
##########################

# 3.4 Instruction conditionnelle (if/else)

def fct(n:int) -> int :		# Définir la fonction fct
	if n%3==0 :				# Si n est divisible par 3, faire
		return(n//3)		# Renvoyer n/3
	elif n%3==1:			# Si n-1 est divisible par 3, faire
		return((n-1)//3)	# Renvoyer (n-1)/3

##########################

# 3.5 Boucles (for et while)

def Carre(n:int, m:int) -> int : # Définir la fonction Carre
    S=0							# Initialisation de la somme à 0
    for k in range(n,m+1) : 	# Pour $k$ allant de $n$ à $m$
        S=S+k**2				# Ajouter $k^2$ à $S$
    return(S)					# Renvoyer $S$

def ComptageLettre(chaine:str) -> None : 
    C=chaine.lower()
    alpha="abcdefghijklmonpqrstuvwxyz"
    for lettre in alpha :
        compteur=0 
        for l in C : 
            if l==lettre :
                compteur = compteur+1
        print("il y a ",compteur,"lettre ",lettre)
        
def puissance2(n:int) -> float :	# Définir la fonction fct dépendant du paramètre n 
	p=0
	while n%2==0 :		# Tant que n est divisible par 2, faire 
		n=n//2			# n est divise par 2
		p=p+1
	return(p)			# Renvoyer la valeur de p

def SommeCubeWhile(n:int) -> int :
	S=0
	k=0
	while k**3<n :		# Tant que le cube est inférieur à n
		S=S+k**3		# Ajouter $k^3$ à S
		k=k+1			# Prendre l'entier suivant
	return(S)			# Renvoyer S

def SommeCubeFor(n:int) -> int :
	S=0
	for k in range(0,int(n**(1/3.0))+1) :	# Pour k allant de 1 à $\floor{\sqrt{n}}$ faire 
		S=S+k**3							# Ajouter $k^3$ à S
	return(S)

##########################

# 4 Débogage

def discriminant(a:float, b:float, c:float) -> float : 
	assert a != 0	# si a=0, le code s'arrête et renvoie AssertionError
	return(b**2-4*a*c)


def Avocat(chaine:str) -> str :
    code= ""
    for lettre in chaine :
        code = code+chr((ord(lettre)-97+ord("k")-97)%26+97)
    return(code)
