2019-2020/Formations/NSI/Bloc1/diubloc1-files-td3/diu-dico-hash.py

183 lines
4.5 KiB
Python

#! /usr/bin/env python3
"""
python3 diu-dico-hash
"""
__author__ = "Nicolas Pronost and Laure Gonnord"
__copyright__ = "Univ Lyon1, 2019"
from libdiulistechainee import * # une librairie maison de listes triées.
import matplotlib.pyplot as plt
import time
import sys
sys.setrecursionlimit(10000)
################## Constantes ######################
TAILLE_TABLE = 308
################## Fonction de hachage ######################
def asciss(mot):
h = 0
for c in mot:
h += ord(c) - 96
return h
def hash(mot):
return asciss(mot) % TAILLE_TABLE
################## Construction de la table ######################
def init_ht(ht):
"""
Construit une liste de TAILLE_TABLE listes chainees (triées)
une nouvelle liste chainee sera obtenue en appelant ListeChainee()
"""
ht = [ListeChainee() for i in range(TAILLE_TABLE)]
return ht
def update_ht(mot, ht):
"""
Ajoute le mot dans la liste chainee triee à la case d'index hash(mot).
Utiliser ajouterDansListeTriee.
"""
ht[hash(mot)].ajouterEnTete(mot)
def load_ht(nomFichier, ht):
"""
Ajoute les mots du fichier dans la table de hachage
"""
with open(nomFichier) as fichier:
for ligne in fichier:
update_ht(ligne[:-1], ht)
################## Fonctionnalités de la table ######################
def afficheCollisions(ht):
"""
Imprime la taille de chaque liste contenue dans les cases de ht
Utiliser la méthode nbElements()
"""
for lc in ht:
print(lc.nbElements())
def nombresCollisions(ht):
"""
Calcule et retourne la taille des listeschainées
pour chaque case de la table
selon une forme utile pour les graphiques, ie :
- la premiere liste contient les indices des cases
- la deuxième la taille de la liste contenue.
Utiliser la méthode nbElements()
"""
res = ([], [])
for k,v in enumerate(ht):
res[0].append(k)
res[1].append(v.nbElements())
return res
def max_hash(nomFichier):
"""
Retourne le couple (mot_max,hmax) du plus "grand" mot (au sens de asciss)
et sa valeur de hachage
"""
mot_max = ""
hmax = 0
with open(nomFichier) as fichier:
for ligne in fichier:
mot = ligne[:-1]
ha = hash(mot)
if ha > hmax:
hmax = ha
mot_max = mot
return (mot_max, hmax)
####### Quelques fonctions de stats/dessin de figures qui font varier la taille de ht
def stats_load(fichier):
global TAILLE_TABLE
ht = []
# affichage temps exec en fct de la taille de la table
plt.figure()
toplot = []
tailles_table = [10, 50, 100, 200, 400]
for TAILLE_TABLE in tailles_table:
ht.clear()
startTime = time.time()
init_ht(ht)
load_ht(fichier, ht)
toplot.append(time.time() - startTime)
plt.plot(tailles_table, toplot, "-k")
plt.title("Temps d'exécution vs. taille table")
plt.grid(True)
plt.show()
# Affichage graphe du nombre de collisions pour plusieurs tailles.
def stats_collisions(fichier):
global TAILLE_TABLE
ht = []
plt.figure()
tailles_table = [10, 50, 100, 200, 400]
colors_plot = ["r", "b", "k", "g", "m"]
for i in range(len(tailles_table)):
TAILLE_TABLE = tailles_table[i]
init_ht(ht)
load_ht(fichier, ht)
(axisX, axisY) = nombresCollisions(ht)
plt.plot(axisX, axisY, colors_plot[i], label="taille " + str(TAILLE_TABLE))
plt.grid(True)
plt.legend(loc="upper right")
# plt.title('Nb de collisions vs. taille table')
plt.show()
################## Programme principal ######################
ht = [] # Ma table de hachage est une liste de listes chainées
fichier = "dico.english"
# initialisation et chargement de la table
ht = init_ht(ht)
load_ht(fichier, ht)
# Affichage console du nombre de collisions
#afficheCollisions(ht)
# A décommenter (il faut numpy et mathplotlib)
# # Affichage graphe du nombre de collisions
# (axisX, axisY) = nombresCollisions(ht)
# plt.figure()
# plt.plot(axisX, axisY, '-k')
# plt.title('Nombre de collisions vs. indice table')
# plt.grid(True)
# plt.savefig("collisions.pdf")
#
# # Mot de valeur de hachage max
(mot_max, hmax) = max_hash(fichier)
print('valeur de hachage max: '+str(hmax)+' pour le mot: '+mot_max)
TAILLE_TABLE = hmax+1
init_ht(ht)
load_ht(fichier, ht)
print('Le mot '+mot_max+' doit être dans la liste : ', end='')
ht[hmax].afficher()
#
# # Maintenant comparons wrt les tailles de ht.
# stats_load(fichier)
# stats_collisions(fichier)