From bd10478bb230df65dad6b24d0f3ebf446af7677d Mon Sep 17 00:00:00 2001 From: Dahmane Lynda <lynda.dahmane.etu@118p28.fil.univ-lille.fr> Date: Wed, 21 Feb 2024 11:48:19 +0100 Subject: [PATCH] Tp6 --- Tp6/associations.zip | Bin 0 -> 6090 bytes Tp6/associations/ap_decorators.py | 135 ++++++++++++++++++++++++++++++ Tp6/associations/apl1test.py | 89 ++++++++++++++++++++ Tp6/associations/association.py | 89 ++++++++++++++++++++ Tp6/associations/dicotrie.py | 98 ++++++++++++++++++++++ Tp6/associations/mesures.py | 98 ++++++++++++++++++++++ Tp6/associations/recherches.py | 117 ++++++++++++++++++++++++++ 7 files changed, 626 insertions(+) create mode 100644 Tp6/associations.zip create mode 100644 Tp6/associations/ap_decorators.py create mode 100644 Tp6/associations/apl1test.py create mode 100755 Tp6/associations/association.py create mode 100755 Tp6/associations/dicotrie.py create mode 100644 Tp6/associations/mesures.py create mode 100755 Tp6/associations/recherches.py diff --git a/Tp6/associations.zip b/Tp6/associations.zip new file mode 100644 index 0000000000000000000000000000000000000000..d0bdeb1d8c6796026cdf8a32e602d3c46f493c16 GIT binary patch literal 6090 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 literal 0 HcmV?d00001 diff --git a/Tp6/associations/ap_decorators.py b/Tp6/associations/ap_decorators.py new file mode 100644 index 0000000..5f4adc9 --- /dev/null +++ b/Tp6/associations/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/Tp6/associations/apl1test.py b/Tp6/associations/apl1test.py new file mode 100644 index 0000000..8533cca --- /dev/null +++ b/Tp6/associations/apl1test.py @@ -0,0 +1,89 @@ +import thonnycontrib +from thonnycontrib.backend.evaluator import Evaluator +import thonnycontrib.backend.l1test_backend +from thonny.plugins.cpython_backend.cp_back import MainCPythonBackend +import thonnycontrib.backend.doctest_parser +from thonnycontrib.backend.doctest_parser import ExampleWithExpected, ExampleWithoutExpected +import thonnycontrib.backend.ast_parser +from thonnycontrib.backend.ast_parser import L1DocTest +import thonnycontrib.backend.verdicts +from thonnycontrib.backend.verdicts.ExceptionVerdict import ExceptionVerdict + +import inspect +import tempfile +import os +import sys + +class MockBackend(MainCPythonBackend): + """ + Fake backend. + """ + def __init__(self): + ... + + def send_message(self, msg) -> None: + ... + +# register backend +thonnycontrib.backend.l1test_backend.BACKEND = MockBackend() + +def l1test_to_org(filename: str, source: str=""): + """ + Return an org abstract of the tests presents in `filename` file. + """ + abstract = {'total': 0, + 'success': 0, + 'failures': 0, + 'errors': 0, + 'empty': 0} + + if source == "": + with open(filename, 'rt') as fin: + source = fin.read() + evaluator = Evaluator(filename=filename, + source=source) + tests = evaluator.evaluate() + n = len(tests) + abstract['total'] = n + res = "" + for test in tests: + examples = test.get_examples() + res_examples = "" + nb_test, nb_test_ok = 0, 0 + empty = True + for example in examples: + verdict = test.get_verdict_from_example(example) + if isinstance(example, ExampleWithExpected): + nb_test += 1 + if verdict.isSuccess(): + nb_test_ok += 1 + abstract['success'] += 1 + else: + abstract['failures'] += 1 + empty = False + if isinstance(verdict, ExceptionVerdict): + abstract['errors'] += 1 + empty = False + res_examples += f"** {verdict}\n\n" + if not verdict.isSuccess(): + res_examples += f" {verdict.get_details()}\n\n" + if not empty: + res += f"* {test.get_name()} ~ {nb_test_ok}/{nb_test} réussis\n\n" + else: + abstract['empty'] += 1 + res += f"* {test.get_name()}\n\n Aucun test trouvé !\n\n" + res += res_examples + res = f"Tests exécutés : {abstract['total']}\nSuccès: {abstract['success']}, \ +Echecs: {abstract['failures']}, Erreurs: {abstract['errors']}, \ +Vide: {abstract['empty']}\n\n" + res + return res + + +def testmod(modulename: str): + """ + mimic the doctest.testmod function + for `modulename` module + """ + print(l1test_to_org(modulename)) + + diff --git a/Tp6/associations/association.py b/Tp6/associations/association.py new file mode 100755 index 0000000..179219e --- /dev/null +++ b/Tp6/associations/association.py @@ -0,0 +1,89 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`association` module : un module pour les associations clé-valeur + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2024 février + +""" +from ap_decorators import count +from typing import TypeVar + +# On définit deux types génériques : +# - C pour le type des clés +# - V pour le type des valeurs + +C = TypeVar('C') +V = TypeVar('V') + +class Association: + """Classe d'une association clé-valeur + """ + + def __init__(self, cle: C, valeur: V): + """ + $$$ asso1 = Association('a', 1) + $$$ asso1.cle + 'a' + $$$ asso1.valeur + 1 + """ + self.cle=cle + self.valeur=valeur + + def __repr__(self) -> str: + """ + $$$ repr(Association(2, 3)) + 'Association(2, 3)' + $$$ repr(Association('a', 1)) + "Association('a', 1)" + $$$ repr(Association((1, True), [1, 2, 3])) + 'Association((1, True), [1, 2, 3])' + """ + return f"Association{(self.cle,self.valeur)}" + + def __eq__(self, autre) -> bool: + """ + $$$ Association('a', 1) == Association('a', 1) + True + $$$ Association('a', 1) == Association('a', 2) + False + $$$ Association('a', 1) == Association(1, 'a') + False + $$$ AssertionError('a', 1) == ('a', 1) + False + """ + if isinstance(autre,Association): + return self.cle==autre.cle and self.valeur==autre.valeur + return False + +@count +def comp_asso(a1: Association, a2: Association) -> int: + """Renvoie 0 si les clés de a1 et a2 sont identiques + -1 si la clé de a1 < la clé de a2 + 1 si la clé de a1 > la clé de a2 + + Precondition : les clés de a1 et a2 sont comparables + + $$$ comp_asso(Association(1, 'a'), Association(1, 'c')) + 0 + $$$ comp_asso(Association(1, 'a'), Association(2, 'a')) + -1 + $$$ comp_asso(Association(1, 'd'), Association(0, 'c')) + 1 + """ + if a1.cle==a2.cle: + return 0 + elif a1.cle< a2.cle: + return -1 + else: + return 1 + +if __name__ == '__main__': + import apl1test + apl1test.testmod('association.py') + diff --git a/Tp6/associations/dicotrie.py b/Tp6/associations/dicotrie.py new file mode 100755 index 0000000..b863fbb --- /dev/null +++ b/Tp6/associations/dicotrie.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`dicotrie` module : un module pour les ensembles d'associations + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2024 février + +""" + +from association import Association, C, V, comp_asso +from recherches import indice_dicho, inserer +from types import NoneType + + +class DicoTrie: + """Classe d'une association clé-valeur + """ + + def __init__(self, liste_assos: list[Association]): + """ + """ + self.liste_assos=liste_assos + + def __repr__(self) -> str: + """ + $$$ repr(DicoTrie([Association('a', 1)])) + "DicoTrie([Association('a', 1)])" + $$$ repr(DicoTrie([Association('a', 1), Association('b', 2)])) + "DicoTrie([Association('a', 1), Association('b', 2)])" + $$$ repr(DicoTrie([Association('c', 3), Association('a', 2), Association('b', 1)])) + "DicoTrie([Association('a', 2), Association('b', 1), Association('c', 3)])" + """ + ... + + def __eq__(self, autre) -> bool: + """ + $$$ d1 = DicoTrie([Association("a", 1), Association("b", 2)]) + $$$ d2 = DicoTrie([Association("b", 2), Association("a", 1)]) + $$$ d3 = DicoTrie([Association("a", 1), Association("b", 2), Association("c", 3)]) + $$$ d1 == d2 + True + $$$ d1 == d3 + False + $$$ d1 == {"a": 1, "b": 2} + False + """ + ... + + def __setitem__(self, cle: C, valeur: V) -> NoneType: + """ + $$$ d1 = DicoTrie([Association("a", 1), Association("b", 2)]) + $$$ d1["c"] = 3 + $$$ d1 + DicoTrie([Association("a", 1), Association("b", 2), Association("c", 3)]) + """ + ... + + def __getitem__(self, cle: C) -> V: + """ + $$$ d1 = DicoTrie([Association("a", 1), Association("b", 2)]) + $$$ d1['a'] + 1 + $$$ d1['b'] + 2 + $$e d1['c'] + KeyError + """ + ... + + def __delitem__(self, cle: C) -> NoneType: + """ + $$$ d1 = DicoTrie([Association("a", 1), Association("b", 2)]) + $$$ del d1['a'] + $$$ d1 + DicoTrie([Association("b", 2)]) + $$e del d1['c'] + KeyError + """ + ... + + def __contains__(self, cle: C) -> bool: + """ + $$$ d1 = DicoTrie([Association("a", 1), Association("b", 2)]) + $$$ 'a' in d1 + True + $$$ 'c' in d1 + False + """ + ... + +if __name__ == '__main__': + import apl1test + apl1test.testmod('dicotrie.py') + diff --git a/Tp6/associations/mesures.py b/Tp6/associations/mesures.py new file mode 100644 index 0000000..ae603e7 --- /dev/null +++ b/Tp6/associations/mesures.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`mesures` module : un module pour les mesures de temps + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2024 février + +""" +from dicotrie import DicoTrie +from association import Association +from types import NoneType +from timeit import timeit +from random import randrange +import matplotlib.pyplot as plt + +def generation_dict(tailles: list[int]) -> list[dict[str, NoneType]]: + """Renvoie une liste de dictionnaires dont les clés sont les + représentations des n entiers compris entre 0 et n-1 et les valeurs + associées None pour chaque entier n dans la liste tailles. + + Précondition : tous les entiers de tailles sont positifs ou nuls + + $$$ generation_dict([0, 2, 4]) + [{}, {'0': None, '1':None}, {'0': None, '1': None, '2': None, '3': None}] + """ + ... + +def generation_dicotrie(tailles: list[int]) -> list[DicoTrie]: + """Renvoie une liste de DicoTrie dont les clés sont les représentations + des n entiers compris entre 0 et n-1 et les valeurs associées None pour + chaque entier n dans la liste tailles. + + Précondition : tous les entiers de tailles sont positifs ou nuls + + $$$ generation_dicotrie([0, 2]) + [DicoTrie([]), DicoTrie([Association('0', None), Association('1', None)])] + """ + ... + +def mesure_temps_acces(taille : int, d: dict[str, NoneType] | DicoTrie) -> float: + """Renvoie le temps moyen mis pour accéder à 1000 éléments quelconques + du dictionnaire d. + + Précondition : les clés de d sont les représentations des entiers + compris entre 0 et taille - 1. + """ + cles_a_tester = [str(randrange(taille)) for _ in range(1000)] + stmt = "all(d[cle] == None for cle in cles_a_tester)" + return timeit(stmt = stmt, globals = locals(), number = 1) / 1000 + +def mesures_temps_acces_dict(tailles: list[int]) -> list[float]: + """Renvoie les listes des temps moyens pour accéder à 1000 éléments quelconques + de chacun des dictionnaires dont les clés sont les remprésentations des + n entiers compris entre 1 et n-1 pour chaque entier n dans la liste + tailles. + + Précondition : tous les entiers de tailles sont positifs ou nuls + """ + ... + +def mesures_temps_acces_dicotrie(tailles: list[int]) -> list[float]: + """Renvoie les listes des temps moyens pour accéder à 1000 éléments quelconques + de chacun des DicoTrie dont les clés sont les remprésentations des + n entiers compris entre 1 et n-1 pour chaque entier n dans la liste + tailles. + + Précondition : tous les entiers de tailles sont positifs ou nuls + """ + ... + + +if __name__ == '__main__': + import apl1test + apl1test.testmod('mesures.py') + + # Écrivez ici le code permettant de faire des hypothèses sur la + # vitesse d'accès aux dictionnaires. + + # linéaire + # tailles = list(range(0, 100000, 1000) + # temps_dict = mesures_temps_acces_dict(tailles) + # temps_dicotrie = mesures_temps_acces_dicotrie(tailles) + # plt.plot(tailles, temps_dict, '+') + # plt.plot(tailles, temps_dicotrie, '.') + # plt.show() + # log + # tailles = [2**n for n in range(16)] + # temps_dict = mesures_temps_acces_dict(tailles) + # temps_dicotrie = mesures_temps_acces_dicotrie(tailles) + # plt.plot(range(16), temps_dict, '+') + # plt.plot(range(16), temps_dicotrie, '.') + # plt.show() + + diff --git a/Tp6/associations/recherches.py b/Tp6/associations/recherches.py new file mode 100755 index 0000000..fa01a60 --- /dev/null +++ b/Tp6/associations/recherches.py @@ -0,0 +1,117 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`recherches` module : un module pour les recherches + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2024 février + +""" +from typing import TypeVar, Callable +from types import NoneType + +# On définit un type générique : +C = TypeVar('C') + +def indice_seq(elem: C, liste: list[C], comp: Callable[[C, C], int]) \ + -> tuple[bool, int]: + """Renvoie un couple (trouve, i) tel que: + - si elem est un élément de liste, + * trouve = True + * i est l'indice de première occurence de elem dans liste + - si elem n'est pas un élément de la liste : * trouve = False + * i = len(liste) + + Précondition : comp est une fonction de comparaison sur C + + $$$ def compare(x, y): return 0 if x == y else 1 if x > y else -1 + $$$ indice_seq(0, [1, 3, 5], compare) + (False, 3) + $$$ indice_seq(3, [1, 3, 5], compare) + (True, 1) + $$$ indice_seq(4, [1, 3, 5], compare) + (False, 3) + $$$ indice_seq(5, [1, 3, 5], compare) + (True, 2) + $$$ indice_seq(6, [1, 3, 5], compare) + (False, 3) + $$$ indice_seq(42, [], compare) + (False, 0) + """ + trouve=False + i=len(liste) + + for index, element in enumerate(liste): + if comp(elem,element)==0: + trouve=True + i=index + + return trouve,i +# +# def indice_dicho(elem: C, liste: list[C], comp: Callable[[C, C], int]) \ +# -> tuple[bool, int]: +# """Renvoie un couple (trouve, i) tel que: +# - si elem est un élément de liste, +# * trouve = True +# * i est l'indice de première occurence de elem dans liste +# - si elem n'est pas un élément de la liste : +# * trouve = False +# * pour tout j < i, liste[j] < liste[i] +# * pour tout j > i, liste[j] > liste[i] +# +# Précondition : comp est une fonction de comparaison et liste est triée pour comp +# +# $$$ def compare(x, y): return 0 if x == y else 1 if x > y else -1 +# $$$ indice_dicho(0, [1, 3, 5], compare) +# (False, 0) +# $$$ indice_dicho(3, [1, 3, 5], compare) +# (True, 1) +# $$$ indice_dicho(4, [1, 3, 5], compare) +# (False, 2) +# $$$ indice_dicho(5, [1, 3, 5], compare) +# (True, 2) +# $$$ indice_dicho(6, [1, 3, 5], compare) +# (False, 3) +# $$$ indice_dicho(42, [], compare) +# (False, 0) +# """ +# + + + +def inserer(indice: int, elem: C, liste: list[C]) -> NoneType: + """Insère l'élément elem à l'indice indice de la liste liste. + + Précondition : 0 ≤ indice ≤ len(liste) + + $$$ l = [1, 3, 5] + $$$ inserer(0, 0, l) + $$$ l + [0, 1, 3, 5] + $$$ inserer(4, 6, l) + $$$ l + [0, 1, 3, 5, 6] + $$$ inserer(3, 4, l) + $$$ l + [0, 1, 3, 4, 5, 6] + $$$ vide = [] + $$$ inserer(0, 42, vide) + $$$ vide + [42] + """ + if indice==len(liste): + liste.append(elem) + else: + liste.append(None) + for i in range (len(liste)-1, indice, -1): + liste[i]=liste[i-1] + liste[indice]=elem + + +if __name__ == '__main__': + import apl1test + apl1test.testmod('recherches.py') + -- GitLab