Skip to content
Snippets Groups Projects
Commit bd10478b authored by Dahmane Lynda's avatar Dahmane Lynda
Browse files

Tp6

parent fd7657e4
Branches
No related tags found
No related merge requests found
File added
#!/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)
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))
#!/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')
#!/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')
#!/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()
#!/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')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment