diff --git a/Tp2/ap_decorators.py b/Tp2/ap_decorators.py new file mode 100644 index 0000000000000000000000000000000000000000..5f4adc9129d3d7ffef9d7dc68b59e4d6643d419d --- /dev/null +++ b/Tp2/ap_decorators.py @@ -0,0 +1,135 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:module: ap_decorators +:author: FIL - Faculté des Sciences et Technologies - Univ. Lille <http://portail.fil.univ-lille1.fr>_ +:date: 2018, september + +""" + +from functools import wraps + + +def trace(fct): + ''' + Decorator for tracing every call to fct. + Recursive calls are indented. + + :Example: + + >>> @trace + ... def fact(n): + ... if n == 0: + ... return 1 + ... else: + ... return n * fact(n - 1) + + >>> fact(5) + -> fact((5,), {}) + ... -> fact((4,), {}) + ...... -> fact((3,), {}) + ......... -> fact((2,), {}) + ............ -> fact((1,), {}) + ............... -> fact((0,), {}) + ............... <- 1 + ............ <- 1 + ......... <- 2 + ...... <- 6 + ... <- 24 + <- 120 + 120 + ''' + @wraps(fct) + def wrapper(*args, **kwargs): + dots = '...' * wrapper.__depth + print('{:s} -> {:s}{:s}'.format(dots, wrapper.__name__, repr((args, kwargs)))) + wrapper.__depth += 1 + y = fct(*args, **kwargs) + wrapper.__depth -= 1 + print('{:s} <- {:s}'.format(dots, repr(y))) + return y + wrapper.__depth = 0 + return wrapper + +def count(fct): + ''' + decorator for counting calls to function fct + + :Example: + + >>> @count + ... def fact(n): + ... if n == 0: + ... return 1 + ... else: + ... return n * fact(n - 1) + + >>> fact.counter + 0 + >>> fact(5) + 120 + >>> fact.counter + 6 + ''' + @wraps(fct) + def wrapper(*args, **kwargs): + y = fct(*args, **kwargs) + wrapper.counter += 1 + return y + wrapper.counter = 0 + return wrapper + + +def memoize(fct): + ''' + decorator for memoizing computed values of function fct + + :Example: + + >>> @count + ... @memoize + ... def fact(n): + ... if n == 0: + ... return 1 + ... else: + ... return n * fact(n - 1) + + >>> fact.counter + 0 + >>> fact(5) + 120 + >>> fact.counter + 6 + >>> fact.counter = 0 + >>> fact(5) + 120 + >>> fact.counter + 1 + ''' + cache = dict() + @wraps(fct) + def wrapper(*args, **kwargs): + key = repr((args, kwargs)) + if key in cache: + return cache[key] + else: + y = fct(*args, **kwargs) + cache[key] = y + return y + return wrapper + + + +if __name__ == '__main__': + import doctest + doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=False) + + + + + + + + + diff --git a/Tp2/recursivite.py b/Tp2/recursivite.py new file mode 100755 index 0000000000000000000000000000000000000000..75e8d2264eaac0145d72240724ea1c174eea4875 --- /dev/null +++ b/Tp2/recursivite.py @@ -0,0 +1,361 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +# Noms :Dahmane +# Prenoms :lynda +# Groupe :MI15 +# Date :24/01/2024 + + + +""" + +:mod: module `recursivite` +:author: FIL - Faculté des Sciences et Technologies - Univ. Lille +:link: <http://portail.fil.univ-lille1.fr>_ +:date: Mars 2020 +:dernière révision: janvier 2024 + +""" + +from ap_decorators import count, trace +# l'instruction suivante permet d'annoter des paramètres qui sont des functions. +from collections.abc import Callable + + +def taille_binaire(naturel: int) -> int: + """ + Renvoie le nombre de chiffres dans l'écriture binaire de l'entier naturel `naturel` + + Précondition : + naturel >= 0 + + Exemples : + $$$ taille_binaire(0) + 1 + $$$ taille_binaire(1) + 1 + $$$ taille_binaire(2) + 2 + $$$ taille_binaire(1023) + 10 + $$$ taille_binaire(1024) + 11 + $$$ from random import randrange + $$$ l = [randrange(1,2**100) for _ in range(100)] + $$$ all(taille_binaire(elt) == len(bin(elt))-2 for elt in l) + True + + """ + res = 1 + while naturel>=2: + res += 1 + naturel //= 2 + return res +# +# def taille_binaire_recursive(naturel: int) -> int: +# """ +# Renvoie le nombre de chiffres dans l'écriture binaire de l'entier naturel `naturel` +# +# Précondition : +# naturel >= 0 +# +# Exemples : +# $$$ taille_binaire_recursive(0) +# 1 +# $$$ taille_binaire_recursive(1) +# 1 +# $$$ taille_binaire_recursive(2) +# 2 +# $$$ taille_binaire_recursive(1023) +# 10 +# $$$ taille_binaire_recursive(1024) +# 11 +# $$$ from random import randrange +# $$$ l = [randrange(1,2**100) for _ in range(100)] +# $$$ all(taille_binaire_recursive(elt) == len(bin(elt))-2 for elt in l) +# True +# """ +# +# if naturel==1: +# return 1 +# else: +# +# res+1 +# taille_binaire_recursive(naturel//2) +# return res +# + + +def poids_binaire(naturel: int) -> int: + """ + Renvoie le nombre de chiffre 1 dans l'écriture binaire de l'entier naturel `naturel` + + Précondition : + naturel >= 0 + + Exxemples : + + $$$ poids_binaire(0) + 0 + $$$ poids_binaire(1) + 1 + $$$ poids_binaire(2) + 1 + $$$ poids_binaire(255) + 8 + $$$ from random import randrange + $$$ l = [randrange(1,2**100) for _ in range(100)] + $$$ all([poids_binaire(x)==bin(x).count('1') for x in l]) + True + """ + res = naturel % 2 + while naturel > 0: + naturel //= 2 + res += naturel % 2 + return res + +# +# def poids_binaire_recursif(naturel: int) -> int: +# """ +# Renvoie le nombre de chiffre 1 dans l'écriture binaire de l'entier naturel `naturel` +# +# Précondition : +# naturel >= 0 +# +# Exxemples : +# +# $$$ poids_binaire_recursif(0) +# 0 +# $$$ poids_binaire_recursif(1) +# 1 +# $$$ poids_binaire_recursif(2) +# 1 +# $$$ poids_binaire_recursif(255) +# 8 +# $$$ from random import randrange +# $$$ l = [randrange(1, 2**100) for _ in range(100)] +# $$$ all([poids_binaire_recursif(x)==bin(x).count('1') for x in l]) +# True +# """ +# res= naturel % 2 +# while naturel>1: +# res=res + (poids_binaire_recursif(naturel//2)%2) +# return res +# + + +def puissance(x: int|float, n: int) -> int|float: + """ + Calcule x élevé à la puissance n + + Précondition : + n>=0 + + Exemples : + + $$$ puissance(10, 0) + 1 + $$$ puissance(10, 1) + 10 + $$$ puissance(2, 10) + 1024 + """ + if n==0: + return 1 + else: + return x*puissance(x,n-1) + + +def puissance_v2(x: int|float, n: int) -> int|float: + """ + calcule x élevé à la puissance n + + Précondition : n>=0 + + Exemples : + $$$ puissance_v2(10,0) + 1 + $$$ puissance_v2(10,1) + 10 + $$$ puissance_v2(2,10) + 1024 + """ + if n==0: + return 1 + else: + return fois(x, puissance_v2(x,n-1)) + +@count +def fois(x: int|float, y: int|float) -> int|float: + """ + renvoie le produit de x par y + + Précondition : les mêmes que l'opérateur * + + Exemples : + $$$ fois(8, 7) + 56 + """ + if y==0: + return 0 + else: + + return x * y + +def comptage(puissance: Callable[[int|float, int], int|float]) -> list[int]: + """ + Renvoie une liste de longueur 100 contenant le nombre de multiplications + effectuées par la fonction ``puissance`` passée en paramètre + + Précondition : + la fonction doit être implantée en utilisant la fonction ``fois`` + """ + res = [] + for i in range(100): + fois.counter = 0 + _ = puissance(2, i) + res.append(fois.counter) + return res +#Q1: +# le paramétre c'est puissance +#Q2: +# le resultat sera une liste de longueure 100 contenant le nombre de multiplication +#effectuées par la fonction puissanceà chaque itération de la boucle. +#Q3: +#calculons comptage(puissance): +#[1,2,3,4,5,6,7,8,9,10,.......,100] , on obtient ce calcul pour mesurer +# la complexité en nombre de multiplication de fonction puissance et de la fonction +#puissance_v2, cela nous permet de comparer les performances de ces deux fonctions de la valeur d +#Q4: +# on utilise le meme calcul comme d'avant : [1,2,3,4,5,6,7,8,9,10,.......,100] +# on observant les résultats sz comptage(puissance_v2), on peut remarquer que le nombre d'appels recursifs +#de la fonction puissance_v2 correspond au nombre d'éléments dans la liste, qui va de 1 à 100 + + + + +#@trace +def puissance_calbuth(x: int|float, n: int) -> int|float: + """ + calcule x élevé à la puissance n + + Précondition : + n>=0 + + Exemples : + + $$$ puissance_calbuth(10,0) + 1 + $$$ puissance_calbuth(10,1) + 10 + $$$ puissance_calbuth(2,10) + 1024 + + """ + if n == 0: + return 1 + if n == 1: + return x + else: + k = n // 2 + return puissance_calbuth(x, k) * puissance_calbuth(x, n - k) + +def puissance_calbuth_v2(x: int|float, n: int) -> int|float: + """ + calcule x élevé à la puissance n + + Précondition : + n>=0 + + Exemples : + + $$$ puissance_calbuth_v2(10,0) + 1 + $$$ puissance_calbuth_v2(10,1) + 10 + $$$ puissance_calbuth_v2(2,10) + 1024 + + """ + if n==0: + return 1 + elif n % 2==0: + temps=puissance_calbuth_v2(x,n//2) + return fois(temps,temps) + else: + temps=puissance_calbuth_v2(x,(n-1)//2) + return fois(fois(temps,temps),x) +#Q5: + # oui l'idée de Raymond Calbuth permet de diminuer la compléxité en nombre de multiplications +# dans le calcul de la puissance . +#Q6: +# le gain dépend du nombre de fois ou la puissance est dévisée par 2. +#Q7: +# la fonction de n + + + + +def puissance_calbuth_v2_amelioree(x: int|float, n: int) -> int|float: + """ + calcule x élevé à la puissance n + + Précondition : + n>=0 + + Exemples : + + $$$ puissance_calbuth_v2_amelioree(10,0) + 1 + $$$ puissance_calbuth_v2_amelioree(10,1) + 10 + $$$ puissance_calbuth_v2_amelioree(2,10) + 1024 + + """ + ... + +def puissance_erronee(x: int|float, n: int) -> int|float: + """ + aurait dû calculer x élevé à la puissance n + + Précondition : + n >= 0 + + Exemples : + + $$$ puissance_erronee(10, 0) + 1 + $$$ puissance_erronee(10, 1) + 10 + $$$ #$$$ puissance_erronee(2, 10) + $$$ #1024 + """ + if n == 0: + return 1 + elif n == 1: + return x + else: + r = n % 2 + q = n // 2 + return puissance_erronee(x, r) * puissance_erronee(puissance_erronee(x, q), 2) + +def puissance_reparee(x: int|float, n: int) -> int|float: + """ + calcule x élevé à la puissance n + + Précondition : + n>=0 + + Exemples : + + $$$ puissance_reparee(10,0) + 1 + $$$ puissance_reparee(10,1) + 10 + $$$ puissance_reparee(2,10) + 1024 + """ + ... +