Nouveau concept, de temps en temps, je vais proposer un exercice à faire en Python, vous postez vos solutions, et j’en posterai une le lendemain.
Pas de pression, c’est pour le fun.
Les solutions dans un autre langage sont bienvenues, mais privilégiez Python si vous avez le choix, c’est quand même le but.
Postez votre code sur un pastebin ou ailleurs avec un lien en commentaire, pas le code directement dans les commentaires.
Exercice du jour :
Un script qui attend un fichier en paramètre, l’ouvre, et trouve toutes les positions de chaque mot.
Le script doit prendre en compte les apostrophes, supprimer la ponctuation, et normaliser la casse et les caractères spéciaux des mots.
Le résultat doit afficher une liste à de mots avec leurs positions ordonnée par le nombre d’apparition, ou en cas d’égalité, par ordre naturel des positions.
Aucune gestion d’erreur n’est demandée.
Par exemple si j’ai un fichier contenant :
« La marche des vertueux est semée d’obstacles qui sont les entreprises égoïstes que fait sans fin surgir l’œuvre du Malin. Béni soit-il l’homme de bonne volonté qui, au nom de la charité, se fait le berger des faibles qu’il guide dans la vallée d’ombre, de la mort et des larmes, car il est le gardien de son frère et la providence des enfants égarés. J’abattrai alors le bras d’une terrible colère, d’une vengeance furieuse et effrayante sur les hordes impies qui pourchassent et réduisent à néant les brebis de Dieu. Et tu connaîtras pourquoi mon nom est l’éternel quand sur toi s’abattra la vengeance du Tout-Puissant ! »
Ça fait des années que je répète ça. L’enfoiré qui l’entend, il meurt aussitôt. J’avais jamais cherché à comprendre, je trouvais seulement que ça en jetait de dire ça avant de flinguer un mec. Et puis ce matin, j’ai vu quelque chose qui m’a fait réfléchir. D’un seul coup, je me dis, ça pourrait bien vouloir dire que tu es l’œuvre du malin, et que l’homme vertueux c’est moi, et que mon joli 9 mm ce serait mon protecteur, mon berger dans la vallée de l’angoisse et des larmes. Ou encore mieux, c’est moi le berger et toi l’homme vertueux, et c’est le monde qui est l’œuvre de Lucifer. Qu’est-ce que tu dis de ça ? Mais rien de tout ça n’est juste. Ce qui est vrai, c’est que tu es le faible et que je suis la tyrannie des méchants. Et moi j’essaie, Ringo, au prix d’un effort harassant, de protéger les faibles.
On appelle le script ainsi :
python ton_script.py ton_fichier.txt |
Et il affiche ceci :
- marche: 1 - semee: 5 - obstacles: 7 - sont: 9 - entreprises: 11 - egoistes: 12 - sans: 15 - fin: 16 - surgir: 17 - beni: 22 - soit: 23 - bonne: 28 - volonte: 29 - charite: 35 - se: 36 - guide: 44 - ombre: 49 - mort: 52 - car: 56 - gardien: 60 - son: 62 - frere: 63 - providence: 66 - enfants: 68 - egares: 69 - abattrai: 71 - alors: 72 - bras: 74 - terrible: 77 - colere: 78 - furieuse: 82 - effrayante: 84 - hordes: 87 - impies: 88 - pourchassent: 90 - reduisent: 92 - neant: 94 - brebis: 96 - dieu: 98 - connaitras: 101 - pourquoi: 102 - eternel: 107 - quand: 108 - s: 111 - abattra: 112 - puissant: 117 - annees: 121 - repete: 124 - enfoire: 127 - entend: 130 - meurt: 132 - aussitot: 133 - avais: 135 - jamais: 136 - cherche: 137 - comprendre: 139 - trouvais: 141 - seulement: 142 - en: 145 - jetait: 146 - avant: 150 - flinguer: 152 - mec: 154 - puis: 156 - matin: 158 - ai: 160 - vu: 161 - quelque: 162 - chose: 163 - m: 165 - reflechir: 168 - seul: 171 - coup: 172 - me: 174 - pourrait: 177 - bien: 178 - vouloir: 179 - joli: 199 - mm: 200 - serait: 202 - protecteur: 204 - angoisse: 212 - ou: 216 - encore: 217 - mieux: 218 - monde: 233 - lucifer: 239 - mais: 248 - rien: 249 - n: 253 - juste: 255 - vrai: 259 - faible: 266 - suis: 270 - tyrannie: 272 - mechants: 274 - essaie: 278 - ringo: 279 - prix: 281 - effort: 284 - harassant: 285 - proteger: 287 - malin: 21, 187 - au: 31, 280 - nom: 32, 104 - faibles: 41, 289 - qu: 42, 240 - dans: 45, 207 - vallee: 47, 209 - larmes: 55, 215 - une: 76, 80 - vengeance: 81, 114 - sur: 85, 109 - toi: 110, 225 - tout: 116, 251 - dire: 148, 180 - dis: 175, 245 - es: 183, 264 - vertueux: 3, 192, 228 - oeuvre: 19, 185, 237 - du: 20, 115, 186 - homme: 26, 191, 227 - berger: 39, 206, 223 - a: 93, 138, 166 - un: 153, 170, 283 - moi: 195, 221, 276 - les: 10, 86, 95, 288 - fait: 14, 37, 119, 167 - il: 24, 43, 57, 131 - j: 70, 134, 159, 277 - tu: 100, 182, 244, 263 - mon: 103, 198, 203, 205 - je: 123, 140, 173, 269 - ce: 157, 201, 242, 256 - c: 193, 219, 230, 260 - d: 6, 48, 75, 79, 169, 282 - le: 38, 59, 73, 222, 232, 265 - des: 2, 40, 54, 67, 120, 214, 273 - qui: 8, 30, 89, 128, 164, 234, 257 - ca: 118, 125, 144, 149, 176, 247, 252 - la: 0, 34, 46, 51, 65, 113, 208, 271 - que: 13, 122, 143, 181, 189, 197, 243, 262, 268 - l: 18, 25, 106, 126, 129, 184, 190, 211, 226, 236 - est: 4, 58, 105, 194, 220, 231, 235, 241, 254, 258, 261 - de: 27, 33, 50, 61, 97, 147, 151, 210, 238, 246, 250, 286 - et: 53, 64, 83, 91, 99, 155, 188, 196, 213, 224, 229, 267, 275
on peut le faire en perl ? :-) #perlgolf #Spotted
Euh, désolé si j’suis con, mais ça veux dire qu’on considère les apostrophes comme des espaces (“c’est” = 2 mots) ou comme un caractère (“c’est” = 1 mot).
Dans l’exemple c’est la première hypothèse mais à la lecture j’avais compris la deuxième.
vu le résultat escompté je dirai que oui ‘ = espace (puisqu’on a du l, c, d tout seul dans le resultat final)
Bonjour,
Je considère que 9 est un mot, d’où le décalage de 1 après «9 mm» par rapport à ce que tu obtiens
Je ne formate pas la sortie pour mettre ma liste avec des virgules parce-que j’ai pas envie.
http://pastebin.com/U5uxY2SH
@zanguu : “c’est” est une contraction de deux mot : “cela est”, donc c’est bien deux mots. Les apostrophes ont je crois été inventé pour pallier syntaxiquement à l’évolution de la langue orale.
@bob: bon usage du defaultdict.
@ Sam
Le defaultdict est une structure de données ultra-pratique, c’est ma préférée.
Pour le nettoyage des caractères (que j’ai torché à la gros porc), je pense que la fonction slugify de django serait un bon départ.
Je voudrai bien “une explication de texte” de la ligne 40 de http://pastebin.com/U5uxY2SH parce que là ok c’est un beau oneliner mais ca fait mal au crane à comprendre :)
@foxmask: La clé du dictionnaire est un tupple (len_mot, mot). Ici le dictionnaire est parsé selon les clés triées, le critère de tri étant ce tupple, donc de la plus petite longueur à la plus longue.
J’ai bon ?
Est-il possible de supprimer le 1er post (nom de Foxmask écorché) ?
@frodon1
t’as bon :)
@foxmask
l’itérateur dictword.iteritems() renvoie à chaque itération la paire clé-valeur notée (k,v).
»»» for item in dictword.iteritems():
print item
('jetait', [146])
('a', [93, 138, 166])
('brebis', [96])
('larmes', [55, 216])
...
la lambda fonction crée à partir de cette paire une clé notée key :
»» f = lambda (k,v):(len(v),v)
»» f(('jetait', [146]))
(1, [146])
»» f(('a', [93, 138, 166]))
(3, [93, 138, 166])
La fonction sorted() prend pour argument l’itérateur ainsi que la clé key constituée par la lambda fonction pour faire le tri.
Si des gens veulent s’amuser : http://www.checkio.org
ok ; j’avais pas vu ce que retournait defaultdict(list) ; ce qui correspond pile poil à l’exercice, mais j’etais resté à defaultdict(int).
merci !
Ma contribution : http://pastebin.com/qnRZMvwk
La méthode de normalisation est un peu crade, pardon.
Une reprise du code de Bob avec le module re:
http://pastebin.com/dYdQSra9
Je suis en Python 2.6, d’où la ligne “from __future__ import with_statement”.
Une autre version : http://pastebin.com/SEYx0XfW
Je voudrais pas faire mon chieur, mais quelqu’un m’a dit qu’on devait savoir l’encoding de toutes les entrées d’un script.
http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/
Or l’encoding du fichier à traiter n’est pas spécifié. C’est quoi ces specs à la mords-moi-l’mormon ?
@groug: c’est quoi un Ligature characters
@recher je connaissais “a la mords moi l’noeud” ;-)
@Sam: j’ai découvert ça en ayant le problème avec normalize. Les caractères “liés”, genre ae, oe (lien trouvé sur SO : http://unicode.org/repos/cldr/trunk/common/transforms/Latin-ASCII.xml )
@sam, http://en.wikipedia.org/wiki/Typographic_ligature#Ligatures_in_Unicode_.28Latin-derived_alphabets.29
En gros là ça pose soucis à cause du mot œuvre car le “e dans l’o” (il me semble qu’on dit comme ça en français) est une ligature qui possède son propre caractère unicode (U+0153) et du coup normalize() ne le transforme pas en “oe”, ce qui serait syntaxiquement faux.
Le problème c’est que si tu veux passer ça dans d’autres encodages, la correspondance n’existe pas forcement et tu as le choix entre mettre un “?” ou effacer le caractère.
Comme je l’avais dit dans mon post (que je fait du boulot juste avant de partir mais qui apparemment n’est pas passé) on n’a pas besoin de s’en soucier quand on utilise unidecode mais ça fait une lib à installer.
@Réchèr, j’ai déjà eu plus petit comme spec pour un truc beaucoup plus gros/important (et la moitié était fausse) alors là franchement ça passe. Au pire tu testes si le fichier est en utf-8 et si non, ben tu le bascules à la lecture et voilà ^^
Ma contribution :
http://pastebin.com/UKPXS2r9 (valable 1 mois)
clean_text pourrait être réduite en utilisant unidecode mais flemme de l’installer.
(phoque! ce message aurais du être envoyé le 16 à 18h)
@Réchèr : j’ai simplifié l’exercice en virant toute gestion d’erreur. Sinon faut aussi gérer les erreurs de parsing d’arguments de la ligne de commande, l’encoding d’entrée ET de sortie, etc. Ca rend le script beaucoup plus lourd, et c’est pas le but.
Je me demande pourquoi personne n’a posté la solution la plus simple :
http://pastebin.com/5987NkTB
99 bottles of beer…
Bon deux jours après, si quelqu’un lis ça tant mieux sinon je me serai quand même bien amusé.
J’ai fait ça en bash et j’ai appris pas mal de truc sur les possibilités de bash, les regex et la toolbox linux.
http://pastebin.com/iHtukYt1
Le code est crade mais ça marche. Au début c’est décalé de 1 car le comptage des mots commence à 1 et après ça décale d’un de plus car 9 est considéré comme un mot.
Voilà ! :-)
INstructif.
Salut !
Comme j’adore Pulp Fiction, j’ai fais l’exrcice.
Mais comme je débute seulement python, j’ai fais avec ce que je conaissais c’est à dire php.
http://pastebin.com/tB0nA8tU
Ps: trop fort le trombone.
Pas de problème, mais faut que change le asort, il ne trie pas par le bon critère.
bah zut, ça doit être un coup de chance car j’ai exactement le même résultat que l’énoncé
voilà qui devrait être plus juste ou pas
http://pastebin.com/6XxmeJ82
ma solution
Hello voici une solution possible: http://pastebin.com/y8kjQbbS