• # AWK en RUST

    Posté par  . Évalué à 5. Dernière modification le 20/03/21 à 21:15.

    Un dev a commencé l'implémentation de AWK en Rust avec du JIT.

    Il utilise ce benchmark.

    Étant un grand fan de AWK, je vais tester. Pour les scripts simples, ça a l'air de bien marcher. Pour des scripts plus compliqués, il y a des adaptations à faire. Pour le parallélisme aussi.

    Ça m'a permis de redécouvrir xsv du même auteur que ripgrep.

    Que de beaux outils

    • [^] # Re: AWK en RUST

      Posté par  . Évalué à 4.

      Je ne connaissais ps xsv ; à comparer avec csvkit et csvtool

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

      • [^] # Re: AWK en RUST

        Posté par  . Évalué à 5.

        • [^] # Re: AWK en RUST

          Posté par  . Évalué à 2.

          J'aurais dit à première vue que la majorité des utilitaires sont peu utiles (d'ailleurs la documentation de synthèse —le lisez-moi— indique bien ça et là que les utilitaires traditionnels font la même choses) si ce n'est leur gestion des entêtes en plus… Je n'ai pas souvent ce cas, mais quand ça arrive, c'est sûr que j'aurais adoré avoir cette trousse en plus (merci donc pour la découverte …renversante.)

          Les trois ou quatre plus utiles de prime abord, àmha, sont :

          • tsv-filter bien que j'utilise awk pour la plupart des exemples données (quand on procède par position… avec les entêtes il y a un réel plus ici car ça devient plus complexe-et-chiant de l'autre côté mais reste faisable) et ai expérimenté quelque autre script à l'occasion ;
          • tsv-summarize là aussi on peut sortir awk ou un autre langage de scripting comme PERL/PHP/Python/Ruby/etc, voire de passer par R ou du SQL, mais je pense que pour les data-scientists ou des staticians qui ont souvent ce genre de besoin sur ce genre de fichiers c'est du temps de scriptage en moins ;
          • dans le même esprit, tsv-sample peut être intéressant pour toute personne amenée à manipuler des échantillons d'un gros fichier (des milliers de lignes) et dans ce cas aurait eu besoin de passer par un script maison vite fait ou un outil pivot ;
          • csv2tsv est clairement un truc que j'aurais aimer avoir dans de nombreux cas où on a des exports CSV dégueulasses (avec des champs qui ne sont pas systématiquement "quoté"s et le pire quand on a des champs avec le délimiteur ou s'étendant sur plusieurs lignes) depuis divers outils

          En tout cas belle découverte.

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: AWK en RUST

          Posté par  . Évalué à 1.

          Ah… comme on en parle, jben nous fait un journal sur sa cuillère

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: AWK en RUST

      Posté par  . Évalué à 2.

      Je viens d'aller voir la page des performances de frawk et j'ai adoré son disclaimer :

      The abundance of such claims notwithstanding, I've found it is very hard to precisely state the degree to which an entire programming language implementation is or is not efficient. I have no doubt that there are programs in frawk that are slower than equivalent programs in Rust or C, or even mawk or gawk (indeed, see the "Group By Key" benchmark). In some cases this will be due to bugs or differences in the quality of the language implementations, in others it will be due to bugs or differences in the quality of the programs themselves, while in still others it may be due to the fact that in some nontrivial sense one language allows you to write the program more efficiently than another.

      I've found that it can be very hard to distinguish between these three categories of explanations when doing performance analysis. As such, I encourage everyone reading this document to draw at most modest conclusions based on the numbers below. What I do hope this document demonstrates are some of frawk's strengths when it comes to some common scripting tasks on CSV and TSV data

      AWK est un DSL prévu pour les fichiers DSV simples de l'époque (le fichier /etc/passwd en est un exemple) alors qu'aujourd'hui le CSV qui s'utilise de plus en plus en plus est loin de cette simplicité+régularité (non seulement, contrairement au sigle, ce n'est pas la virgule qui est forcément utilisée, mais les différents séparateurs peuvent se retrouver dans les champs qui doivent en plus être entourés etc.) À l'inverse, frawk veut adresser d'entrée cette complexité déjà discutée ici. Il est donc bien vu d'avoir xsv et tsv-tools dans le comparatif puisque ceux-ci sont sur le créneau visé. Ceci dit, le CSV utilisé pour ses tests n'est pas des plus complexes, mais nécessite plus de taf (comme je l'ai mentionné dans un autre commentaire, ce sont dans ces cas que xsv et tsv-utils peuvent sembler intéressant, pour ne pas devoir investir plus de temps et d'énergie en développement supplémentaire)

      Benchmarks for the TREE_GRM_ESTN dataset are not run on CSV input with mawk or gawk, as it contains quoted fields and these utilities do not handle CSV escaping out of the box. We still run them on the TSV versions of these files using \t as a field separator.

      Les awk présentés sont écrits sans hack et donc pourront être utilisés avec d'autres implémentations d'une part, et les performances observées avec les implémentations et versions utilisées n'exploitent pas leurs spécificité (gawk par exemple a quelques ajouts qui font que la réécriture peut donner des résultats plus bluffants mais cela ne sera malheureusement pas portable, contrairement à la forme POSIX) Il y a quand même de petits détails auxquels il faut faire gaffe, comme il est dit

      Note: the +0s ensure we are always performing a numeric comparison. In Awk this is unnecessary if all instances of column $4 and column $5 are numeric; in frawk this is required: max will perform a lexicographic comparison instead of a numeric one without the explicit conversion.

      La plus grande surprise, pour moi, fut pour le petit test en Python et en Rust

      frawk is a good deal faster than the other options, particularly on the newer hardware, or when run in parallel. Now, the Rust script could of course be optimized substantially (frawk is implemented in Rust, after all). But if you need to do exploratory, ad-hoc computations like this, a frawk script is probably going to be faster than the first few Rust programs you write.

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # Des choux et des carottes...

    Posté par  (site Web personnel) . Évalué à 4.

    Pour prendre le langage que je connais le mieux, PHP, j'ai zieuté vite fait le code proposé, et qui est plutôt court :
    ```
    <?php
    $words = [];
    while (($line = fgets(STDIN)) !== false) {
    foreach (preg_split('/ +/', strtolower(trim($line)), -1, PREG_SPLIT_NO_EMPTY) as $word) {
    if (!isset($words[$word])) {
    $words[$word] = 0;
    }
    $words[$word]++;
    }
    }

    arsort($words);

    foreach($words as $word => $count) {
    echo "$word $count\n";
    }
    ```
    Il y a moyen de faire rapido plus court et plus rapide d'environ 30 ou 40% (j'y reviens plus bas) :

    while (($line = fgets(STDIN)) !== false) {
        foreach (explode(" ", strtolower(trim($line))) as $word) {
            @$words[$word]++;
        }
    }
    unset($words[""]);
    arsort($words);
    foreach($words as $word => $count) echo "$word $count\n";
    

    Certes c'est moins "propre" : pas bien de ne pas déclarer le tableau (auto en PHP non-strict), peut-être moins clair de ne pas initialiser à 0 l'élément du tableau (auto en PHP), et encore moins d'utiliser l'arobase pour faire tomber aux oubliettes le warning sur l'élément non-déclaré. Mais c'est un test de performance, non ? Même résultat en plus rapide.

    Ce "plus rapide" est difficile à estimer car sur ma machine, qui n'est pourtant pas de première jeunesse, le script PHP d'origine s'exécute en 0.19s (en moyenne), et la version modifiée en 0.11s (en moyenne aussi). En moyenne car d'un lancement à l'autre ça fluctue beaucoup (de 0.03s environ).

    Bref, comparer des langages alors que de toutes petites modifs comme celle que j'ai faites peuvent faire passer le résultat presque du simple au double (ou l'inverse), ça ne veut plus dire grand chose.
    Il faudrait retirer la partie "sortie standard" du calcul de temps d'exécution car les buffers de sorties des consoles (xfce4-terminal dans mon cas) doivent influencer pas mal le résultat ; et partir sur un jeu d'entrée beaucoup plus gros pour allonger le temps de traitement (viser au moins 30s) pour voir réellement des différences.

    • [^] # Re: Des choux et des carottes...

      Posté par  (site Web personnel) . Évalué à 3.

      Il faudrait retirer la partie "sortie standard" du calcul de temps d'exécution

      Je m'auto-quote (oui monsieur!) en voyant après coup que le gars envoie tout sur /dev/null, du coup les temps sont plus stables (0.01s environ), confirmant l'influence du terminal sur la fluctuation des temps si on affiche les résultats.

    • [^] # Re: Des choux et des carottes...

      Posté par  . Évalué à 1.

      Ils sont tous relativement courts les codes proposés…

      Alors, si je comprends bien, tu gagnes 0.08s chez toi en remplaçant

      if (!isset($words[$word])) {
          $words[$word] = 0;
      }
      $words[$word]++;

      par (moins propre pour ne pas dire carrément crade)

      @$words[$word]++;

      ? Est-ce isset ou l'affectation qui plombe les performance ?
      Parce-que raccourcir pour raccourci abouti au genre de trucs qui font la mauvaise presse de PHP (qui pourtant, malgré la performance qui te déplait, laisse Python sur le carreau)
      En tout cas je n'aurais pas viré ce passage, et si c'est juste pour faire moins de ligne

      isset($words[$word]) ?: $words[$word]= 0;
      $words[$word]++;

      ou encore (après c'est une question de goût)

      !isset($words[$word]) && $words[$word] = 0;
      $words[$word]++;

      Et une réduction de 57.9% (de 0.19s à 0.11s) n'est pas vraiment 100% comme tu dis

      de toutes petites modifs comme celle que j'ai faites peuvent faire passer le résultat presque du simple au double (ou l'inverse)

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

      • [^] # Re: Des choux et des carottes...

        Posté par  (site Web personnel) . Évalué à 3.

        Alors, si je comprends bien, tu gagnes 0.08s chez toi en remplaçant …

        Non. Retirer un test fait bien entendu gagner un peu, mais le plus gros du gain vient du remplacement du preg_split par un explode.

        Est-ce que c'est crade ? oui, je l'ai dit. Pas de surprise. Ce n'est pas un truc à faire en dehors de ce cadre spécial. Le but était de démontrer d'une mesure de temps d'exécution est fantaisiste car il y a moultes façons d'écrire ce programme, avec des temps d'exécution fort différents.

        Passer de 0.19 à 0.11, ce n'est pas gagner 100%, mais plutôt 40%, comme je l'ai également écrit. Les pourcentages, faut toujours se baser sur ce qui représente 100% (ici le temps de la version d'origine). Et c'est "presque" (le mot est important) passer du double au simple (en gros passer de 19 à 11 au lieu de 19 à 9.5 sans le presque), mais on peut toujours chipoter.

        • [^] # Re: Des choux et des carottes...

          Posté par  . Évalué à 1.

          Le but était de démontrer d'une mesure de temps d'exécution est fantaisiste car il y a moultes façons d'écrire ce programme, avec des temps d'exécution fort différents.

          Ça tombe bien… C'est dans la section finale, « Other languages », où il est dit :

          Many readers contributed to the benhoyt/countwords repository to add other popular languages – thank you! Here’s the list:

          L'auteur n'a clairement pas écrit la variante en PHP d'une part (c'est Max Semenik qui en est crédité), et elles sont sur un dépôt ouvert ouvert d'autre part… Donc tu peux soumettre une version optimisée.

          Il est aussi conscient qu'il y a plusieurs façons d'arriver au même résultat, et précise dans le résumé en introduction :

          For each language, I’ve included a simple, idiomatic solution as well as a more optimized approach via profiling.

          La solution de base, simple, est normalement ce qu'on peut pondre de tête lorsqu'on vous présente le problème en entretien et qu'on n'a pas tous les éléments et le temps pour faire un truc beau et optimisé (là dessus, on est d'accord que le plus simple est d'utiliser explode et que peu de gens ont le réflexe preg_split qui se trouve moins performant pour le coup)

          A basic solution reads the file line-by-line, converts to lowercase, splits each line into words, and counts the frequencies in a hash table. When that’s done, it converts the hash table to a list of word-count pairs, sorts by count (largest first), and prints them out.

          L'optimisation est la seconde étape, et c'est dans ce cadre et ce sens qu'il faut regarder les temps d'exécution. Mais pas pour eux-même ni pour se comparer au voisi dans l'absolu : la démonstration est surtout comment profiter des outils de profilage pour optimiser (donc on devrait comparer les différentes versions d'un même langage entre elles —mais accidentellement, quand on sait le faire dans plusieurs langages, il est tentant de comparer les mêmes implémentations entre langages pour voir si les mêmes efforts payent de la même façon et aussi mieux appréhender les points forts et les points faibles de chacun.)
          Non seulement Ben ne pratique pas le PHP, mais si c'était le cas il n'aurait accordé une section que s'il peut présenter une version de base et une optimisée en s'appuyant sur une possibilité de profilage intégrée (et ce point m'intéresse si tu as la réponse.)

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

          • [^] # Re: Des choux et des carottes...

            Posté par  (site Web personnel) . Évalué à 3.

            Je veux bien entendre tes arguments, mais quand le titre est "Performance comparison: counting words in Python, Go, C++, C, AWK, Forth, and Rust", le but du jeu est clairement de comparer les perfomances entre ces langages, ce n'est pas "tiens, vu qu'on a déjà fait le truc dans plusieurs langages, on pourrait aussi les comparer tant qu'on y est".
            L'optimisation, le profilage, c'est visiblement plus un bonus que le but du jeu.

            J'ai pris le cas de PHP parce que je connais ce langage bien mieux que les autres (voire pas du tout pour certains). Des petites modifs ayant un impact important sur la performance, il y a sûrement moyen d'en faire aussi dans les autres langages dont ceux de Ben, et là on ne parle pas des versions optimisées avec des algos spécifiques, juste des petits modifs ne touchant pas à la logique de la version simple. Du coup, la comparaison est fantaisiste, car quand décide-t-on que la version simple est la plus "apte" pour la comparaison ? Dans cinq ans, il y a un gars qui dira : "en Lua, si on fait comme ça, on va 3 fois plus vite" et donc Lua qui n'était pas considéré comme rapide ces cing dernières années va devenir plus rapide que d'autres langages. C'est tiré par les cheveux. (j'ai pris Lua au pif, hein)

            Je ne connais pas Ben et ça n'enlève pas son mérite d'avoir proposé des algos dans plusieurs langages. Juste que comparer les performances des langages n'est pas aussi simple que ça en a l'air, et que ce n'est pas une bonne idée de juste regarder le tableau final en pensant que le langage Machin est plus performant que le langage Truc.

            • [^] # Re: Des choux et des carottes...

              Posté par  . Évalué à 5.

              Je veux bien entendre tes arguments, mais quand le titre est "Performance comparison: counting words in Python, Go, C++, C, AWK, Forth, and Rust", le but du jeu est clairement de comparer les perfomances entre ces langages, ce n'est pas "tiens, vu qu'on a déjà fait le truc dans plusieurs langages, on pourrait aussi les comparer tant qu'on y est".
              L'optimisation, le profilage, c'est visiblement plus un bonus que le but du jeu.

              Ce n'est pas du tout comme ça que je lis le titre ni le billet. Il ne parle pas de comparer la performance entre les langages mais dans chaque langage. Et s'il produit une liste multi langage il montre pour chacun le gain entre idiomatique et optimisé.

              Il suffit de regarder la conclusion pour s'en convaincre. Il parle même de quel langage est le plus performant, mais du fait que C++ donne des messages d'erreur affreux, qu'en C ça vaut le coût d'utiliser une bibliothèque pour ça et que python et awk sont les plus rapide (pour la partie écriture du code et pas pour la partie exécution).

              https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

              • [^] # Re: Des choux et des carottes...

                Posté par  (site Web personnel) . Évalué à 2.

                Ce n'est pas du tout comme ça que je lis le titre ni le billet. Il ne parle pas de comparer la performance entre les langages mais dans chaque langage. Et s'il produit une liste multi langage il montre pour chacun le gain entre idiomatique et optimisé.

                Il suffit de regarder la conclusion pour s'en convaincre.

                On ne doit avoir lu le même billet alors.
                Pour le titre, s'il ne voulait pas comparer les langages entre-eux à la base, il aurait du choisir un truc du genre : "Performance comparison in counting words, study cases in various languages.", sinon c'est ce qu'on appelle un titre putaclick.

                Quand à la conclusion, la moitié est consacrée au tableau de comparaison entre langages, et ensuite viennent quelques pensées qu'il en tire, avec en premier : "I think it’s the simple, idiomatic versions that are the most telling. This is the code programmers are likely to write in real life.", alors que j'ai prouvé ci-dessus que ce n'est pas le cas, les developpeurs ne ponderont pas tous le même code dans la vie réelle, il existera des versions différentes avec des performances elles aussi bien différentes.

                Le problème est certainement lié à une autre de ses pensées : "I still think this interview question is a good one for a coding question". Si cette question m'était posée telle que lors d'un entretien (hypothèse improbable), je demanderais à l'examinateur dans quel contexte le programme est censé s'exécuter, quels sont les critères importants : performance à tout prix ? code facile à maintenir même 20 ans plus tard par un nouvel arrivant ? Empreinte mémoire minimale ? Espace disque ou IO minimum ? … Même si dans la vie réelle c'est souvent un équilibre entre tous ces critères, rien ne permet de deviner le choix de l'examinateur. Au final il y aura autant de versions que ce choix d'équilibre entre ces critères.

                • [^] # Re: Des choux et des carottes...

                  Posté par  . Évalué à 4.

                  Pour le titre, s'il ne voulait pas comparer les langages entre-eux à la base, il aurait du choisir un truc du genre : "Performance comparison in counting words, study cases in various languages.", sinon c'est ce qu'on appelle un titre putaclick.

                  Qu'il soit possible de trouver un titre qui préserve mieux ta sensibilité n'indique pas que ce titre est putaclick.

                  Quand à la conclusion, la moitié est consacrée au tableau de comparaison entre langages, et ensuite viennent quelques pensées qu'il en tire, avec en premier : "I think it’s the simple, idiomatic versions that are the most telling. This is the code programmers are likely to write in real life.", alors que j'ai prouvé ci-dessus que ce n'est pas le cas, les developpeurs ne ponderont pas tous le même code dans la vie réelle, il existera des versions différentes avec des performances elles aussi bien différentes.

                  Je ne suis pas d'accord. Oui il y a des façons différentes pour autant peu vont réellement diverger (sur un sujet aussi simple) et la version idiomatique va logiquement être la solution la plus fréquemment utilisée. Le fait que tu ai montré qu'il y a d'autres façons de faire n'invalide pas cela.

                  Plus de la moitié du billet montre comment on mesure la performance dans chacun des langages et comment les choix fait impactes ses métriques, il n'y a aucun endroit où il parle de la performance comparer des langages. Ce n'est pas un point de vu.

                  https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                • [^] # Re: Des choux et des carottes...

                  Posté par  . Évalué à 1.

                  et ensuite viennent quelques pensées qu'il en tire, avec en premier : "I think it’s the simple, idiomatic versions that are the most telling. This is the code programmers are likely to write in real life.", alors que j'ai prouvé ci-dessus que ce n'est pas le cas, les developpeurs ne ponderont pas tous le même code dans la vie réelle, il existera des versions différentes avec des performances elles aussi bien différentes.

                  Pas tous, mais la majorité, en ayant les mêmes contraintes que celles posées. Mais cela ne signifie pas que c'est la version finale de la majorité, mais le premier truc qui vient à l'esprit d'une personne pas trop perchée. Et sur ce point justement, il dit bien que ce qui l'intéresse c'est que les devs connaissent et comprennent assez ces aspects (comment sont géré les tableaux de hachage, les performances des entrées/sorties et des routines de tri intégrées) de leur langage de prédilection et non des concepts algorithmiques très avancés que peu mettent en œuvre au final (encore en général, et ça vise les petites entreprises qui veulent faire des entretiens à la Foogle/Gacebook pour finalement vous faire pondre des petits trucs bien loin de là) : « I think this is a good interview question because it’s somewhat harder to solve than FizzBuzz, but it doesn’t suffer from the “invert a binary tree on this whiteboard” issue. It’s the kind of thing a programmer might have to write a script for in real life, and it shows whether they understand file I/O, hash tables (maps), and how to use their language’s sort function. There’s a little bit of trickiness in the sorting part, because most hash tables aren’t ordered, and if they are, it’s by key or insertion order and not by value. »

                  Le problème est certainement lié à une autre de ses pensées : "I still think this interview question is a good one for a coding question". Si cette question m'était posée telle que lors d'un entretien (hypothèse improbable), je demanderais à l'examinateur dans quel contexte le programme est censé s'exécuter, quels sont les critères importants : performance à tout prix ? code facile à maintenir même 20 ans plus tard par un nouvel arrivant ? Empreinte mémoire minimale ? Espace disque ou IO minimum ? … Même si dans la vie réelle c'est souvent un équilibre entre tous ces critères, rien ne permet de deviner le choix de l'examinateur. Au final il y aura autant de versions que ce choix d'équilibre entre ces critères.

                  De ce que j'ai vu pour avoir fait passer un certain nombre d'entretiens et pour en avoir subi de bien costaudes aussi, on ne pense pas forcément à faire le malin ni à donner une réponse exhaustive quand on pense à tout les points que tu évoques. Les examinateurs pas fêlés n'ont normalement pas de choix et veulent juste voir comment est esquissée la solution (et là, en proposant celle de Ben tu le rassures que tu sauras répondre aux urgences au lieu de pinailler quand il y a le feu ; et si en plus tu mets les réserves citées par vous deux, ça montre que tu connais ton langage et sauras optimiser le moment venu)
                  Mais sinon, c'est un peu la seconde partie de l'entretien déjà… « After the candidate has a basic solution, you can push it in all sorts of different directions: what about capitalization? punctuation? how does it order two words with the same frequency? what’s the performance bottleneck likely to be? how does it fare in terms of big-O? what’s the memory usage? roughly how long would your program take to process a 1GB file? would your solution still work for 1TB? and so on. Or you can take it in a “software engineering” direction and talk about error handling, testability, turning it into a hardened command line utility, etc. »

                  “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: Des choux et des carottes...

              Posté par  . Évalué à 2.

              Le titre est ce qu'on appelle, je crois, putaclic (il est à parier qu'avec un titre plus honnête il aurait eu beaucoup moins de lectures et de commentaires ici, et probablement de contributions héhé) ;-)

              Alors, pour la version simple et l'optimisée, il a énoncé les critères suivants :

              • on lit un fichier depuis l'entrée standard, et on ne lit pas tout le fichier en mémoire (mais par blocs pouvant être des lignes et au d'au plus 64 kibi)
              • on écrit le nombre d'occurrence des mots le composant du plus élevé au plus bas sur la sortie standard
              • on ne fait pas de distinction de casse et son résultat est en minuscule : "le" et "Le" et "LE" seront tous trois comptés "le 3"
              • on ne se préoccupe pas de l'encodage et des accentuations, on considère qu'on bosse sur de l'ASCII des familles (comme le document de test utilisé)
              • on ne cherche pas à classer les mots ayant la même fréquence d'apparition
              • on n'utilise que les éléments de base du langage (pas de bibliothèque supplémentaire)
              • on n'invente pas sa propre structure de hachage (même s'il a fait une exception pour la variante optimisée en C)
              • on s'évite les trucs de jedi du langage et le recours à l'assembleur ou trucs similaires

              Avec ces trois derniers, il est un peu difficile de trouver un autre algo que celui proposé. Tu trouves autres chose et ce ne sera plus le même test ni le même objectif de l'entretien.
              Mais fort de ces contraintes, il est normal que même la version optimisée ne touche pas fondamentalement la logique première (toute façon l'autre but, comme je le perçois, était de voir comment mettre le profilage à profit ensuite et quand il faut s'avoir s'arrêter dans l'optimisation : pour certains langages il dit qu'on peut faire mieux, mais qu'il estime que c'est trop d'effort pour des poullièmes par rapport au cadre posé)

              “It is seldom that liberty of any kind is lost all at once.” ― David Hume

      • [^] # Re: Des choux et des carottes...

        Posté par  . Évalué à 3.

        par (moins propre pour ne pas dire carrément crade)

        @$words[$word]++;

        Le propre ou pas est toujours débattable mais c'est le comportement de AWK : echo | awk 'BEGIN {A[a]++} END{print A[a]}'.

        Et cela s'obtient facilement en python avec les "defaultdict".

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.