Une étudiante en biologie que vous venez de rencontrer vous demande de l'aide pour un problème de bioinformatique. Grâce aux progrès des techniques de séquençage automatiques de l'ADN, il est maintenant facile d'obtenir l'ADN d'un être vivant. L'ADN est composé de quatre types de bases : Adénine, Cytosine, Guanine et Thymine. Pour manipuler ces séquences ADN, les biologistes ont pris l'habitude de les représenter sous la forme d'une (longue) suite de caractères représentants les 4 bases qui forment l'ADN. A titre d'exemple, voici un extrait de séquence ADN provenant de la base de données GenBank:
LOCUS SCU49845 5028 bp DNA PLN 21-JUN-1999 DEFINITION Saccharomyces cerevisiae TCP1-beta gene, partial cds, and Axl2p (AXL2) and Rev7p (REV7) genes, complete cds. ... ORIGIN 1 gatcctccat atacaacggt atctccacct caggtttaga tctcaacaac ggaaccattg 61 ccgacatgag acagttaggt atcgtcgaga gttacaagct Aaaacgagca gtagtcagct 121 ctgcatctga agccgctgaa gttctactaa gggtggataa catcatccgt gcaagaccaa 181 gaaccgccaa tagacaacat atgtaacata tttaggatat acctcgaaaa taataaaccg 241 ccacactgtc attattataa ttagaaacag aacgcaaaaa ttatccacta tataattcaa 301 agacgcgaaa aaaaaagaac aacgcgtcat agaacttttg gcaattcgcg tcacaaataa ... 4861 ttctccactt cactgtcgag ttgctcgttt ttagcggaca aagatttaat ctcgttttct 4921 ttttcagtgt tagattgctc taattctttg agctgttctc tcagctcctc atatttttct 4981 tgccatgact cagattctaa ttttaagcta ttcaatttct ctttgatc
Une séquence d'ADN d'un gène peut être très longue. A titre d'exemple, on estime que l'ADN humain contient de l'ordre de 3×109 bases découpées en environ 20.000 gènes. L'ADN d'une bactérie contient de l'ordre de 4 millions de bases. Les biologistes ont séquencé l'ADN d'un grand nombre d'espèces qu'ils stockent dans des bases de données spécialisées comme GenBank. Le traitement de toutes ces données a mené à la création de la bio-informatique, discipline qui rassemble des biologistes et des informaticiens.
Afin d'aider cette étudiante en biologie, vous allez écrire durant cette mission vos premiers algorithmes de bio-informatique.
A l'issue de ce problème, chacun d'entre vous :
La matière relative à cette mission est décrite dans les sections suivantes du syllabus :
Il est cependant important que vous puissiez facilement vous y retrouver dans la documentation de Python pour y trouver les renseignements dont vous avez besoin pour écrire des programmes efficaces. Pour des fonctions qui peuvent être exécutées sur des chaînes de caractères, regardez ici.
Les questions à choix multiples de cette mission sont également accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session4_QCM
Vous voulez dire bonjour à l'utilisateur de votre programme. Le nom de l'utilisateur est enregistré dans une variable appelée name et vous voulez enregistrer vos salutations dans une variable nommée hello. Cette chaine de caractères aura la forme suivante : "Hello, name!"
Par exemple, si "Charles" est assigné à name, votre code écrirait "Hello, Charles!" dans la variable hello.
Etant donnée une chaîne de caractères stockée dans une variable l, par exemple, l = "louvain-la-neuve" ou l = "braine-le-compte", comment feriez-vous pour :
La fonction maximum_index(lst) doit retourner l'index de l'élément avec la plus grande valeur dans une liste non vide. Par exemple: maximum_index([0,2,5,3]) doit retourner 2, puisque 5 est la plus grande valeur et apparaît en position 2. Définissez cette fonction.
Nous voulons écrire une fonction positions(s,p) qui pour une chaîne de caractères s et un caractère p retourne la liste des positions où le caractère p apparaît dans s. Par exemple, pour positions("gtagaac","a") le résultat doit être [2,4,5].
def q(c1,c2): return c1.upper () == c2.upper ()
Écrivez une fonction ajoute ( l, v ) qui pour une liste donnée l, ajoute le nombre v à la fin de la liste, si ce nombre n'est pas encore présent dans la liste. Si le nombre apparaît déjà, la liste doit rester non modifiée. Pour ce code:
l = [ 3, 1, 5, 4 ] ajoute ( l, 4 ) ajoute ( l, 6 ) ajoute ( l, 7 ) ajoute ( l, 6 ) print ( l )
Le programme doit imprimer [ 3, 1, 5, 4, 6, 7 ]. La fonction ajoute ne retourne rien.
def mysterieux(n): l = [] for i in range(n): l2 = [] for j in range(n): l2.append ( n ) l.append ( l2 ) return l
Pour un nombre entier donné n, la fonction doit retourner la matrice
[ [ 0, 1, ..., n - 1 ], [ n, n + 1, ..., 2 * n - 1 ], [ 2 * n, 2 * n + 1, ..., 3 * n - 1 ], ..., [ (n-1) * n, (n-1) * n + 1, ..., n * n - 1 ] ]
Par exemple, pour n=4, la fonction retourne
[ [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ], [ 8, 9, 10, 11 ], [ 12, 13, 14, 15 ] ]
Les séquences d'ADN sont composées d'un suite de caractères A, T, C et G. Pour traiter de telles séquences en Python, le plus simple est de les manipuler comme des chaînes de caractères.
Votre objectif durant cette mission est de développer quelques fonctions permettant de traiter des séquences d'ADN stockées sous la forme de chaînes de caractères.
Toutes les fonctions doivent être écrites dans un fichier avec le nom bioinfo.py. Vérifiez pour chaque fonction que la fonction est correcte en utilisant des exemples!
La première fonction à écrire est la fonction is_adn(s). Elle prend comme argument une chaîne de caractères s et retourne True si la chaîne de caractères contient uniquement les caractères a, t, c ou g (à la fois en majuscules et en minuscules) et False sinon. Une chaîne de caractères vide ("") n'est pas considérée comme étant de l'ADN.
De bons exemples à utiliser pour les tests sont ici: "acgac", "AcaA", aAaza, "".
La deuxième fonction à écrire est la fonction positions(s, p). Elle prend comme arguments deux chaînes de caractères s et p. Elle retourne les positions des occurences de p dans s. Par exemple, pour ACGACCG (majuscules) et cg (minuscule) le résultat doit être [1,5]. Vous ne pouvez pas utiliser la fonction find de Python.
La troisième fonction à écrire est baptisée distance_h. Elle calcule la distance de Hamming (http://fr.wikipedia.org/wiki/Distance_de_Hamming) entre deux chaînes de caractères de longueurs égales. En théorie de l'information, cette distance est définie comme étant le nombre de positions où les deux chaînes de caractères diffèrent. Voici quelques exemples qui devraient vous aider à mieux comprendre cette distance :
Chaîne 1 | Chaîne 2 | Distance |
A | A | 0 |
AG | GG | 1 |
AG | AT | 1 |
ATGAC | ATGAC | 0 |
ATGAC | AGGAG | 2 |
ATGAC | TGACG | 5 |
Si les chaînes n'ont pas la même longueur, la fonction doit retourner None.
La quatrième fonction à écrire est distances_matrice(l). Étant donné une liste de chaînes de caractères, la fonction doit calculer une matrice des distances de Hamming entre toutes ces chaînes de caractères. Par exemple, pour cette liste: ["AG", "AT", "GT", "ACG", "ACT" ] la fonction doit retourner:
[ [ 0, 1, 2, None, None ], [ 1, 0, 1, None, None ], [ 2, 1, 0, None, None ], [ None, None, None, 0, 1 ], [ None, None, None, 1, 0 ] ]
Utilisez la fonction que vous avez écrit dans l'exercice précédente.
Pour cette mission, vous devez soumettre votre fichier bioinfo.py au serveur de soumissions de programmes du cours. Votre fichier bioinfo.py doit au moins contenir les fonctions :
is_adn(text) positions(text,car) distance_h(text1,text2) distances_matrice(l)
Écrivez une fonction recherche ( m, v ) qui pour un nombre entier donné v, retourne True si ce nombre apparaît dans la matrice, et False si non. Par exemple, pour la matrice suivante et la valeur v=4, le résultat doit être False. Pour la valeur v=3 le résultat doit être True.
[ [ 0, 3, 2, 8 ], [ 6, 5, 2, 1 ], [ 7, 0, 3, 2 ] ]
La méthode sum(list) retourne la somme des éléments contenus dans list.
Exemple: la somme de [1,2,3] est 6
Notez que votre algorithme devrait être capable de calculer la somme même si la liste list contient des éléments malicieux (pas des nombres).
La méthode average(list) retourne la moyenne arithmétique des éléments contenu dans list, sauf si list est vide auquel cas, elle devrait retourner None.
La méthode diff_count(lst) retourne le nombre d'éléments différents contenus dans la liste lst.
Par exemple:
Les équations du second degré sont des équations de la forme suivante:
$$ax^2 + bx + c = 0$$
avec a ≠ 0
Pour déterminer si l'équation dispose d'une solution, on calcule le nombre ρ = b2 − 4ac. Si ρ est strictement positif, l'équation a exactement deux solutions. La première solution s'obtient via la formule suivante :
Et la seconde racine s'obtient via la formule suivante :
Si ρ est nul, l'équation a exactement une solution, dont la valeur est égale à − b ⁄ (2a). Si ρ est négatif, l'équation n'a aucune solution.
Un étudiant vous demande de l'aider à résoudre des équations à tour de bras. Vous disposez de la fonction suivante, qui est une variante de la fonction implémentée dans un exercice complémentaire de la Session 3:
def solution(a, b, c): """ pre: a, b et c sont 3 nombres réels post: la valeur de retour de cette fonction dépend du nombre de solutions de l'équation ax^2 + bx + c = 0. - 0 solution: retourne la liste vide - 1 solution: retourne une liste contenant la solution de l'équation - 2 solutions: retourne une liste contenant les deux solutions, la plus petite solution en première place """
Écrivez la signature et le corps de la fonction solveur, dont le but est de résoudre une liste d'équations du second degré. Une équation est représentée par la liste [a, b, c]. La fonction solveur doit retourner une liste. L'élément à l'indice i de la valeur de retour contient le résultat de la fonction solution appliquée sur l'équation située à l'indice i de l'input.
Pour réussir cette exercice, vous devez utiliser une list comprehension.
Voici un exemple de la valeur de retour de la fonction solveur :
>>> solveur([]) [] >>> solveur([[1, 1, -1], [4, 4, 1], [1, 2, 3], [-1, 2, 3]]) [[-1.618033988749895, 0.6180339887498949], [-0.5], [], [-1.0, 3.0]]
Une fois de plus, la Grosse Dame a bu tout le vin de la peinture des moines ivres et le Chevalier du Catogan n'est pas disponible pour la remplacer. L'accès à la salle commune des Gryffondor n'est pas gardée et les intentions des Serpentards sont mauvaises.
Nous avons besoin que vous conceviez un vérificateur de mot de passe pour combler le vide laisser par le départ de la Grosse Dame.
Créez une fonction portrait(right_password, entered_password) qui retourne True si les deux mots de passe sont identiques et False sinon.
Anonymous vient de vous engager sur le dark web pour une tâche dangereuse. Ils essayent de craquer un code depuis quelques jours mais ne sont arrivés à rien... pour le moment!
Ils veulent que vous construisiez une fonction qui analysera chaque caractère dans un code donné et que vous déterminiez sa nature. Le but est simple : ils ont l'intention d'utiliser les informations que vous leur fournirez pour trouver un pattern dans le code.
Créez une fonction extract(code) pour fournir des infos concernant la nature de chaque élément du code :
Par exemple, si le code 'AeB7' est donné en entrée, la fonction devrait produire 'vowel-up vowel-low consonant-up number' comme sortie. En général :
Exemple :
Avec le code '65AeBc7' la fonction devrait sortir 'number number vowel-upvowel-low consonant-up consonant-up number'.
Etant donné que votre travail était remarquable, Anonymous vous a à nouveau contacté avec une autre tâches risquée. Ils manquent de main d'oeuvre et aimeraient que traitiez les données que vous leur avez donné.
Ils veulent que vous construisiez une fonction qui transformera votre précédente sortie en quelque chose de plus simple et plus rapide à traiter. C'est à vous de voir comment transformer l'information en un pattern utilisable!
Créez une fonction treatment(data) pour transformer l'information que vous avez précédemment retourné en un pattern :
Chaque suite d'éléments communs devrait être indiqué par la nature de l'élément suivi de '*' et le nombre d’occurrence sans autre éléments entre.
Exemple:
Avec le code '66AeB7' votre précédente fonction sortirait 'number number vowel-up vowel-low consonant-up number'.
Avec cette sortie en entrée votre nouvelle fonction treatment sortirait la string suivante 'number*2 vowel-up*1 vowel-low*1 consonant-up*1 number*1'.
N'hésitez pas à utiliser autant de sous-méthodes que vous jugez nécessaires.
Les nombres premiers (https://en.wikipedia.org/wiki/Prime_number) sont des nombres avec les caractéristiques suivantes:
Des nombres premiers sont 2, 3, 5, 7, 11, 13, ...
Pour calculer les nombres premiers on peut utiliser le crible d'Eratosthène : pour chaque nombre successif, on vérifie si on peut le diviser par un des nombres premiers déjà trouvés. Si non, on peut ajouter le nombre à la liste. Ecrivez la fonction primes(max) qui retourne une liste de tous les nombres premiers jusque max (max inclus si max est un nombre premier). Si max est négatif ou zéro, la liste vide doit être retournée.
Pour limiter la complexité de la solution, decomposez votre solution en sous-problèmes comme nécessaire; utilisez des boucles for.
Vous travaillez pour une entreprise qui est active dans toute la Belgique. En tant que composant d'un système plus grand, l'entreprise a besoin d'outils qui permettent de rechercher les coordonnées des communes belges. Vous avez trouvé une liste des communes et leur coordonnées GPS en ligne et devez utiliser Python pour créer les outils demandés.
A l’issue de ce problème, chacun d’entre vous :
A l’issue de ce problème, le groupe tout entier :
La matière relative à cette mission est décrite dans les sections suivantes du syllabus en ligne :
Les questions à choix multiples de cette mission sont également accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session5_QCM
Dans cet exercice, nous étudions les listes de nombres entiers ordonnées de façon strictement croissante. Un exemple d'une telle liste est [-1,0,3,5]; la liste [-1,0,0,2] ne l'est pas (puisque 0 et 0 sont égales).
Étant donnée une liste de nombres entiers, comme [-2,0,3,4] ou [3,-2,0], écrivez une fonction def is_sorted(l) avec la spécification suivante:
def is_sorted ( l ): """ Retourne si la liste l est ordonnée de façon strictement croissante. Args: l: une liste de nombres entiers, positif ou négatif Retourne: Un booléen qui indique si la liste l est ordonnée de façon strictement croissante. """
Étant données deux listes ordonnées de façon strictement croissante, on veut calculer une nouvelle liste ordonnée des nombres entiers qui sont communs entre les deux listes. Par exemple, étant données les listes [-2,-1,0,1,2,3,4] et [0,1,2,5,6], on veut calculer la liste [0,1,2], qui contient les nombres entiers [0,1,2] qui sont communs entre les deux listes. Une première implémentation de cette idée est donnée ci-dessous.
def intersect ( l1, l2 ): """ Retourne une liste ordonnée des nombres entiers communs entre l1 et l2. Args: l1: une liste ordonnée de nombres entiers, positif ou négatif l2: une liste ordonnée de nombres entiers, positif ou négatif Retourne: Une liste ordonnée de nombres entiers communs entre l1 et l2. """ l = [] for e1 in range(len(l1)): for e2 in range(len(l2)): if e2 == e1: l.append ( e1 ) return l
Malheureusement, le code ne fonctionne pas encore correctement. Écrivez un test qui montre que le code n'est pas correct.
Donnée est une liste de coordonnées, comme par exemple:
coordonnees = [(0,1),(2,3),(0,1),(4,5),(1,2),(0,1),(1,1),(0,2),(1,1)]
Étudiez le code suivant:
coordonnees = [(0,1),(2,3),(0,1),(4,5)] def f ( v ): return v*v def increment ( l ): for i in range(len(l)): l[i][0] = f(l[i][0]) increment ( coordonnees ) assert coordonnees == [(0,1),(4,3),(0,1),(16,5)]
Malheureusement le code donne une erreur et ne passe pas le test. Corrigez une ligne de la fonction increment(l) de telle sorte que le code passe le test.
On représente les cours suivis par des étudiants en utilisant des listes imbriquées, comme suit:
[('LINFO1101', ['Jean', 'Pierre']), ('LINFO1110', ['Jean']),\ ('LINFO1111', ['Jean']), ('LINFO1112', ['Jacques', 'Pierre']),\ ('LINFO1113', ['Pierre'])]
Donnez un algorithme binary_search(course,list_of_courses) pour trouver tous les étudiants d'un cours donné dans cette structure de données. Copiez le code du cours et modifiez-le.
On peut appliquer l'algorithme de question 3 pour trouver les étudiants de plusieurs cours. Supposez que chaque fois que vous calculez middle, tu imprimes la valeur calculée pour middle. Dans ce cas, le nombre de valeurs imprimées pour middle correspond à la nombre de fois que la boucle while est exécutée. Combien de fois est-ce que la boucle est exécutée pour l'exemple suivant ?
La liste est:
[('LINFO1101', ['Jean', 'Pierre']), ('LINFO1110', ['Jean']),\ ('LINFO1111', ['Jean']), ('LINFO1112', ['Jacques', 'Pierre']), \ ('LINFO1113', ['Pierre'])]
Les cours donnés sont: LINFO1110, LINFO1112, LINFO1111, LINFO1114.
Pour cette mission, vous devez écrire des fonctions et tester leur bon fonctionnement. Comme dans les exercices de préparation, vous devez travailler à deux de cette façon: pendant qu'un étudiant écrit une fonction, l'autre développe la fonction de test correspondante. Lorsqu'une fonction est correctement spécifiée, on peut écrire les tests permettant de vérifier son bon fonctionnement sans connaître son code.
Dans cette mission vous allez créer plusieurs fonctions qui fonctionnent sur une liste de communes de la Belgique.
Téléchargez le fichier sorted_belgian_communes.py, qui contient une liste de toutes les communes de la Belgique ainsi que leurs coordonnées (selon une projection Mercator). Ecrivez toutes les fonctions demandées durant cette mission dans ce fichier.
Finalement, appliquez votre fonction à la liste all_communes.
Écrivez une fonction distance(commune1, commune2, all_communes) pour calculer la distance euclidienne entre deux communes dont les noms sont donnés. La distance euclidienne entre deux coordonnées (x1,y1) et (x2,y2) est:
Rappel: le module math contient une implémentation d'une fonction sqrt. Écrivez une fonction auxiliaire pour calculer la distance entre deux coordonnées (x1,y1) et (x2,y2).
De nouveau: ajoutez des spécifications pour toutes les fonctions, ainsi que des tests, dans une fonction test_distance().
Écrivez une fonction tour_distance(communes, all_communes) pour calculer la distance totale d'une tournée à travers toutes les communes dans la liste communes. La tournée commence à communes[0], va ensuite vers communes[1], communes[2], ..., communes[-1], pour finalement retourner à communes[0].
De nouveau: ajoutez des spécifications pour la fonction, ainsi que des tests, dans une fonction test_tour_distance().
Pour cette mission, vous devez soumettre votre fichiers sorted_belgian_communes.py et README.txt au serveur de soumissions de programmes du cours. Les fonctions et les testes doivent être dans le même fichier. Le fichier ne doit contenir que des fonctions (en plus de la variable all_communes). Votre fichier sorted_belgian_communes.py doit au moins contenir les fonctions :
verify_order(communes) coordinate(commune,all_communes) distance(commune1, commune2, all_communes) tour_distance(communes, all_communes)
Les questions ci-dessous sont des questions supplémentaires de Question 1 de la phase de préperation; ce sont des questions à faire sur papier.
Déterminez combien de fois la ligne de code if e2 == e1: est executée pour le cas de test suivant:
assert intersect ( list(range(100)), list(range(100)) ) == list(range(100))
On va essayer de résoudre le problème plus efficacement. Une idée est de parcourir les deux listes en même temps; pour chaque élément de la première liste, on regarde si on peut trouver l'élément dans la partie de la deuxième liste qu'on n'a pas encore parcouru. Cette idée a été mise en oeuvre dans la fonction suivante:
def intersect ( l1, l2 ): """ Retourne une liste ordonnée des nombres entiers communs entre l1 et l2. Args: l1: une liste ordonnée de nombres entiers, positif ou négatif l2: une liste ordonnée de nombres entiers, positif ou négatif Retourne: Une liste ordonnée de nombres entiers communs entre l1 et l2. """ l = [] p1 = 0 p2 = 0 while p1 < len(l1): while l1[p1] > l2[p2]: p2 += 1 if l1[p1] == l2[p2]: l.append ( p2 ) p1 += 1 return l
Malheureusement, le code ne fonctionne pas encore correctement.
Écrivez quelques testes qui permettent de découvrir que le code n'est pas correct.
Donnée est une liste de coordonnées. Par exemple:
l = [ ( 2.0, 5.0 ), ( 8.0, 12.0 ), ( 10.0, 40.0 ), (8.0, 50.0), (8.0, 50.0) ]
Nous voulons créer un dictionnaire pour identifier rapidement les valeurs y pour une x donnée. Pour l'exemple:
d = { 2.0: [ 5.0 ], 8.0: [ 12.0, 50.0, 50.0 ], 10.0: [ 40.0 ] }
Écrivez une fonction create_dict(l) qui crée cette dictionnaire (pas limité à cet exemple).
Donnée est une liste de coordonnées, comme dans l'exercice précédente. Nous voulons créer un dictionnaire pour identifier rapidement la valeur maximale Pour l'exemple:
d = {2.0: 5.0, 8.0: 50.0, 10.0: 40.0}
Écrivez une fonction create_dict_max(l) qui crée ce dictionnaire (pas limité à cet exemple).
def get_ordered_list ( l ): """ Retourne les chaînes de caractères dans la liste l dans l'ordre indiquée par la liste l L'ordre est déterminée par les nombres entiers dans la liste: pour chaque tuple e dans la liste l, le successeur est l[e[1]], si e[1] != None. Args: l: une liste de tuples, dont chacun se compose d'une chaîne de caractères et un nombre entier ou None; les nombres entiers définissent un ordre total sur les éléments de la liste. Retourne: Les chaines de caractères dans la liste l dans l'ordre indiqué par les nombres entiers. """
Nous avons la structure de données suivante pour stocker la relation entre étudiants et cours qu'ils ont suivis:
student_courses = [ ( "Jean", "LINFO1111" ), ( "Jean", "LINFO1101"), \ ( "Pierre", "LINFO1101" ), ( "Pierre", "LINFO1112" ) ]
Écrivez le code pour ajouter un tuple ("Jacques", "LINFO1112") à student_courses.
Créez une fonction students(course, student_courses) qui, pour un cours donné, renvoie une liste des étudiants qui suivent le cours. Par exemple, si on appelle la fonction avec "LINFO1101" et la liste de la question 3 comme paramètres, le résultat doit être ["Jean", "Pierre"].
On présume qu'il n'y a pas d'ordre dans la liste student_courses.
Écrivez une fonction remove_student(student,student_courses) qui, pour un étudiant donné présent dans une liste donnée, retourne la liste sans les tuples qui concernent cet étudiant.
Par exemple, si on appelle la fonction avec "Jean" et la liste de la question 1 comme paramètres le résultat doit être :
[ ( "Pierre", "LINFO1101" ), ( "Pierre", "LINFO1112" ) ]On présume qu'il n'y a pas d'ordre dans la liste student_courses.
Écrivez une fonction nest_students(student_courses) qui, pour chaque cours, crée une liste imbriquée des étudiants qui suivent le cours. Sur l'exemple précédent, la fonction doit retourner cette structure de données:
[('LINFO1101', ['Jean', 'Pierre']), ('LINFO1111', ['Jean']), ('LINFO1112', ['Pierre'])]
La liste doit être triée par ordre de cours. Utilisez le code de question 4 et de question 5 comme inspiration. Réfléchissez sur la question: comment est-ce qu'on peut ajouter un élément dans une liste imbriquée qui vient d'être créée?
Vous faites partie de l'organisation des 5 et 10 miles de Louvain-la-Neuve. Mais le système est tombé en panne juste avant le départ.
Il y avait deux étudiants pour prendre note des arrivées des coureurs. Heureusement, il n'y avait que deux lignes à compter. Votre job consiste à faire une liste de ces deux listes pour avoir un classement général.
Les listes que vous recevez sont une succession de ['name', time] avec le temps dans un ordre croissant. Créez une fonction merge(first_list, second_list) qui retournera une liste qui a les éléments des deux listes dans l'ordre.
En sciences informatiques, un algorithme de tri est un algorithme qui place les éléments d'une liste dans un certain ordre. Les ordres les plus utilisés sont l'ordre numérique et l'ordre lexicographique. Un tri efficace est important pour optimiser l'utilisation d'autres algorithmes (tels que les algorithmes de recherche ou de fusion) qui ont besoin d'une liste triée en entrée ; c'est aussi souvent utile pour la canonicalisation des données et pour produire des sorties lisibles par les humains. Plus formellement, la sortie doit satisfaire deux conditions :
Une fois de plus, c'est l'heure de la cérémonie de la répartition . Les premières années attendent en rangs devant un vieux chapeau, à la fois anxieux et excités. Le directeur fait un long discours pour les accueillir et laisse la place à un mystérieux intervenant.
Tous les premières années sont ébahis lorsque le Choixpeau Magique brise le silence en chantant l'une de ses célèbres chansons.
Cependant, le choixpeau en fait un peu trop et rencontre quelques problèmes. Il perd sa voix et ne sera pas en état d'assurer la suite de la cérémonie. Heureusement, nous avons toujours accès aux connaissances des fondateurs et nous pourrons répartir les élèves avec votre aide.
Créez une fonction house_designation(student_qualities) qui va retourner une liste avec les noms des quatres maisons, la première étant celle où l'étudiant devrait aller et la dernière, celle qui convient le moins à l'étudiant. Pour décider de cette répartition, l'étudiant devrait être placé dans la maison où il a le plus d'affinités, c'est-à-dire, la maison avec laquelle il partage le plus de qualités. Si deux maisons sont à égalité, on les retourne dans l'ordre dans lequel elles sont placées dans les connaissances des fondateurs.
Vous allez développer un programme qui permets l’exécution de certaines tâches. Très fréquemment, un utilisateur doit faire les tâches suivantes :
Les exercices préparatoires vous permettent de completer certains éléments de cette mission.
A l’issue de ce problème, chacun d’entre vous sera en mesure d’exploiter les notions suivantes :
La matière relative à cette mission est décrite dans les sections suivantes du syllabus en ligne :
Il peut être utile de relire:
Les questions à choix multiples de cette mission sont également accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session6_QCM
Considérez le code suivant:
file = open ( "file.txt", "r" ) for line in file: print ( line.strip ().split (",") ) file.close ()
Le contenu du fichier file.txt est le suivant:
X | , | X | , | \n | , | X | \n | X | X | , | , | X |
Expliquez le résultat de code.
Dans les exercices suivants, vous pouvez supposer que les fichiers à lire existent et qu'il ne faut pas traiter les erreurs.
On donne des listes contenant des paires de coordonnées comme [(0.5,0.5),(0.1,0.3),(0.4,0.5)].
0.5,0.5 0.1,0.3 0.4,0.5
Considérez l'utilisation de méthodes de string telles que : * split * strip
Voyez la documentation de ces méthodes dans le manuel de référence de Python.
Dans cet exercice, les erreurs possibles lors de la lecture ou de l'écriture d'un fichier peuvent être ignorées.
Considérez le code suivant.
command = input ( "Enter your command: " ) parameters = command.split () if parameters[0] == "divide": print ( "The value of your division is: " + str ( float(parameters[1])/float(parameters[2]))) elif parameters[0] == "showfile": file = open ( parameters[1] ) print ( file.read () ) file.close () else: print ( "Command not recognized")
Dans la mission, vous devrez lire un fichier qui contient des mots avec leur fréquence d'occurrence. Par exemple:
this,5146 that,10790 these,1575 the,69975 those,864
Identifiez les différentes erreurs que l'on pourrait rencontrer en lisant ce fichier. Il n'est pas nécessaire d'identifier les noms exacts des erreurs; il suffit de les décrire en mots.
Dans cette mission nous allons développer un simple assistant qui fonctionne sur la console Python. L'utilisateur doit être capable de donner des commandes simples, pour lesquelles l'outil doit répondre avec une réponse pertinente. L'objective dans cette mission est de montrer que l'outil continue à fonctionner même si l'utilisateur donne des commandes incomplètes ou incorrectes.
Les commandes qui doivent être supportées sont:
Par exemple, l'outil doit supporter cette séquence de commandes :
Welcome to your personalized tool! > file all-words.dat Loaded all-words.dat > info 11304 lines 1330218 caracters > words Read file as list of words > search presbytaerial Presbytaerial is not in the list of words > search presbyterial Presbyterial is in the list of words > exit
Si l'utilisateur spécifie un fichier autre qu'une liste de mots, ou si l'utilisateur cherche un mot sans avoir spécifié une liste de mots, l'outil doit produire un message d'erreur et continuer à fonctionner.
Le format des listes de mots est spécifié dans les exercices préparatoires. Pour éviter tout problème avec l'encodage des caractères accentués, votre liste de mots vérifiera des mots en anglais (sans accents).
Note: dans cet exercice, la liste de mots ne doit pas encore être mise en oeuvre à l'aide de dictionnaires Python, ce qui sera le sujet de la mission de la semaine prochaine.
La phase de réalisation de cette mission est moins guidée que les précédentes; vous devez choisir vous-même la subdivision de votre programme en fonctions.
Néanmoins, on vous suggère de procéder comme suit:
Pour vous aider, vous avez à disposition le fichier all-words.dat qui contient une centaine de milliers de mots de la langue anglaise ainsi que le nombre d'occurrences de ce mot. Cette liste de mots a été construit en se basant sur deux sources d'information : les mots utilisés par ispell (http://wordlist.sourceforge.net/) et la Global Service List (http://jbauman.com/gsl.html), c'est-à-dire les 2000 mots les plus fréquemment utilisés par un personne qui apprend l'anglais. Ce fichier contient les mots en minuscules et n'est pas trié dans l'ordre alphabétique. La première ligne contient le nombre de mots présents dans le fichier.
La mission de cette semaine n'aura pas de correction automatique donc soyez bien attentifs pendant la séance de feedback.
Vous devrez aussi écrire des tests de vos fonctions. Si assistant.py est le fichier qui contient votre code, nous attendons que vous écrivez un deuxième fichier test.py dans lequel vous faites des appels aux fonctions que vous avez fournies. Il est décrit dans le syllabus théorique comment faire des tests quand on a plusieurs fichiers (Section Tests).
Vous devez soumettre un fichier assistant.py avec le code de votre outil et un fichier test.py avec vos tests. N'oubliez pas d'ajouter dans ce fichier des spécifications (docstrings) et aussi d'écrire un fichier README.
Écrivez un outil qui fait le suivant:
Séparez le programme en fonctions, avec au moins
Pour simplifier l'exercice, il n'est pas nécessaire de traiter les erreurs.
Écrivez une fonction table(filename_in, filename_out, width) qui crée pour un fichier donné un autre fichier dans lequel toutes les lignes ont été mises dans un tableau. Pour cet exemple:
Mons Bruxelles Ottignies Jean Charles
le résultat avec width = 8 doit être:
Mons Bruxelle Ottignie Jean Cha |
Remarquez qu'il y a un espace avant et après chaque ligne. Considérez l'utilisation des méthodes suivantes de string:
Consultez la documentation de Python si vous ne connaissez pas encore ces méthodes. Vous pouvez présumer que le fichier filename_in existe.
Toute votre vie vous vous êtes demandé "Où cette stupide chouette a-t-elle égaré ma lettre ?", "Quand irais-je enfin à Poudlard ?" ou même à la fin "Suis-je un Cracmol ?". Ne vous inquiétez pas!
Poudlard vous a enfin contacté pour une tâche importante. Même si vous êtes trop vieux pour apprendre la sorcellerie, ils ont de la chance parce que vous avez appris une différente sorte de magie : la programmation.
Ils ont décidé de moderniser un peu leurs services d'admission et veulent que vous créiez un programme qui sera capable de remplir un fichier (template d'un lettre d'admission) avec le nom de l'étudiant. De cette manière, ils pourront réduire le coût en plumes et réduire la charge de travail des elfes!
Implémentez la fonction write(letter_template, name) en Python.
N'oubliez pas de lever une exception si elle se produit.
Les règles du Quidditch ont été établie en 1750 par le Département des jeux et sports magiques. Et il n'est dit nul part que l'arbitre ne peut recevoir un petit coup de main.
Madame Bibine est plutôt occupée à regarder pour le boutenchoc, le croc-en-manche, le hochequeue et tout un tas d'autres vilaines fautes de Quidditch. Donc elle a pensé que vous pourriez écrire une programme qui déciderait le vainqueur d'un match en se basant sur la liste des points.
La liste des scores serait fournie dans un fichier. Le contenu de ce fichier suivrait le format suivant :
S'il y a une erreur, pensez à lever une exception.
Rappelez-vous qu'attraper le vif d'or en plus de rapporter 150 points marque la fin du match.
Implémentez la fonction referee(score_file) en Python.
Pour votre prochain gros jeu, Dieu de la Destruction Massive : Edition Jeu du Siècle, vous devez créer une fonction pour charger et sauvegarder les données du joueur.
Vous devez créer deux fonctions : une pour sauvegarder les données et une pour les charger. Vous êtes libres d'enregistrer les données comme vous le souhaitez dans le fichier, mais placer un entier par ligne est probablement la méthode la plus simple. S'il n'y a pas de fichier à charger quand vous voulez utiliser le fontion load_data (par exemple, le joueur commence un nouveau jeu), vous devez lever une FileNotFoundError.
Les deux fonctions auront ces définitions :
#sauvegarder les 4 entiers dans le fichier nommé filename def save_data(filename, life, mana, position_x, position_y) #retourne un tuple contenant les valeurs (life, mana, position_x et position_y précédemment sauvegardées def load_data(filename)
Le but de cette mission est de développer un outil qui permet un utilisateur de chercher répétitivement dans un fichier de texte: pour des mots donnés, l'outil va imprimer les phrases dans lesquelles tous les mots donnés sont présents. Pour assurer que l'outil ne prend pas trop de temps pour déterminer ces phrases, on va construire un index des mots présents dans les phrases des documents. On utilisera les dictionnaires pour stocker l'index.
La matière relative à cette mission est décrite dans les sections suivantes du syllabus en ligne :
Les questions à choix multiples de cette mission sont également accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session7_QCM
Considérez le code suivant:
codes = {"Bruxelles" : [1000,1020,1030], "Louvain-la-Neuve" : [1348], "Wavre": [1300,1301]}
Les morceaux de code ci-dessous sont executés chacun après ce code. Décrivez ce qui se passe pour chacun des cas.
print(codes["Bruxelles"])
print(codes["Mons"])
print(codes[1000])
print(codes.get("Mons",[]))
codes["Liege"] = [4000] print(codes)
codes["Bruxelles"].append(1040) print(codes)
codes.get("Bruxelles",[]).append(1050) print(codes)
codes.get("Arlon",[]).append(8362) print(codes)
if "Bruxelles" in codes: print("Found!") else: print("Not found!")
if 1000 in codes: print("Found!") else: print("Not found!")
for x in codes: print(x)
for x in codes: print(codes[x])
for x in codes.items(): print(x)
for x, y in codes.items(): y = y + [2000] print(codes)
for x, y in codes.items(): y.append(2000) print(codes)
for x, y in codes.items(): x = x + "*" print(codes)
Considérez le code suivant:
def mot_ligne(ligne): d = {} for mot in ligne: d[mot] = 1 return d
Quelle est la taille du dictionnaire résultant des appels suivants ? Pourquoi ?
Écrivez une fonction avec la spécification suivante:
def create_index ( list_of_words ): """ crée un index pour une liste de chaînes de caractères. L'index se compose d'un dictionnaire dans lequel pour chaque chaîne de caractères dans list_of_strings on retrouve une liste des positions où l'on retrouve cette chaîne de caractères. Par exemple, pour la liste ["the","galaxy","and","the","universe","are","the","same"] Le résultat est {"the":[0,3,6],"galaxy":[1],"and":[2],"universe":[4], \ "are":[5],"same":[7]} Args: list_of_words: une liste de chaînes de caractères Retourne: un dictionnaire avec pour chaque mot dans la liste, une liste des positions de cette chaîne de caractères dans la liste """
Étant donnée:
Par exemple,
l = [ [ 0, 2, 4 ], [ 4, 1, 0 ] ] d = { (0,1): 2, (0,2): 4, (1,0): 4, (1,1): 1 }
Écrivez une fonction equal(l,d) qui détermine si d contient les même valeurs pour chaque élément de l. (Nous permettons que d soit plus large que l.)
Étant donné une structure de données comme la suivante:
Écrivez une fonction get_country(l,name) qui, pour le nom d'une ville name et une structure de données l du format illustré dans l'exemple, retourne le nom du pays dans lequel la ville est localisée. La fonction retourne None si la ville n'est pas dans l.
Le but de cette mission est de contribuer à un outil qui permet un utilisateur de chercher répétitivement dans un fichier de texte.
Il faut implementer les fonctions suivantes dans un fichier search.py et vérifier que ces fonctions sont correctes:
La fonction readfile(filename) avec la spécification suivante:
def readfile(filename): """ Crée une liste des lignes contenues dans un fichier dont le nom est ``filename`` Args: filename: le nom d'un fichier de texte Retourne: une liste dans laquelle chaque ligne du fichier filename est un élément. Si filename n'existe pas, la fonction retourne une liste vide. """
La fonction get_words(line) avec la spécification suivante:
def get_words(line): """ Pour une chaîne de caractères donnée, retourne une liste des mots dans la chaîne en minuscules et dans l'ordre d'apparence dans le texte. La ponctuation et les caractères non-alphabétiques doivent être ignorés et retirés des mots. Par exemple : - Pour la chaîne de caractères : "Turmoil has engulfed the Galactic Republic. The taxation of trade routes to outlying star systems is in dispute." Le résultat est : ["turmoil", "has", "engulfed", "the", "galactic", "republic", "the", "taxation", "of", "trade", "routes", "to", "outlying", "star", "systems", "is", "in", "dispute" ] - Pour la chaîne de caractères : "These aren't the droids you're looking for." Le résultat est : ['these', 'arent', 'the', 'droids', 'youre', 'looking', 'for'] Un caractère est considéré comme une ponctuation ou un caractère non-alphabétique si ce n'est pas une lettre, selon la fonction string.isalpha(). Args: line: une chaîne de caractères. Retourne: une liste des mots dans la chaîne, en minuscules, et sans ponctuation. """
Ici, vous pouvez utiliser la méthode string.isalpha(); un exemple de l'utilisation de cette méthode se trouve ci-dessous:
text = "a.b" r = "" for c in text: if c.isalpha(): r += c print(r) # "ab"
La fonction create_index(filename) avec la spécification suivante:
def create_index(filename): """ crée un index pour le fichier avec nom ``filename``. L'index se compose d'un dictionnaire dans lequel pour chaque mot du fichier ``filename`` on retrouve une liste des indices des lignes du fichier qui contiennent ce mot. Par exemple, pour un fichier avec le contenu suivant: While the Congress of the Republic endlessly debates this alarming chain of events, the Supreme Chancellor has secretly dispatched two Jedi Knights. Une partie de l'index, representé comme dictionnaire, est: {"while": [0], "the": [0,1], "congress": [0], \ "of": [0,1], "republic": [0], ... , "jedi": [2], ...} Args: filename: une chaîne de caractères Retourne: un dictionnaire avec pour chaque mot du fichier (en minuscules) la liste des indices des lignes qui contiennent ce mot. """
Cette fonction doit utiliser les fonctions get_words et readfile.
La fonction get_lines(words,index) avec la spécification suivante:
def get_lines(words, index): """ Détermine les lignes qui contiennent tous les mots indexes dans ``words``, selon l'index ``index``. Par exemple, pour l'index suivant: index = {"while": [0], "the": [0,1], "congress": [0], \ "of": [0,1], "republic": [0], ... , "jedi": [2], ...} La fonction retourne get_lines(["the"], index) -> [0, 1] get_lines(["jedi"], index) -> [2] get_lines(["the", "of"], index) -> [0, 1] get_lines(["while", "the"], index) -> [0] get_lines(["congress", "jedi"], index) -> [] get_lines(["while", "the", "congress"], index) -> [0] Args: words: une liste de mots, en minuscules index: un dictionnaire contenant pour mots (en minuscules) des listes de nombres entiers Retourne: une liste des nombres des lignes contenant tous les mots indiqués """
Commencez par faire cette fonction uniquement pour les listes avec un mot; dans ce cas, l'outil marche au moins quand l'utilisateur spécifie un seul mot. Essayez de modifier cette fonction pour les listes plus longues ensuite.
Plusieurs approches sont possible pour calculer le résultat de get_lines() pour des listes de mots plus longues. Une possibilité est de traverser la liste associé au premier mot, et de vérifier si on trouve dans ces lignes aussi les autre mots, en utilisant l'index de chaque mot.
De nouveau, les fonctions ci-dessus doivent être mises en oeuvre dans un fichier search.py.
L'outil est implementé dans un fichier utility.py, qui importe le fichier search.py. Voici le code de utility.py, que vous pouvez soumettre sans le modifier:
import search filename = input("Spécifiez le nom de fichier: ") index = search.create_index(filename) while True: words = input("Spécifiez les mots a rechercher, en utilisant des espaces entre les mots: ") lines = search.get_lines(words.strip().split(), index) print("Les mots se retrouvent dans ces lignes:") for line in lines: print(line)
Autrement dit, après avoir demandé le nom d'un fichier, dans une boucle, l'interface demande à l'utilisateur de donner une liste de mots; chaque fois, l'outil cherche les lignes dans lesquelles les mots spécifiés sont présents, et imprime ces lignes. Votre tâche principale est de vous assurer que l'outil fonctionne correctement, en mettant en oeuvre les fonctions dans le fichier search.py.
Pour vous aider, vous trouverez un exemple de texte episodeIV_dialogues.txt.
Créez les fonctions dans l'ordre spécifié. Si vous n'arrivez pas à terminer toutes les fonctions, soumettez les fonctions que vous avez réussi à terminer.
Pour assurer que l'outil marche correctement, vous devez ajouter des tests pour vérifier que les fonctions sont correctes; par exemple, les tests pour la fonction get_words doivent être mis dans une fonction test_get_words. Puisque vous devez tester une fonction qui lit un fichier, créez des petits fichiers pour tester cette fonction; il faut soumettre ces fichiers de texte aussi.
Les tests doivent être mis dans un fichier test.py qui importe search.py. Un petit exemple du contenu du fichier test.py est:
import search def test_get_words(): assert search.get_words("Turmoil has engulfed the Galactic Republic.") == ["turmoil", "has", "engulfed", "the", "galactic", "republic"], "Petit exemple donné" test_get_words()
Si vous le souhaitez, vous pouvez étendre l'outil même, par exemple, pour montrer les lignes au lieu des nombres des lignes. Dans ce cas vous pouvez modifier le code du fichier utility.py. Indiquez ceci dans le commentaire de utility.py.
Pour cette mission, vous devez soumettre:
Lors de la dernière session du club de duel, les sabliers comptant les points de chaque maison ont été détruits même un reparo n'a rien pu faire et la célébration de la Coupe des Quatre Maisons arrive à grands pas!
Heureusement, Rusard, qui ne fait pas confiance à la magie, a gardé les comptes de tous les accomplissements perpétrés par les étudiants. Il vous a fourni un dictionnaire associant chaque élève à sa maison et un parchemin avec tous leurs gains.
La liste des scores est donnée dans un fichier. Le contenu de ce fichier suit le format suivant :
Merci de retourner le nom de la maison gagnante, dans le cas d'un ex-aequo : retournez une liste des meilleures maisons.
S'il y a une erreur, levez une exception.
Implémentez la fonction winning_house(scroll) en Python.
Vous avez déjà la liste des étudiants triés par maison à votre disposition :
students = {'gryffindor': ['Harry', 'Hermione', 'Ron', 'Ginny', 'Fred', ' Georges', 'Neville'], 'ravenclaw': ['Cho', 'Luna', 'Sybill', 'Marcus', 'Marietta', 'Terry', 'Penelope'], 'hufflepuff': ['Pomona', 'Zacharias', 'Teddy', 'Cedric', 'Nymphadora', 'Newton', 'Justin'], 'slytherin': ['Malfoy', 'Severus', 'Dolores', 'Horace', 'Blaise', 'Pansy', 'Bellatrix']}
Anonymous a été épaté par votre travail et a décidé de vous faire confiance pour l'analyse de toutes les données qu'ils ont intercepté.
Avec l'aide des deux fonctions que vous avez déjà créées, vous allez transformer chaque ligne de données en un pattern et extraire le nombre d’occurrences présentes dans le fichier.
Créez une fonction collect(data) pour lire le fichier, extraire les patterns et les enregistrer dans un dictionnaire avec leurs occurrences.
S'il y a une erreur, levez une exception.
Rappel:
Après la troisième guerre mondiale, la planète est laissée dans un état post-apocalyptique. Vous êtes l'un des seuls survivants et vous cherchez un peu de compagnie. Mais vous ne pouvez pas trop swiper sur Tinder vu que le réseau est mort..
Heureusement votre meilleur ami est avec vous... Votre ordinateur (oui, ça craint!) Avec son aide, aide vous allez pouvoir entrer en contact avec le reste du monde. Puisque vous avez un dictionnaire Morse enregistré sur votre machine (Matt Damon avait bien une table ASCII avec lui dans "Seul sur Mars" , donc c'est pas si absurde), vous allez l'utiliser pour traduire votre texte et l'émettre grâce à une vieille radio.
Notez que si vous devez essayer de traduire un caractère non-enregistré, vous devez lever une exception TypeError.
Implémentez la fonction translate(data) en Python.
Avec data comme chaine de caractère que vous voulez encoder en Morse et un dictionnaire morse utile pour faire les traductions.
morse = { "A" : ".-", "B" : "-...", "C" : "-.-.", "D" : "-..", "E" : ".", ... }
Votre tinder par radio a bien fonctionné et vous pouvez désormais discuter avec beaucoup de gens intéressants. Encore plus intéressant, une merveilleuse créature vient de vous contacter et est parvenue à vous envoyer une image à travers des points et des espaces (Dieu bénisse le code Morse).
Vous voulez vraiment lui parler ainsi qu'à vos autres futurs matchs mais vous venez de réaliser que vous n'avez jamais bien étudier les langues étrangères. Heureusement, vous avez des dictionnaires sur votre ordinateur (qui a apparemment téléchargé l'entierté d'internet). Vous devez simplement coder un traducteur!
Notez que si un mot que vous voulez traduire n'est pas dans le dictionnaire, vous devez laisser le mot dans son langage original.
Exemple:
"I'm fond of Dean" deviendrait en français avec le dictionnaire fr: "je suis amoureux de doyen" Notez qu'on ne s'attend pas à ce que vous donniez des traductions exactes mais bien une traduction mot par mot. De plus, les clés sont enregistrées en minuscules dans le dictionnaire.
Implémentez la fonction translate(data, lan) en Python.
Avec data comme la chaine de caractère que vous souhaiter traduire et les dictionnaires nommés selon lan utilisable pour faire les traductions dans le langage ciblé.
Vous et vos amis vous prêtez souvent de l'argent. Plutôt que d'utiliser une application spéciale pour se rappeler qui doit combien d'argent et à qui, vous décidez de faire votre propre programme python pour réaliser cette tâche.
Spécifiquement, vous aimeriez pouvoir:
Notez que de l'argent prêté à quelqu'un doit être emprunté. En d'autres termes, si Woody a prêté 3€ à Buzz, votre programme devrait dire que Buzz doit 3€ à Woody et que Woody doit -3€ à Buzz.
Pour faire cela, vous allez utiliser un dictionnaire de dictionnaires appelé borrowed_money, indexé par le nom des personnes (comme des strings). Le premier index sera le nom de "l'emprunteur"; le deuxième, celui du "prêteur".
Par exemple, si Woody a prêté 3€ à Buzz, votre dictionnaire devrait être comme suit:
borrowed_money[\"Buzz\"][\"Woody\"] == 3 # Lisez \"Buzz doit 3€ à Woody\" borrowed_money[\"Woody\"][\"Buzz\"] == -3
Par conséquent, vous pouvez obtenir un dictionnaire qui contient tout l'argent que Buzz emprunte:
borrowed_money[\"Buzz\"] == {\"Woody\": 3, \"Hamm\": 60, \"Rex\": -5}
Faites une fonction give_money(borrowed_money, from_person, to_person, amount) qui sera appelée quand from_person donne amount € à to_person (soit parce que from_person prête de l'argent to_person, ou bien parce qu'il rembourse de l'argent qu'il a emprunté). Si une des deux personnes n'est pas déjà une clé dans le dictionnaire, elle doit y être ajoutée. Vous devez lever une ValueError dans le cas où quelqu'un essaye de se donner de l'argent à lui-même.
Faites une autre fonction total_money_borrowed(borrowed_money) qui retourne le montant total d'argent emprunté en ce moment (c'est-à-dire, la somme des montants positifs se trouvant dans le dictionnaire).
Note: vous devez lever une ValueError``*si l'un des arguments passé à ces fonctions est invalide (c'est-à-dire si les noms ne sont pas de strings, si* ``borrowed_money n'est pas un dictionnaire ou si le montant d'argent n'est pas un integer ou un float). Vous pouvez tester si une variable est du bon type des manières suivantes :
variable = 5 type(variable) == int # retourne True # OR isinstance(variable, int) # retourne True
Enfin, implémentez l'exemple où Mark prête 2 000 000 € à Bill et Steve, Serguei prête 5 000 000 € à Bill, Bill prête 6 000 000 € à Larry et enfin, Larry prête 5,5 € à Linus. Ensuite, Steve rembourse Mark. Utilisez la variable borrowed_money.