Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Jupyter notebook Sujets/Semaine 1 - Le point sur les types Python/Le point sur les types Python.ipynb

171 views
Kernel: Python 3

Le point sur les types en Python

Ces exercices ont pour but de vous faire réfléchir à la façon de modéliser un problème à l'aide des types Python (listes, dictionnaires, etc.).

Exercice : Compter les mots et les caractères (tiré du TP 10 d’AP1).

On souhaite faire des statistiques sur l’usage des caractères (lettres) ainsi que des différents mots dans un long texte, en comptant le nombre d’occurrences de chaque lettre ou de chaque mot.

Structures de données

  • Pour commencer, on cherche à compter seulement le nombre d’occurrences de chaque caractère. En supposant que le texte contient uniquement des caractères ASCII (facilement représentables par un entier compris entre 32 et 126), proposer une structure la plus simple possible pour stocker le nombre d’occurrences de chaque caractère. Utilisez le code du caractère comme indice.

les mots clé (keywords) vont être la lettre et la valeur vas être le nombre d'occurence : exemple dico[a] = 2 la lettre apparait 2 fois

  • Que se passe-t-il si le texte n’est pas codé en ASCII mais en UTF-8 (qui peut représenter en théorie jusqu’à 1112064 symboles différents, même si tous ne sont pas utilisés) ? Adaptez la structure de donnée en conséquence. Utilisez le caractère comme clef d'accès.

  • On s’intéresse maintenant au comptage des mots du texte. Discutez les deux choix de structure utilisés pour les lettres, et indiquez pourquoi l’un de ces deux choix n’est pas adapté du tout. On défini un mot comme une suite de caractères non transparants/espace.

  • Décrivez rapidement un algorithme permettant de calculer la fréquence d’apparition de chaque mot dans le texte.

remplacer ce texte

Implémentation

Dans les questions qui suivents, nous allons réellement implémenter l'ensemble des structures de données, fonctions et algorithmes décrits ci-dessus.

  • Écrivez une fonction compte_caracteres qui prend en argument une chaîne de caractères et un dictionnaire, insère dans le dictionnaire le nombre d'occurrences de chaque caractère dans la chaîne, et renvoie le nombre total de caractères dans la chaîne.

def compte_caracteres (chaine,dico): for i in chaine: if i in dico: dico[i] = dico[i] +1 else : dico[i]= 1 return len(chaine) dico={} print(compte_caracteres("Hello",dico))
5
# Verifiez votre code en executant cette cellule SHIFT+Enter # si vous n'avez pas d'assertion error c'est bon assert (compte_caracteres("hello",dict())== 5) # dico = dict() assert(compte_caracteres("hello",dico) == 5) # assert (dico['l'] == 2)
  • Écrivez une fonction compte_mots qui prend en argument une chaîne de caractères et un dictionnaire comme paramètres et qui insère dans le dictionnaire le nombre d'occurrences de chaque mot de la chaîne. La fonction renverra le nombre total de mots dans cette chaîne.

def compte_mots (chaine,dico): a=0 lst=chaine.split() for i in lst: if i in dico: dico[i]+=1 a+=1 else: dico[i]=1 a+=1 return a
# Verifiez votre code en executant cette cellule SHIFT+Enter dico = dict() assert (compte_mots("hello ceci est un texte",dico)== 5) assert (compte_mots("hello hello the sun is shining hello",dico)== 7) assert (dico['hello'] == 4)

Manipulation de fichiers

  • Écrivez une fonction qui prend un nom de fichier en argument et qui compte et renvoie le nombre total de lignes, de mots et de caractères dans le fichier.

def Nblignes(fichier): f=open(fichier,"r") lst=f.readlines() f.close() lignes = len(lst) lst =" ".join(lst) return lignes Nblignes("hernani.txt")
5592
def Nblignes(fichier): f=open(fichier,"r") lst=f.readlines() f.close() lignes = len(lst) chaine =" ".join(lst) dico_m={} dico_cara={} total_m = compte_mots(chaine,dico_m) total_cara =compte_caracteres(chaine,dico_cara) return (lignes,total_m,total_cara) Nblignes("hernani.txt")
(5592, 24975, 163860)
  • Modifiez la fonction précédente pour qu'elle compte et renvoie aussi le nombre d'occurrences de chaque mot et de chaque caractère.

def Nblignes(fichier): f=open(fichier,"r") lst=f.readlines() f.close() lignes = len(lst) chaine =" ".join(lst) dico_m={} dico_cara={} total_m = compte_mots(chaine,dico_m) total_cara =compte_caracteres(chaine,dico_cara) ponctuation = ["?","!",",","."] chaine=chaine.replace("\n"," ") #Supression de discalies p=chaine.index('_') while p < len(chaine): if chaine[p]=='_': lst2=chaine[(p+1):] if '_' in lst2: indice2=p+lst2.index('_') chaine=chaine.replace(chaine[p:indice2+2],"") p+=1 #ponctuation for c in ponctuation: chaine=chaine.replace(c," ") return (lignes,total_m,total_cara) Nblignes("hernani.txt")
(5592, 24975, 163860)
  • Écrivez une fonction qui prend un nom de fichier en paramètre et écrit les statistiques calculées par la fonction précédente dans un fichier portant le même nom suffixé par .stats. Par exemple, appelée sur un fichier hernani.txt, la fonction créera le fichier hernani.txt.stats (en TP, ce fichier est fourni dans le répertoire de la semaine 1).

def ecrire_nb_ligne_fichier(fichier): (lignes,total_m,total_cara,)=Nblignes(fichier) fichier=fichier+".stats" dico_m={} dico_cara={} texte="Nombre de lignes : "+str(lignes)+".\n"+"Nombre de mots : "+str(total_m)+".\n"+"Nombre de caractères : "+str(total_cara)+".\n" texte+="\nOccurences des mots :\n" for mot in dico_m: texte+="Occurences du mot '"+mot+"' : "+str(dico_m[mot])+".\n" texte+="\nOccurences des caractères :\n" for elem in dico_cara: texte+="Occurences du caractère '"+elem+"' : "+str(dico_cara[elem])+".\n" f=open(fichier,"w") f.write(texte) f.close() ecrire_nb_ligne_fichier("hernani.txt")
  • ☆ Modifiez le programme pour ignorer la ponctuation.

Voir fonction NbLignes
  • ☆ Modifiez le programme pour ignorer les didascalies et les noms de personnages.

Voir fonction NbLignes
  • ☆ Modifiez le programme pour afficher le comptage des mots et des caractères par nombre d'occurrences décroissant. Indice : utilisez la fonction prédéfinie sorted.

def tri_dico(dico): lst_dico=[] for elem in dico: lst_dico.append([dico[elem],elem]) lst_dico=sorted(lst_dico, reverse=True) return lst_dico def ecrire_nb_ligne_fichier_tri(fichier): (lignes,total_m,total_cara)=Nblignes(fichier) dico_m = {} dico_cara = {} fichier=fichier+".stats" texte="Nombre de lignes : "+str(lignes)+".\n"+"Nombre de mots : "+str(total_m)+".\n"+"Nombre de caractères : "+str(total_cara)+".\n" texte+="\nOccurences des mots :\n" lst_m=tri_dico(dico_m) lst_cara=tri_dico(dico_cara) for mot in lst_m: texte+="Occurences du mot '"+str(mot[1])+"' : "+str(mot[0])+".\n" texte+="\nOccurences des caractères :\n" for cara in lst_cara: texte+="Occurences du caractère '"+str(cara[1])+"' : "+str(cara[0])+".\n" f=open(fichier,"w") f.write(texte) f.close() print ecrire_nb_ligne_fichier_tri("hernani.txt")

Exercice : Polygones.

On souhaite créer une petite application graphique permettant de dessiner des polygones. Avant de se lancer dans la réalisation de l'interface, on souhaite écrire quelques fonctions permettant de manipuler les polygones.

  • Proposez une structure Python permettant de représenter un polygone.

#On represente chaque point suous forme de liste tuple exemple un triangle: # polygone=[[1,2],[6,18] ,[19,25] ]
  • Donnez une expression permettant d’accéder à l’abscisse du premier point d’un polygone.

#le premier point serait polygone[0][0]
  • Écrivez une fonction calculant le périmètre d’un polygone.

def longueur_segment(pt1,pt2): dist_carre=(pt1[0]-pt2[0])**2 dist_carre+=(pt1[1]-pt2[1])**2 return(math.sqrt(dist_carre)) def permimetre(P): peri=0 pts=len(P) for i in range (nbpts-1): peri+=longueur_segment(P[i],P[i+1]) peri+=longueur_segment(P[0],P[-1]) return peri
  • Une fois un premier polygone dessiné, il est tentant d’en dessiner un deuxième. Mais si l’on se trompe ? Décrivez une structure Python permettant de supprimer le dernier polygone créé, puis le polygone précédent, etc.

Pour supprimer un polygone d'indice i : lst.pop(i) i=len(lst)-1 si on veut prendre le dernier polygone
  • Quelles sont les actions nécessaires pour maintenir cette structure, et à quel moment sont-elles effectuées ?

Pour ajouter un point de coordonnées (x,y) au polygone d'indice i : lst[i].append((x,y))
  • Pour aller plus loin : écrivez dans un programme python séparé (pas dans ce notebook) et à l'aide de la bibliothèque upemtk une interface graphique permettant de dessiner des polygones à l'aide de la souris. Chaque clic gauche insère un nouveau point, et un clic droit referme le polygone en reliant le premier et le dernier point désignés. Par exemple, trois clics gauches suivi d’un clic droit dessinent un triangle. Un clic droit non précédé d'un clic gauche supprimera le dernier polygone créé.

Exercice : Les lapins, ça va et ça vient.

Comme tout le monde le sait, dans la société des lapins on trouve plusieurs grandes familles. Il y a par exemple les familles Rabbit, Bunny, Lapin, etc. Chaque famille est composée d’un ou plusieurs membres, identifiés par leur prénom. Par exemple, Roger et Jacob sont dans la famille Rabbit, Jeannot dans la famille Lapin. Une famille peut contenir plusieurs individus portant le même prénom. On ne connaît pas l’âge exact de chaque membre d’une famille, mais on sait malgré tout dire qui est né avant ou après qui. Les familles voient de nombreuses naissances, mais parfois certain lapins disparaissent du fait de leur âge ou dans de tragiques accidents de cuisine.

  • Proposez un exemple de structure Python permettant de rassembler (au moins) toutes les données décrites ci-dessus.

#On crée un dictionnaire Lapin dont les keywords serait les familles de lapins A l'interieur on aurait une liste pour chaque famille #avec par ordre de naissance le nom de chaque lapin et les donnés qui lui sont attribué #Pour cela il faut faire une liste de tuples
  • Donnez une expression valant True si un membre de la famille Bunny s’appelle Bugs.

def Buggs(dico): if dico["Bunny"] == "Bugs": return True dico_Lapin={"Bunny":["Bugs"] ,"Rabbit":["Roger","Jacob"], "Lapin":["Jeannot"]}
True
  • Donnez une instruction permettant de déclarer la naissance dans la famille Lapin d’un nouveau-né appelé Jeannette.

#voici l'instruction: #dico_Lapin[Lapin]=append."jeanette"
  • Écrivez une fonction permettant de déterminer la famille la plus nombreuse.

def nombreuse(dico): maxi=0 for i in dico: if len(dico[i])>maxi: maxi=len(dico[i]) maxi_famille=i return maxi_famille
  • Écrivez une fonction permettant de déclarer le décès du plus vieux lapin de la famille passée en argument. Attention, si le dernier lapin d’une famille décède, la famille disparaît.

def vieux(dico,famille): if famille in dico: print (dico[famille][0]) dico[famille].pop(0) if len(dico[famille])==0: del dico[famille]
  • Quelle modification pouvez-vous proposer pour modéliser le fait que deux lapins de la même famille ne peuvent porter le même prénom ?

#Il faudrait crée un dictionnaire au nom de la famille de lapin et qui aurait pour keyword le prénom de chaque membre
  • Quelle modification pouvez-vous proposer pour intégrer au modèle l’âge exact de chaque lapin ? Cette modification fonctionne-t-elle si plusieurs lapins de la même famille portent le même prénom ? Comment faire alors ?

#Il Faudrait donc affecter a chaque lapin la valeur de leur age exemple Rabbit["Roger"]= 25 #Si plusieur lapin de la meme famille on le meme nom ca ne marchera pas .

Exercice : Les bons comptes font les bons amis.

Guildenstern s’est mis en tête de tenir les comptes de son groupe d’amis. Ce sont tous des têtes en l’air qui, oubliant régulièrement leur bourse à la maison, se font offrir le sandwich grec en disant « Ouais ouais, je te rembourse quand on sera rentrés à Elseneur. » Par conséquent, ils ont tous de petites dettes les uns envers les autres, et il devient difficile de se rappeler qui doit combien à qui.

  • Proposez une structure Python permettant de rassembler toutes les données nécessaires. Vous devez définir un objet comptes permettant de représenter les dettes des uns et des autres (inventez un exemple contenant au moins Rosencrantz et Guildenstern).

#On peut crée un dictionnaire "prénom" représentant la personne concerné #les keywords représentant le prénom des personne qui doivent de l'argent et la somme que les gens doivent rembourser # exemple: Rosencrantz[Guildenstern]=15
  • Donnez une expression valant True si Rosencrantz doit quelque chose à Guildenstern.

# if Guildenster[Rosencrantz] > 0 # return True
  • Donnez une expression permettant de savoir combien Rosencrantz doit à Guildenstern (en supposant éventuellement que cette expression vaut 0 s’il ne lui doit rien).

def Argent(Guildenstern): if Guildenstern[Rosencrantz] > 0: return Guildenster[Rosencrantz] elif Guildenster [rosencrantz ] == 0: return 0

Comme tout le monde est étourdi, deux personnes se doivent parfois mutuellement de l’argent. Par exemple, si Guildenstern doit xx € à Rosencrantz et Rosencrantz doit yy € à Guildenstern (avec x>yx > y), on peut effacer la dette de Rosencrantz et ramener celle de Guildenstern à xyx - y €.

  • Écrivez une fonction prenant les arguments nécessaires et simplifiant les dettes partout où cela est possible. (Il est conseillé d’écrire des fonctions intermédiaires.)

def compenser(personne1,personne2): if persone1[personne2] > 0 and personne2[personne1] > 0: if personne1[personne2] > personnne2[personne1]: personne1[personne2]= personne1[personne2]- personne2[personne1] personne2[personne1]= personne1[personne2] -personne2[personne1] else : personne1[personne2]= personne2[personne1]- personne1[personne2] personne2[personne1]= personne2[personne1]- personne1[personne2]
  • Pour aller plus loin : écrivez un programme complet de gestion de dettes entre amis en vous inspirant des questions précédentes.