Construisez un ASCII graphique des mots les plus couramment utilisés dans un texte donné.
Les règles:
a-z
et A-Z
(caractères alphabétiques) dans le cadre d'un mot.She
== she
pour notre but).the, and, of, to, a, i, it, in, or, is
Clarification: considérant don't
: ce serait considéré comme 2 "mots" différents dans les plages a-z
et A-Z
: (don
et t
).
Facultativement (il est trop tard pour modifier officiellement les spécifications maintenant) vous pouvez choisissez de supprimer tous les "mots" d'une seule lettre (cela pourrait également entraîner un raccourcissement de la liste des ignorés).
Analyser un text
donné (lire un fichier spécifié via des arguments de ligne de commande ou canalisé; présumer us-ascii
) et construisez-nous un Word frequency chart
avec les caractéristiques suivantes:
width
représente le nombre d'occurrences (fréquence) du mot (proportionnellement). Ajoutez un espace et imprimez le mot.bar
+ [space]
+ Word
+ [space]
doit toujours être <= 80
caractères (assurez-vous de tenir compte des éventuelles longueurs de barre et de mot différentes: par exemple: le deuxième mot le plus courant pourrait être beaucoup plus long que le premier sans trop différer en fréquence). Maximize largeur de barre à l'intérieur de ces contraintes et mise à l'échelle appropriée des barres (selon les fréquences qu'elles représentent).Un exemple:
Le texte de l'exemple peut être trouvé ici ( Alice's Adventures in Wonderland, par Lewis Carroll).
Ce texte spécifique produirait le graphique suivant:
_________________________________________________________________________ | _________________________________________________________________________ | elle | _______________________________________________________________ | vous | ____________________________________________________________ | dit | ____________________________________________________ | alice | ______________________________________________ | était | __________________________________________ | | ___________________________________ | comme | _______________________________ | son | ____________________________ | avec | ____________________________ | à | ___________________________ | s | ___________________________ | t | _________________________ | le | _________________________ | tous | ______________________ | ce | ______________________ | pour | ______________________ | avait | _____________________ | mais | ____________________ | être | ____________________ | pas | ___________________ | ils | __________________ | alors
Pour votre information: ce sont les fréquences sur lesquelles le tableau ci-dessus est construit:
[("elle", 553), ("vous", 481), ("dit", 462), ("alice", 403), ("était", 358), ("que ', 330), (' as ', 274), (' her ', 248), (' with ', 227), (' at ', 227), (' s ', 219), ( 't' , 218), ('on', 204), ('all', 200), ('this', 181), ('for', 179), ('had', 178 ), (' mais', 175), ('be', 167), ('not', 166), ('they', 155), ('so', 152)]
Un deuxième exemple (pour vérifier si vous avez implémenté la spécification complète): Remplacez chaque occurrence de you
dans le lien Alice au pays des merveilles fichier avec superlongstringstring
:
________________________________________________________________ | ________________________________________________________________ | elle | _______________________________________________________ | superlongstringstring | _____________________________________________________ | dit | ______________________________________________ | alice | ________________________________________ | était | _____________________________________ | que | ______________________________ | comme | ___________________________ | son | _________________________ | avec | _________________________ | à | ________________________ | s | ________________________ | t | ______________________ | le | _____________________ | tous | ___________________ | ce | ___________________ | pour | ___________________ | avait | __________________ | mais | _________________ | être | _________________ | pas | ________________ | ils | ________________ | alors
Le gagnant:
Solution la plus courte (par nombre de caractères, par langue). S'amuser!
Edit : Tableau résumant les résultats jusqu'à présent (2012-02-15) (initialement ajouté par l'utilisateur Nas Banov):
Langage détendu strict ========= ======= ====== GolfScript 130 143 Perl 185 Windows PowerShell 148 199 Mathematica 199 Ruby 185 205 Unix Toolchain 194 228 Python 183 243 Clojure 282 Scala 311 Haskell 333 Awk 336 R 298 Javascript 304 354 Groovy 321 Matlab 404 C # 422 Smalltalk 386 PHP 450 F # 452 TSQL 483 507
Les nombres représentent la longueur de la solution la plus courte dans une langue spécifique. "Strict" fait référence à une solution qui implémente complètement la spécification (dessine |____|
bars, ferme la première barre en haut avec un ____
ligne, tient compte de la possibilité de mots longs à haute fréquence, etc.). "Détendu" signifie que certaines libertés ont été prises pour raccourcir la solution.
Seules les solutions de moins de 500 caractères sont incluses. La liste des langues est triée selon la longueur de la solution "stricte". 'Unix Toolchain' est utilisé pour signifier diverses solutions qui utilisent le shell * nix traditionnel plus un mélange d'outils (comme grep, tr, sort, uniq, head, Perl, awk).
(fortement basé sur les autres solutions Ruby solutions)
w=($<.read.downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).group_by{|x|x}.map{|x,y|[-y.size,x]}.sort[0,22]
k,l=w[0]
puts [?\s+?_*m=76-l.size,w.map{|f,x|?|+?_*(f*m/k)+"| "+x}]
Au lieu d'utiliser des commutateurs de ligne de commande comme les autres solutions, vous pouvez simplement passer le nom de fichier en argument. (c'est à dire. Ruby1.9 wordfrequency.rb Alice.txt
)
Étant donné que j'utilise des littéraux de caractères ici, cette solution ne fonctionne que dans Ruby 1.9.
Modifier: les points-virgules remplacés par des sauts de ligne pour plus de "lisibilité". : P
Edit 2: Shtééf a souligné que j'avais oublié l'espace de fuite - corrigé cela.
Edit 3: Suppression de l'espace de fuite à nouveau;)
Lent - 3 minutes pour l'exemple de texte (130)
{32|.123%97<n@if}%]''*n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<.0=~:2;,76\-:1'_':0*' '\@{"
|"\~1*2/0*'| '@}/
Explication:
{ #loop through all characters
32|. #convert to uppercase and duplicate
123%97< #determine if is a letter
n@if #return either the letter or a newline
}% #return an array (of ints)
]''* #convert array to a string with magic
n% #split on newline, removing blanks (stack is an array of words now)
"oftoitinorisa" #Push this string
2/ #split into groups of two, i.e. ["of" "to" "it" "in" "or" "is" "a"]
- #remove any occurrences from the text
"theandi"3/-#remove "the", "and", and "i"
$ #sort the array of words
(1@ #takes the first Word in the array, pushes a 1, reorders stack
#the 1 is the current number of occurrences of the first Word
{ #loop through the array
.3$>1{;)}if#increment the count or Push the next Word and a 1
}/
]2/ #gather stack into an array and split into groups of 2
{~~\;}$ #sort by the latter element - the count of occurrences of each Word
22< #take the first 22 elements
.0=~:2; #store the highest count
,76\-:1 #store the length of the first line
'_':0*' '\@ #make the first line
{ #loop through each Word
"
|"\~ #start drawing the bar
1*2/0 #divide by zero
*'| '@ #finish drawing the bar
}/
"Correct" (j'espère). (143)
{32|.123%97<n@if}%]''*n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<..0=1=:^;{~76@,-^*\/}%$0=:1'_':0*' '\@{"
|"\~1*^/0*'| '@}/
Moins lent - une demi-minute. (162)
'"'/' ':S*n/S*'"#{%q
'\+"
.downcase.tr('^a-z','
')}\""+~n%"oftoitinorisa"2/-"theandi"3/-$(1@{.3$>1{;)}if}/]2/{~~\;}$22<.0=~:2;,76\-:1'_':0*S\@{"
|"\~1*2/0*'| '@}/
Sortie visible dans les journaux de révision.
Merci à Gabe pour quelques suggestions utiles pour réduire le nombre de personnages.
NB: Des sauts de ligne ont été ajoutés pour éviter les barres de défilement, seul le dernier saut de ligne est requis.
DECLARE @ VARCHAR(MAX),@F REAL SELECT @=BulkColumn FROM OPENROWSET(BULK'A',
SINGLE_BLOB)x;WITH N AS(SELECT 1 i,LEFT(@,1)L UNION ALL SELECT i+1,SUBSTRING
(@,i+1,1)FROM N WHERE i<LEN(@))SELECT i,L,i-RANK()OVER(ORDER BY i)R INTO #D
FROM N WHERE L LIKE'[A-Z]'OPTION(MAXRECURSION 0)SELECT TOP 22 W,-COUNT(*)C
INTO # FROM(SELECT DISTINCT R,(SELECT''+L FROM #D WHERE R=b.R FOR XML PATH
(''))W FROM #D b)t WHERE LEN(W)>1 AND W NOT IN('the','and','of','to','it',
'in','or','is')GROUP BY W ORDER BY C SELECT @F=MIN(($76-LEN(W))/-C),@=' '+
REPLICATE('_',-MIN(C)*@F)+' 'FROM # SELECT @=@+'
|'+REPLICATE('_',-C*@F)+'| '+W FROM # ORDER BY C PRINT @
Version lisible
DECLARE @ VARCHAR(MAX),
@F REAL
SELECT @=BulkColumn
FROM OPENROWSET(BULK'A',SINGLE_BLOB)x; /* Loads text file from path
C:\WINDOWS\system32\A */
/*Recursive common table expression to
generate a table of numbers from 1 to string length
(and associated characters)*/
WITH N AS
(SELECT 1 i,
LEFT(@,1)L
UNION ALL
SELECT i+1,
SUBSTRING(@,i+1,1)
FROM N
WHERE i<LEN(@)
)
SELECT i,
L,
i-RANK()OVER(ORDER BY i)R
/*Will group characters
from the same Word together*/
INTO #D
FROM N
WHERE L LIKE'[A-Z]'OPTION(MAXRECURSION 0)
/*Assuming case insensitive accent sensitive collation*/
SELECT TOP 22 W,
-COUNT(*)C
INTO #
FROM (SELECT DISTINCT R,
(SELECT ''+L
FROM #D
WHERE R=b.R FOR XML PATH('')
)W
/*Reconstitute the Word from the characters*/
FROM #D b
)
T
WHERE LEN(W)>1
AND W NOT IN('the',
'and',
'of' ,
'to' ,
'it' ,
'in' ,
'or' ,
'is')
GROUP BY W
ORDER BY C
/*Just noticed this looks risky as it relies on the order of evaluation of the
variables. I'm not sure that's guaranteed but it works on my machine :-) */
SELECT @F=MIN(($76-LEN(W))/-C),
@ =' ' +REPLICATE('_',-MIN(C)*@F)+' '
FROM #
SELECT @=@+'
|'+REPLICATE('_',-C*@F)+'| '+W
FROM #
ORDER BY C
PRINT @
Sortie
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| You
|____________________________________________________________| said
|_____________________________________________________| Alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| at
|_____________________________| with
|__________________________| on
|__________________________| all
|_______________________| This
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| So
|___________________| very
|__________________| what
Et avec la longue chaîne
_______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| Alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| at
|_________________________| with
|_______________________| on
|______________________| all
|____________________| This
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| So
|________________| very
|________________| what
~ % wc -c wfg
209 wfg
~ % cat wfg
egrep -oi \\b[a-z]+|tr A-Z a-z|egrep -wv 'the|and|of|to|a|i|it|in|or|is'|sort|uniq -c|sort -nr|head -22|Perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
~ % # usage:
~ % sh wfg < 11.txt
hm, juste vu ci-dessus: sort -nr
-> sort -n
puis head
-> tail
=> 208 :)
update2: euh, bien sûr, ce qui précède est idiot, car il sera alors inversé. Donc, 209.
update3: optimisation de l'expression rationnelle d'exclusion -> 206
egrep -oi \\b[a-z]+|tr A-Z a-z|egrep -wv 'the|and|o[fr]|to|a|i[tns]?'|sort|uniq -c|sort -nr|head -22|Perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
pour le plaisir, voici une version uniquement Perl (beaucoup plus rapide):
~ % wc -c pgolf
204 pgolf
~ % cat pgolf
Perl -lne'$1=~/^(the|and|o[fr]|to|.|i[tns])$/i||$f{lc$1}++while/\b([a-z]+)/gi}{@w=(sort{$f{$b}<=>$f{$a}}keys%f)[0..21];$Q=$f{$_=$w[0]};$B=76-y///c;print" "."_"x$B;print"|"."_"x($B*$f{$_}/$Q)."| $_"for@w'
~ % # usage:
~ % sh pgolf < 11.txt
Une amélioration sur Anurag, intégrant la suggestion de rfusca. Supprime également l'argument de tri et quelques autres golfs mineurs.
w=(STDIN.read.downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).group_by{|x|x}.map{|x,y|[-y.size,x]}.sort.take 22;k,l=w[0];m=76.0-l.size;puts' '+'_'*m;w.map{|f,x|puts"|#{'_'*(m*f/k)}| #{x} "}
Exécuter en tant que:
Ruby GolfedWordFrequencies.rb < Alice.txt
Edit: replacez les "met", doit être là pour éviter d'avoir des guillemets en sortie.
Edit2: Fichier modifié-> IO
Edit3: supprimé/i
Edit4: Suppression des parenthèses autour (f * 1.0), recompté
Edit5: utilisez l'ajout de chaîne pour la première ligne; développez s
sur place.
Edit6: Fait flotter m, supprimé 1.0. EDIT: ne fonctionne pas, modifie les longueurs. EDIT: Pas pire qu'avant
Edit7: utilisez STDIN.read
.
Regardez maman ... pas de vars, pas de mains, .. pas de tête
Édition 1> quelques raccourcis définis (284 caractères)
f[x_, y_] := Flatten[Take[x, All, y]];
BarChart[f[{##}, -1],
BarOrigin -> Left,
ChartLabels -> Placed[f[{##}, 1], After],
Axes -> None
]
& @@
Take[
SortBy[
Tally[
Select[
StringSplit[ToLowerCase[Import[i]], RegularExpression["\\W+"]],
!MemberQ[{"the", "and", "of", "to", "a", "i", "it", "in", "or","is"}, #]&]
],
Last],
-22]
Quelques explications
Import[]
# Get The File
ToLowerCase []
# To Lower Case :)
StringSplit[ STRING , RegularExpression["\\W+"]]
# Split By Words, getting a LIST
Select[ LIST, !MemberQ[{LIST_TO_AVOID}, #]&]
# Select from LIST except those words in LIST_TO_AVOID
# Note that !MemberQ[{LIST_TO_AVOID}, #]& is a FUNCTION for the test
Tally[LIST]
# Get the LIST {Word,word,..}
and produce another {{Word,counter},{Word,counter}...}
SortBy[ LIST ,Last]
# Get the list produced bt tally and sort by counters
Note that counters are the LAST element of {Word,counter}
Take[ LIST ,-22]
# Once sorted, get the biggest 22 counters
BarChart[f[{##}, -1], ChartLabels -> Placed[f[{##}, 1], After]] &@@ LIST
# Get the list produced by Take as input and produce a bar chart
f[x_, y_] := Flatten[Take[x, All, y]]
# Auxiliary to get the list of the first or second element of lists of lists x_
dependending upon y
# So f[{##}, -1] is the list of counters
# and f[{##}, 1] is the list of words (labels for the chart)
Sortie
texte alternatif http://i49.tinypic.com/2n8mrer.jpg
Mathematica n'est pas bien adapté pour le golf, et c'est simplement à cause des noms de fonctions longs et descriptifs. Des fonctions comme "RegularExpression []" ou "StringSplit []" me font juste sangloter :(.
Le loi de Zipf prédit que pour un texte en langage naturel, le Log (Rank) vs Journal (occurrences) Le tracé suit une relation linéaire .
La loi est utilisée dans le développement d'algorithmes de criptographie et de compression de données. (Mais ce n'est PAS le "Z" dans l'algorithme LZW).
Dans notre texte, nous pouvons le tester avec les éléments suivants
f[x_, y_] := Flatten[Take[x, All, y]];
ListLogLogPlot[
Reverse[f[{##}, -1]],
AxesLabel -> {"Log (Rank)", "Log Counter"},
PlotLabel -> "Testing Zipf's Law"]
& @@
Take[
SortBy[
Tally[
StringSplit[ToLowerCase[b], RegularExpression["\\W+"]]
],
Last],
-1000]
Le résultat est (assez bien linéaire)
texte alternatif http://i46.tinypic.com/33fcmdk.jpg
Refactorisation du Regex (plus de fonction Select)
Suppression de 1 mot de caractère
Définition plus efficace de la fonction "f"
f = Flatten[Take[#1, All, #2]]&;
BarChart[
f[{##}, -1],
BarOrigin -> Left,
ChartLabels -> Placed[f[{##}, 1], After],
Axes -> None]
& @@
Take[
SortBy[
Tally[
StringSplit[ToLowerCase[Import[i]],
RegularExpression["(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"]]
],
Last],
-22]
BarChart[#2, BarOrigin->Left, ChartLabels->Placed[#1, After], Axes->None]&@@
Transpose@Take[SortBy[Tally@StringSplit[ToLowerCase@Import@i,
RegularExpression@"(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"],Last], -22]
f
remplacé par Transpose
et Slot
(#1
/#2
) arguments.f@x
au lieu de f[x]
lorsque c'est possible)Pas si court, mais maintenant probablement correct! Remarque, la version précédente n'affichait pas la première ligne des barres, ne mettait pas à l'échelle les barres correctement, téléchargeait le fichier au lieu de l'obtenir depuis stdin et n'incluait pas toute la verbosité C # requise. Vous pourriez facilement raser de nombreux coups si C # n'avait pas besoin de tant de merde supplémentaire. Peut-être que Powershell pourrait faire mieux.
using C=System.Console; // alias for Console
using System.Linq; // for Split, GroupBy, Select, OrderBy, etc.
class Class // must define a class
{
static void Main() // must define a Main
{
// split into words
var allwords = System.Text.RegularExpressions.Regex.Split(
// convert stdin to lowercase
C.In.ReadToEnd().ToLower(),
// eliminate stopwords and non-letters
@"(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|\W)+")
.GroupBy(x => x) // group by words
.OrderBy(x => -x.Count()) // sort descending by count
.Take(22); // take first 22 words
// compute length of longest bar + Word
var lendivisor = allwords.Max(y => y.Count() / (76.0 - y.Key.Length));
// prepare text to print
var toPrint = allwords.Select(x=>
new {
// remember bar pseudographics (will be used in two places)
Bar = new string('_',(int)(x.Count()/lendivisor)),
Word=x.Key
})
.ToList(); // convert to list so we can index into it
// print top of first bar
C.WriteLine(" " + toPrint[0].Bar);
toPrint.ForEach(x => // for each Word, print its bar and the Word
C.WriteLine("|" + x.Bar + "| " + x.Word));
}
}
422 caractères avec lendivisor en ligne (ce qui le rend 22 fois plus lent) dans le formulaire ci-dessous (nouvelles lignes utilisées pour certains espaces):
using System.Linq;using C=System.Console;class M{static void Main(){var
a=System.Text.RegularExpressions.Regex.Split(C.In.ReadToEnd().ToLower(),@"(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|\W)+").GroupBy(x=>x).OrderBy(x=>-x.Count()).Take(22);var
b=a.Select(x=>new{p=new string('_',(int)(x.Count()/a.Max(y=>y.Count()/(76d-y.Key.Length)))),t=x.Key}).ToList();C.WriteLine(" "+b[0].p);b.ForEach(x=>C.WriteLine("|"+x.p+"| "+x.t));}}
(Mis à jour à nouveau pour battre la version Ruby avec des astuces de golf plus sales, remplaçant split/[^a-z/,lc
avec lc=~/[a-z]+/g
, et en éliminant la vérification de la chaîne vide à un autre endroit. Celles-ci ont été inspirées par la Ruby, donc crédit à l'endroit où le crédit est dû.)
Mise à jour: maintenant avec Perl 5.10! Remplacez print
par say
et utilisez ~~
pour éviter un map
. Cela doit être appelé sur la ligne de commande en tant que Perl -E '<one-liner>' alice.txt
. Étant donné que le script entier est sur une seule ligne, l'écrire en une seule ligne ne devrait pas poser de problème :).
@s=qw/the and of to a i it in or is/;$c{$_}++foreach grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>;@s=sort{$c{$b}<=>$c{$a}}keys%c;$f=76-length$s[0];say" "."_"x$f;say"|"."_"x($c{$_}/$c{$s[0]}*$f)."| $_ "foreach@s[0..21];
Notez que cette version se normalise pour le cas. Cela ne raccourcit pas la solution, car la suppression de ,lc
(pour les minuscules) vous oblige à ajouter A-Z
au regex divisé, donc c'est un lavage.
Si vous êtes sur un système où une nouvelle ligne est un caractère et non deux, vous pouvez raccourcir cela de deux autres caractères en utilisant une nouvelle ligne littérale à la place de \n
. Cependant, je n'ai pas écrit l'exemple ci-dessus de cette façon, car c'est "plus clair" (ha!) De cette façon.
Voici une solution Perl généralement correcte, mais pas assez courte:
use strict;
use warnings;
my %short = map { $_ => 1 } qw/the and of to a i it in or is/;
my %count = ();
$count{$_}++ foreach grep { $_ && !$short{$_} } map { split /[^a-zA-Z]/ } (<>);
my @sorted = (sort { $count{$b} <=> $count{$a} } keys %count)[0..21];
my $widest = 76 - (length $sorted[0]);
print " " . ("_" x $widest) . "\n";
foreach (@sorted)
{
my $width = int(($count{$_} / $count{$sorted[0]}) * $widest);
print "|" . ("_" x $width) . "| $_ \n";
}
Ce qui suit est à peu près aussi court que possible tout en restant relativement lisible. (392 caractères).
%short = map { $_ => 1 } qw/the and of to a i it in or is/;
%count;
$count{$_}++ foreach grep { $_ && !$short{$_} } map { split /[^a-z]/, lc } (<>);
@sorted = (sort { $count{$b} <=> $count{$a} } keys %count)[0..21];
$widest = 76 - (length $sorted[0]);
print " " . "_" x $widest . "\n";
print"|" . "_" x int(($count{$_} / $count{$sorted[0]}) * $widest) . "| $_ \n" foreach @sorted;
$x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *
filter f($w){' '+'_'*$w
$x[-1..-22]|%{"|$('_'*($w*$_.Count/$x[-1].Count))| "+$_.Name}}
f(76..1|?{!((f $_)-match'.'*80)})[0]
(Le dernier saut de ligne n'est pas nécessaire, mais inclus ici pour plus de lisibilité.)
(Code actuel et mes fichiers de test disponibles dans mon référentiel SVN . J'espère que mes cas de test détectent les erreurs les plus courantes (longueur de barre, problèmes de correspondance d'expressions rationnelles et quelques autres))
Hypothèses:
Version détendue (137), car cela est désormais compté séparément, apparemment:
($x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *)[-1..-22]|%{"|$('_'*(76*$_.Count/$x[-1].Count))| "+$_.Name}
Les variations des longueurs de barre d'un caractère par rapport à d'autres solutions sont dues au fait que PowerShell utilise l'arrondi au lieu de la troncature lors de la conversion de nombres à virgule flottante en entiers. Étant donné que la tâche ne nécessitait qu'une longueur de barre proportionnelle, cela devrait être bien, cependant.
Par rapport à d'autres solutions, j'ai adopté une approche légèrement différente pour déterminer la longueur de barre la plus longue en essayant simplement et en prenant la longueur la plus élevée lorsqu'aucune ligne ne dépasse 80 caractères.
Une ancienne version expliquée peut être trouvée ici .
mise à jour 1: Hourra ! C'est une égalité avec JS Bangs ' solution . Je ne peux pas penser à un moyen de réduire davantage :)
mise à jour 2: joué un sale tour de golf. each
a été remplacé par map
pour enregistrer 1 caractère :)
mise à jour 3: Changé File.read
à IO.read
+2. Array.group_by
n'était pas très fructueux, remplacé par reduce
+6. La vérification insensible à la casse n'est pas nécessaire après une casse inférieure avec downcase
dans regex +1. Le tri dans l'ordre décroissant se fait facilement en annulant la valeur +6. Économies totales +15
mise à jour 4: [0]
plutôt que .first
, +3. (@ Shtééf)
mise à jour 5: Développez la variable l
sur place, +1. Développez la variable s
sur place, +2. (@ Shtééf)
mise à jour 6: utilisez l'ajout de chaînes plutôt que l'interpolation pour la première ligne, +2. (@ Shtééf)
w=(IO.read($_).downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).reduce(Hash.new 0){|m,o|m[o]+=1;m}.sort_by{|k,v|-v}.take 22;m=76-w[0][0].size;puts' '+'_'*m;w.map{|x,f|puts"|#{'_'*(f*1.0/w[0][1]*m)}| #{x} "}
mise à jour 7: j'ai parcouru pas mal de hoopla pour détecter la première itération à l'intérieur la boucle, en utilisant des variables d'instance. Tout ce que j'ai obtenu est +1, bien qu'il y ait peut-être un potentiel. Préserver la version précédente, car je crois que celle-ci est de la magie noire. (@ Shtééf)
(IO.read($_).downcase.scan(/[a-z]+/)-%w{the and of to a i it in or is}).reduce(Hash.new 0){|m,o|m[o]+=1;m}.sort_by{|k,v|-v}.take(22).map{|x,f|@f||(@f=f;puts' '+'_'*(@m=76-x.size));puts"|#{'_'*(f*1.0/@f*@m)}| #{x} "}
Version lisible
string = File.read($_).downcase
words = string.scan(/[a-z]+/i)
allowed_words = words - %w{the and of to a i it in or is}
sorted_words = allowed_words.group_by{ |x| x }.map{ |x,y| [x, y.size] }.sort{ |a,b| b[1] <=> a[1] }.take(22)
highest_frequency = sorted_words.first
highest_frequency_count = highest_frequency[1]
highest_frequency_Word = highest_frequency[0]
Word_length = highest_frequency_Word.size
widest = 76 - Word_length
puts " #{'_' * widest}"
sorted_words.each do |Word, freq|
width = (freq * 1.0 / highest_frequency_count) * widest
puts "|#{'_' * width}| #{Word} "
end
Utiliser:
echo "Alice.txt" | Ruby -ln GolfedWordFrequencies.rb
Sortie:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|____________________________| s
|____________________________| t
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
import sys,re
t=re.split('\W+',sys.stdin.read().lower())
r=sorted((-t.count(w),w)for w in set(t)if w not in'andithetoforinis')[:22]
for l,w in r:print(78-len(r[0][1]))*l/r[0][0]*'=',w
Permettant la liberté dans l'implémentation, j'ai construit une concaténation de chaînes qui contient tous les mots demandés pour l'exclusion (the, and, of, to, a, i, it, in, or, is
) - en plus elle exclut également les deux fameux "mots" s
et t
de l'exemple - et j'ai ajouté gratuitement l'exclusion pour an, for, he
. J'ai essayé toutes les concaténations de ces mots contre le corpus des mots d'Alice, de la Bible de King James et du fichier Jargon pour voir s'il y a des mots qui seront mal exclus par la chaîne. Et c'est ainsi que j'ai fini avec deux chaînes d'exclusion: itheandtoforinis
et andithetoforinis
.
PS. emprunté à d'autres solutions pour raccourcir le code.
=========================================================================== she
================================================================= you
============================================================== said
====================================================== alice
================================================ was
============================================ that
===================================== as
================================= her
============================== at
============================== with
=========================== on
=========================== all
======================== this
======================== had
======================= but
====================== be
====================== not
===================== they
==================== so
=================== very
=================== what
================= little
En ce qui concerne les mots à ignorer, on pourrait penser qu'ils seraient tirés de la liste des mots les plus utilisés en anglais. Cette liste dépend du corpus de texte utilisé. Par l'une des listes les plus populaires ( http://en.wikipedia.org/wiki/Most_common_words_in_English , http://www.english-for-students.com/Frequently-Used -Words.html , http://www.sporcle.com/games/common_english_words.php ), les 10 premiers mots sont: the be(am/are/is/was/were) to of and a in that have I
Les 10 premiers mots du texte d'Alice au pays des merveilles sont the and to a of it she i you said
Les 10 premiers mots du fichier de jargon (v4.4.7) sont the a of to and in is that or for
La question est donc de savoir pourquoi or
a été inclus dans la liste d'ignorance du problème, où il est ~ 30e en popularité alors que le mot that
(8e plus utilisé) ne l'est pas. etc, etc. Par conséquent, je pense que la liste des ignorés devrait être fournie dynamiquement (ou pourrait être omise).
L'idée alternative serait simplement de sauter les 10 premiers mots du résultat - ce qui en fait raccourcirait la solution (élémentaire - ne devrait afficher que les 11e à 32e entrées).
Le graphique dessiné dans le code ci-dessus est simplifié (en utilisant un seul caractère pour les barres). Si l'on veut reproduire exactement le graphique de la description du problème (ce qui n'était pas obligatoire), ce code le fera:
import sys,re
t=re.split('\W+',sys.stdin.read().lower())
r=sorted((-t.count(w),w)for w in set(t)-set(sys.argv))[:22]
h=min(9*l/(77-len(w))for l,w in r)
print'',9*r[0][0]/h*'_'
for l,w in r:print'|'+9*l/h*'_'+'|',w
Je prends un problème avec le choix quelque peu aléatoire des 10 mots à exclure the, and, of, to, a, i, it, in, or, is
Donc ceux-ci doivent être passés en tant que paramètres de ligne de commande, comme ceci:python WordFrequencyChart.py the and of to a i it in or is <"Alice's Adventures in Wonderland.txt"
Il s'agit de 213 caractères + 30 si nous tenons compte de la liste d'ignorations "d'origine" transmise sur la ligne de commande = 243
PS. Le second code fait également un "ajustement" pour les longueurs de tous les premiers mots, donc aucun d'entre eux ne débordera en cas de dégénérescence.
_______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|_____________________________________________________| said
|______________________________________________| alice
|_________________________________________| was
|______________________________________| that
|_______________________________| as
|____________________________| her
|__________________________| at
|__________________________| with
|_________________________| s
|_________________________| t
|_______________________| on
|_______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|___________________| not
|_________________| they
|_________________| so
(Un saut de ligne dans main
a été ajouté pour plus de lisibilité, et aucun saut de ligne n'est nécessaire à la fin de la dernière ligne.)
import Data.List
import Data.Char
l=length
t=filter
m=map
f c|isAlpha c=toLower c|0<1=' '
h w=(-l w,head w)
x!(q,w)='|':replicate(minimum$m(q?)x)'_'++"| "++w
q?(g,w)=q*(77-l w)`div`g
b x=m(x!)x
a(l:r)=(' ':t(=='_')l):l:r
main=interact$unlines.a.b.take 22.sort.m h.group.sort
.t(`notElem`words"the and of to a i it in or is").words.m f
Son fonctionnement est mieux vu en lisant l'argument à interact
à l'envers:
map f
alphabétique en minuscules, remplace tout le reste par des espaces.words
produit une liste de mots, supprimant les espaces de séparation.filter (
notElemwords "the and of to a i it in or is")
supprime toutes les entrées contenant des mots interdits.group . sort
trie les mots et regroupe les mots identiques dans des listes.map h
mappe chaque liste de mots identiques à un Tuple de la forme (-frequency, Word)
.take 22 . sort
trie les tuples par fréquence décroissante (la première entrée de Tuple) et ne conserve que les 22 premiers tuples.b
mappe les tuples aux barres (voir ci-dessous).a
ajoute la première ligne de soulignements pour compléter la barre supérieure.unlines
joint toutes ces lignes avec des retours à la ligne.Le plus difficile est d'obtenir la bonne longueur de barre. J'ai supposé que seuls les traits de soulignement comptaient pour la longueur de la barre, donc ||
serait une barre de longueur nulle. La fonction b
mappe c x
sur x
, où x
est la liste des histogrammes. La liste entière est passée à c
, afin que chaque invocation de c
puisse calculer le facteur d'échelle pour elle-même en appelant u
. De cette façon, j'évite d'utiliser des mathématiques ou des rationnels à virgule flottante, dont les fonctions de conversion et les importations consomment de nombreux caractères.
Notez l'astuce d'utiliser -frequency
. Cela supprime la nécessité de reverse
le sort
depuis le tri (croissant) -frequency
placera les mots avec la plus grande fréquence en premier. Plus tard, dans la fonction u
, deux -frequency
les valeurs sont multipliées, ce qui annulera la négation.
Cette solution prend en compte la dernière exigence que la plupart des puristes ont choisi d'ignorer. Cela a coûté 170 caractères!
Utilisation: php.exe <this.php> <file.txt>
Minifié:
<?php $a=array_count_values(array_filter(preg_split('/[^a-z]/',strtolower(file_get_contents($argv[1])),-1,1),function($x){return !preg_match("/^(.|the|and|of|to|it|in|or|is)$/",$x);}));arsort($a);$a=array_slice($a,0,22);function R($a,$F,$B){$r=array();foreach($a as$x=>$f){$l=strlen($x);$r[$x]=$b=$f*$B/$F;if($l+$b>76)return R($a,$f,76-$l);}return$r;}$c=R($a,max($a),76-strlen(key($a)));foreach($a as$x=>$f)echo '|',str_repeat('-',$c[$x]),"| $x\n";?>
Lisible par l'homme:
<?php
// Read:
$s = strtolower(file_get_contents($argv[1]));
// Split:
$a = preg_split('/[^a-z]/', $s, -1, PREG_SPLIT_NO_EMPTY);
// Remove unwanted words:
$a = array_filter($a, function($x){
return !preg_match("/^(.|the|and|of|to|it|in|or|is)$/",$x);
});
// Count:
$a = array_count_values($a);
// Sort:
arsort($a);
// Pick top 22:
$a=array_slice($a,0,22);
// Recursive function to adjust bar widths
// according to the last requirement:
function R($a,$F,$B){
$r = array();
foreach($a as $x=>$f){
$l = strlen($x);
$r[$x] = $b = $f * $B / $F;
if ( $l + $b > 76 )
return R($a,$f,76-$l);
}
return $r;
}
// Apply the function:
$c = R($a,max($a),76-strlen(key($a)));
// Output:
foreach ($a as $x => $f)
echo '|',str_repeat('-',$c[$x]),"| $x\n";
?>
Sortie:
|-------------------------------------------------------------------------| she
|---------------------------------------------------------------| you
|------------------------------------------------------------| said
|-----------------------------------------------------| alice
|-----------------------------------------------| was
|-------------------------------------------| that
|------------------------------------| as
|--------------------------------| her
|-----------------------------| at
|-----------------------------| with
|--------------------------| on
|--------------------------| all
|-----------------------| this
|-----------------------| for
|-----------------------| had
|-----------------------| but
|----------------------| be
|---------------------| not
|--------------------| they
|--------------------| so
|-------------------| very
|------------------| what
Lorsqu'il y a un long mot, les barres sont ajustées correctement:
|--------------------------------------------------------| she
|---------------------------------------------------| thisisareallylongwordhere
|-------------------------------------------------| you
|-----------------------------------------------| said
|-----------------------------------------| alice
|------------------------------------| was
|---------------------------------| that
|---------------------------| as
|-------------------------| her
|-----------------------| with
|-----------------------| at
|--------------------| on
|--------------------| all
|------------------| this
|------------------| for
|------------------| had
|-----------------| but
|-----------------| be
|----------------| not
|---------------| they
|---------------| so
|--------------| very
x={};p='|';e=' ';z=[];c=77
while(l=readline())l.toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,function(y)x[y]?x[y].c++:z.Push(x[y]={w:y,c:1}))
z=z.sort(function(a,b)b.c-a.c).slice(0,22)
for each(v in z){v.r=v.c/z[0].c
c=c>(l=(77-v.w.length)/v.r)?l:c}for(k in z){v=z[k]
s=Array(v.r*c|0).join('_')
if(!+k)print(e+s+e)
print(p+s+p+e+v.w)}
Malheureusement, la for([k,v]in z)
de la version Rhino ne semble pas vouloir fonctionner dans SpiderMonkey, et readFile()
est un peu plus facile que d'utiliser readline()
mais en passant à 1.8 nous permet d'utiliser des fermetures de fonctions pour couper quelques lignes de plus ....
Ajout d'espaces pour la lisibilité:
x={};p='|';e=' ';z=[];c=77
while(l=readline())
l.toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,
function(y) x[y] ? x[y].c++ : z.Push( x[y] = {w: y, c: 1} )
)
z=z.sort(function(a,b) b.c - a.c).slice(0,22)
for each(v in z){
v.r=v.c/z[0].c
c=c>(l=(77-v.w.length)/v.r)?l:c
}
for(k in z){
v=z[k]
s=Array(v.r*c|0).join('_')
if(!+k)print(e+s+e)
print(p+s+p+e+v.w)
}
tilisation:js golf.js < input.txt
Sortie:
_________________________________________________________________________ | _________________________________________________________________________ | elle | _______________________________________________________________ | vous | ____________________________________________________________ | dit | ____________________________________________________ | alice | ______________________________________________ | était | ___________________________________________ | | ___________________________________ | comme | ________________________________ | son | _____________________________ | à | _____________________________ | avec | ____________________________ | s | ____________________________ | t | __________________________ | le | _________________________ | tous | _______________________ | ce | ______________________ | pour | ______________________ | avait | ______________________ | mais | _____________________ | être | _____________________ | pas | ___________________ | ils | ___________________ | alors
(version de base - ne gère pas les largeurs de barre correctement)
Je pense que ma logique de tri est désactivée, mais .. je ne sais pas. Brainfart fixe.
Minified (abuser de \n
Est parfois interprété comme un ;
):
x={};p='|';e=' ';z=[]
readFile(arguments[0]).toLowerCase().replace(/\b(?!(the|and|of|to|a|i[tns]?|or)\b)\w+/g,function(y){x[y]?x[y].c++:z.Push(x[y]={w:y,c:1})})
z=z.sort(function(a,b){return b.c-a.c}).slice(0,22)
for([k,v]in z){s=Array((v.c/z[0].c)*70|0).join('_')
if(!+k)print(e+s+e)
print(p+s+p+e+v.w)}
Je suppose que l'utilisation de Counter est une sorte de tricherie :) Je viens de lire à ce sujet il y a environ une semaine, donc c'était l'occasion idéale de voir comment cela fonctionne.
import re,collections
o=collections.Counter([w for w in re.findall("[a-z]+",open("!").read().lower())if w not in"a and i in is it of or the to".split()]).most_common(22)
print('\n'.join('|'+76*v//o[0][1]*'_'+'| '+k for k,v in o))
Imprime:
|____________________________________________________________________________| she
|__________________________________________________________________| you
|_______________________________________________________________| said
|_______________________________________________________| alice
|_________________________________________________| was
|_____________________________________________| that
|_____________________________________| as
|__________________________________| her
|_______________________________| with
|_______________________________| at
|______________________________| s
|_____________________________| t
|____________________________| on
|___________________________| all
|________________________| this
|________________________| for
|________________________| had
|________________________| but
|______________________| be
|______________________| not
|_____________________| they
|____________________| so
Une partie du code a été "empruntée" à la solution d'AKX.
Certaines parties ont été inspirées par les soumissions antérieures de Perl/Ruby, quelques idées similaires ont été élaborées indépendamment, les autres sont originales. La version plus courte incorpore également certaines choses que j'ai vues/apprises d'autres soumissions.
Original:
$k{$_}++for grep{$_!~/^(the|and|of|to|a|i|it|in|or|is)$/}map{lc=~/[a-z]+/g}<>;@t=sort{$k{$b}<=>$k{$a}}keys%k;$l=76-length$t[0];printf" %s
",'_'x$l;printf"|%s| $_
",'_'x int$k{$_}/$k{$t[0]}*$l for@t[0..21];
Dernière version jusqu'à 191 caractères:
/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;@e=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";$r=(76-y///c)/$k{$_=$e[0]};map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
"}@e[0,0..21]
Dernière version jusqu'à 189 caractères:
/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;@_=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";$r=(76-m//)/$k{$_=$_[0]};map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
"}@_[0,0..21]
Cette version (205 caractères) représente les lignes avec des mots plus longs que ce qui serait trouvé plus tard.
/^(the|and|of|to|.|i[tns]|or)$/||$k{$_}++for map{lc=~/[a-z]+/g}<>;($r)=sort{$a<=>$b}map{(76-y///c)/$k{$_}}@e=sort{$k{$b}<=>$k{$a}}keys%k;$n=" %s
";map{printf$n,'_'x($k{$_}*$r),$_;$n="|%s| %s
";}@e[0,0..21]
$/=\0;/^(the|and|of|to|.|i[tns]|or)$/i||$x{lc$_}++for<>=~/[a-z]+/gi;map{$z=$x{$_};$y||{$y=(76-y///c)/$z}&&warn" "."_"x($z*$y)."\n";printf"|%.78s\n","_"x($z*$y)."| $_"}(sort{$x{$b}<=>$x{$a}}keys%x)[0..21]
Implémentation alternative et complète, y compris le comportement indiqué (barre de compression globale) pour le cas pathologique dans lequel le mot secondaire est à la fois populaire et suffisamment long pour se combiner à plus de 80 caractères (cette implémentation est de 231 caractères):
$/=\0;/^(the|and|of|to|.|i[tns]|or)$/i||$x{lc$_}++for<>=~/[a-z]+/gi;@e=(sort{$x{$b}<=>$x{$a}}keys%x)[0..21];for(@e){$p=(76-y///c)/$x{$_};($y&&$p>$y)||($y=$p)}warn" "."_"x($x{$e[0]}*$y)."\n";for(@e){warn"|"."_"x($x{$_}*$y)."| $_\n"}
La spécification n'indiquait nulle part que cela devait aller à STDOUT, j'ai donc utilisé warn () de Perl au lieu d'imprimer - quatre caractères enregistrés là. Carte utilisée au lieu de foreach, mais j'ai l'impression qu'il pourrait encore y avoir plus d'économies dans la division (join ()). Pourtant, il est descendu à 203 - pourrait dormir dessus. Au moins Perl est désormais sous le nombre de caractères "Shell, grep, tr, grep, sort, uniq, sort, head, Perl" pour l'instant;)
PS: Reddit dit "Salut";)
Mise à jour: suppression de join () en faveur de l'affectation et de la jointure de conversion scalaire implicite. Jusqu'à 202. Veuillez également noter que j'ai profité de la règle facultative "ignorer les mots à 1 lettre" pour raser 2 caractères, alors gardez à l'esprit que le nombre de fréquences reflétera cela.
Mise à jour 2: permutation de l'affectation et jointure implicite pour avoir tué $/pour obtenir le fichier en une seule fois en utilisant <> en premier lieu. Même taille, mais plus méchant. Échangé si (! $ Y) {} pour $ y || {} &&, sauvé 1 char supplémentaire => 201.
Mise à jour 3: pris le contrôle des minuscules tôt (lc <>) en déplaçant lc hors du bloc de carte - Échange les deux expressions régulières pour ne plus utiliser l'option/i, car elle n'est plus nécessaire. Construction conditionnelle x? Y: z conditionnelle échangée pour le Perlgolf traditionnel || construction conditionnelle implicite - /^...$/i?1:$x{$}++ pour /^...$/||$x{$} ++ Enregistré trois caractères! => 198, a franchi la barrière des 200. Pourrait dormir bientôt ... peut-être.
Mise à jour 4: La privation de sommeil m'a rendu fou. Bien. Plus fou. En pensant que cela n'a qu'à analyser les fichiers de texte heureux normaux, je l'ai fait abandonner s'il atteint une valeur nulle. Enregistré deux caractères. "Longueur" remplacé par le 1-caractère plus court (et beaucoup plus golfique) y /// c - vous m'entendez, GolfScript ?? Je viens pour toi!!! sanglot
Mise à jour 5: Sleep dep m'a fait oublier la limite de 22 lignes et la limite de ligne suivante. Sauvegardez jusqu'à 208 avec ceux traités. Pas trop mal, 13 personnages à gérer ce n'est pas la fin du monde. Joué avec l'eval en ligne regex de Perl, mais ayant du mal à le faire fonctionner et enregistrer les caractères ... lol. Mise à jour de l'exemple pour correspondre à la sortie actuelle.
Mise à jour 6: Suppression des accolades inutiles protégeant (...) pour, car le bonbon syntaxique ++ permet de le heurter heureusement contre le pour. Merci à la contribution de Chas. Owens (rappelant mon cerveau fatigué), a obtenu la solution de classe de caractère i [tns] là-dedans. Redescendre à 203.
Mise à jour 7: Ajout d'un deuxième travail, mise en œuvre complète des spécifications (y compris le comportement complet de compression des barres pour les mots longs secondaires, au lieu de la troncature que la plupart des gens font, sur la base des spécifications originales sans l'exemple pathologique)
Exemples:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
|___________________| very
|__________________| what
Mise en œuvre alternative dans l'exemple de cas pathologique:
_______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| with
|_________________________| at
|_______________________| on
|______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| so
|________________| very
|________________| what
Strightforward: obtenez une séquence a
de paires Word-count, trouvez le meilleur multiplicateur Word-count-per-column k
, puis imprimez les résultats.
let a=
stdin.ReadToEnd().Split(" .?!,\":;'\r\n".ToCharArray(),enum 1)
|>Seq.map(fun s->s.ToLower())|>Seq.countBy id
|>Seq.filter(fun(w,n)->not(set["the";"and";"of";"to";"a";"i";"it";"in";"or";"is"].Contains w))
|>Seq.sortBy(fun(w,n)-> -n)|>Seq.take 22
let k=a|>Seq.map(fun(w,n)->float(78-w.Length)/float n)|>Seq.min
let u n=String.replicate(int(float(n)*k)-2)"_"
printfn" %s "(u(snd(Seq.nth 0 a)))
for(w,n)in a do printfn"|%s| %s "(u n)w
Exemple (j'ai des nombres de fréquences différents de vous, je ne sais pas pourquoi):
% app.exe < Alice.txt
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|___________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|____________________________| t
|____________________________| s
|__________________________| on
|_________________________| all
|_______________________| this
|______________________| had
|______________________| for
|_____________________| but
|_____________________| be
|____________________| not
|___________________| they
|__________________| so
import re
W,x={},"a and i in is it of or the to".split()
[W.__setitem__(w,W.get(w,0)-1)for w in re.findall("[a-z]+",file("11.txt").read().lower())if w not in x]
W=sorted(W.items(),key=lambda p:p[1])[:22]
bm=(76.-len(W[0][0]))/W[0][1]
U=lambda n:"_"*int(n*bm)
print "".join(("%s\n|%s| %s "%((""if i else" "+U(n)),U(n),w))for i,(w,n)in enumerate(W))
Sortie:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|____________________________| s
|____________________________| t
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
(après avoir corrigé le formatage de sortie; corrigé le problème des contractions; peaufiné; peaufiné à nouveau; supprimé une étape de tri totalement inutile; peaufiné encore une fois; et encore (oups celui-ci a cassé le formatage); Tweak some plus; relever le défi de Matt je désespérément Tweak donc plus; trouvé un autre endroit pour en sauver quelques-uns, mais en ai donné deux pour corriger le bug de la longueur de la barre)
Heh heh! Je suis momentanément en avance sur la solution [Matt's JavaScript] [1]contre-défi! ;) et [python AKX] [2].
Le problème semble appeler un langage qui implémente des tableaux associatifs natifs, donc bien sûr j'en ai choisi un avec un ensemble d'opérateurs horriblement déficient . En particulier, vous ne pouvez pas contrôler l'ordre dans lequel awk offre les éléments d'une carte de hachage, je scanne donc à plusieurs reprises la carte entière pour trouver la plus nombreux éléments, imprimez-le et supprimez-le du tableau.
Tout cela est terriblement inefficace, avec toutes les golfifcations que j'ai faites, cela est devenu aussi horrible.
Minifié:
{gsub("[^a-zA-Z]"," ");for(;NF;NF--)a[tolower($NF)]++}
END{split("the and of to a i it in or is",b," ");
for(w in b)delete a[b[w]];d=1;for(w in a){e=a[w]/(78-length(w));if(e>d)d=e}
for(i=22;i;--i){e=0;for(w in a)if(a[w]>e)e=a[x=w];l=a[x]/d-2;
t=sprintf(sprintf("%%%dc",l)," ");gsub(" ","_",t);if(i==22)print" "t;
print"|"t"| "x;delete a[x]}}
sauts de ligne pour plus de clarté uniquement: ils ne sont pas nécessaires et ne doivent pas être comptés.
Sortie:
$ gawk -f wordfreq.awk.min < 11.txt
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|____________________________________________________| alice
|______________________________________________| was
|__________________________________________| that
|___________________________________| as
|_______________________________| her
|____________________________| with
|____________________________| at
|___________________________| s
|___________________________| t
|_________________________| on
|_________________________| all
|______________________| this
|______________________| for
|______________________| had
|_____________________| but
|____________________| be
|____________________| not
|___________________| they
|__________________| so
$ sed 's/you/superlongstring/gI' 11.txt | gawk -f wordfreq.awk.min
______________________________________________________________________
|______________________________________________________________________| she
|_____________________________________________________________| superlongstring
|__________________________________________________________| said
|__________________________________________________| alice
|____________________________________________| was
|_________________________________________| that
|_________________________________| as
|______________________________| her
|___________________________| with
|___________________________| at
|__________________________| s
|__________________________| t
|________________________| on
|________________________| all
|_____________________| this
|_____________________| for
|_____________________| had
|____________________| but
|___________________| be
|___________________| not
|__________________| they
|_________________| so
Lisible; 633 caractères (à l'origine 949):
{
gsub("[^a-zA-Z]"," ");
for(;NF;NF--)
a[tolower($NF)]++
}
END{
# remove "short" words
split("the and of to a i it in or is",b," ");
for (w in b)
delete a[b[w]];
# Find the bar ratio
d=1;
for (w in a) {
e=a[w]/(78-length(w));
if (e>d)
d=e
}
# Print the entries highest count first
for (i=22; i; --i){
# find the highest count
e=0;
for (w in a)
if (a[w]>e)
e=a[x=w];
# Print the bar
l=a[x]/d-2;
# make a string of "_" the right length
t=sprintf(sprintf("%%%dc",l)," ");
gsub(" ","_",t);
if (i==22) print" "t;
print"|"t"| "x;
delete a[x]
}
}
Ceci est incomplet, mais pour l'enfer, voici la fréquence des mots comptant la moitié du problème en 192 octets:
curl -s http://www.gutenberg.org/files/11/11.txt|sed -e 's@[^a-z]@\n@gi'|tr '[:upper:]' '[:lower:]'|egrep -v '(^[^a-z]*$|\b(the|and|of|to|a|i|it|in|or|is)\b)' |sort|uniq -c|sort -n|tail -n 22
Je suis un débutant LISP, et c'est une tentative d'utiliser une table de hachage pour compter (donc probablement pas la méthode la plus compacte).
(flet((r()(let((x(read-char t nil)))(and x(char-downcase x)))))(do((c(
make-hash-table :test 'equal))(w NIL)(x(r)(r))y)((not x)(maphash(lambda
(k v)(if(not(find k '("""the""and""of""to""a""i""it""in""or""is"):test
'equal))(Push(cons k v)y)))c)(setf y(sort y #'> :key #'cdr))(setf y
(subseq y 0(min(length y)22)))(let((f(apply #'min(mapcar(lambda(x)(/(-
76.0(length(car x)))(cdr x)))y))))(flet((o(n)(dotimes(i(floor(* n f)))
(write-char #\_))))(write-char #\Space)(o(cdar y))(write-char #\Newline)
(dolist(x y)(write-char #\|)(o(cdr x))(format t "| ~a~%"(car x))))))
(cond((char<= #\a x #\z)(Push x w))(t(incf(gethash(concatenate 'string(
reverse w))c 0))(setf w nil)))))
peut être exécuté par exemple avec cat alice.txt | clisp -C golf.LISP
.
Sous forme lisible est
(flet ((r () (let ((x (read-char t nil)))
(and x (char-downcase x)))))
(do ((c (make-hash-table :test 'equal)) ; the Word count map
w y ; current Word and final Word list
(x (r) (r))) ; iteration over all chars
((not x)
; make a list with (Word . count) pairs removing stopwords
(maphash (lambda (k v)
(if (not (find k '("" "the" "and" "of" "to"
"a" "i" "it" "in" "or" "is")
:test 'equal))
(Push (cons k v) y)))
c)
; sort and truncate the list
(setf y (sort y #'> :key #'cdr))
(setf y (subseq y 0 (min (length y) 22)))
; find the scaling factor
(let ((f (apply #'min
(mapcar (lambda (x) (/ (- 76.0 (length (car x)))
(cdr x)))
y))))
; output
(flet ((outx (n) (dotimes (i (floor (* n f))) (write-char #\_))))
(write-char #\Space)
(outx (cdar y))
(write-char #\Newline)
(dolist (x y)
(write-char #\|)
(outx (cdr x))
(format t "| ~a~%" (car x))))))
; add alphabetic to current Word, and bump Word counter
; on non-alphabetic
(cond
((char<= #\a x #\z)
(Push x w))
(t
(incf (gethash (concatenate 'string (reverse w)) c 0))
(setf w nil)))))
200 (légèrement cassé)199197195193187 185 caractères. Les deux dernières nouvelles lignes sont importantes. Conforme à la spécification.
map$X{+lc}+=!/^(.|the|and|to|i[nst]|o[rf])$/i,/[a-z]+/gfor<>;
$n=$n>($:=$X{$_}/(76-y+++c))?$n:$:for@w=(sort{$X{$b}-$X{$a}}%X)[0..21];
die map{$U='_'x($X{$_}/$n);" $U
"x!$z++,"|$U| $_
"}@w
La première ligne charge le nombre de mots valides dans %X
.
La deuxième ligne calcule le facteur d'échelle minimal de sorte que toutes les lignes de sortie soient <= 80 caractères.
La troisième ligne (contient deux caractères de nouvelle ligne) produit la sortie.
Il ressemble beaucoup au code obscurci et utilise glib pour la chaîne, la liste et le hachage. Nombre de caractères avec wc -m
dit 828. Il ne prend pas en compte les mots à caractère unique. Pour calculer la longueur maximale de la barre, il faut considérer le mot le plus long possible parmi tous, pas seulement le premier 22. Est-ce un écart par rapport à la spécification?
Il ne gère pas les échecs et ne libère pas de mémoire utilisée.
#include <glib.h>
#define S(X)g_string_##X
#define H(X)g_hash_table_##X
GHashTable*h;int m,w=0,z=0;y(const void*a,const void*b){int*A,*B;A=H(lookup)(h,a);B=H(lookup)(h,b);return*B-*A;}void p(void*d,void*u){int *v=H(lookup)(h,d);if(w<22){g_printf("|");*v=*v*(77-z)/m;while(--*v>=0)g_printf("=");g_printf("| %s\n",d);w++;}}main(c){int*v;GList*l;GString*s=S(new)(NULL);h=H(new)(g_str_hash,g_str_equal);char*n[]={"the","and","of","to","it","in","or","is"};while((c=getchar())!=-1){if(isalpha(c))S(append_c)(s,tolower(c));else{if(s->len>1){for(c=0;c<8;c++)if(!strcmp(s->str,n[c]))goto x;if((v=H(lookup)(h,s->str))!=NULL)++*v;else{z=MAX(z,s->len);v=g_malloc(sizeof(int));*v=1;H(insert)(h,g_strdup(s->str),v);}}x:S(truncate)(s,0);}}l=g_list_sort(H(get_keys)(h),y);m=*(int*)H(lookup)(h,g_list_first(l)->data);g_list_foreach(l,p,NULL);}
Mises à jour avant le premier 742 : regex amélioré, suppression des types paramétrés superflus, suppression des espaces superflus.
Mise à jour 742> 744 caractères : correction du hack de longueur fixe. Cela ne dépend que du 1er mot, pas des autres mots (pour l'instant). Trouvé plusieurs endroits pour raccourcir le code (\\s
Dans regex remplacé par et ArrayList
remplacé par Vector
). Je cherche maintenant un moyen rapide de supprimer la dépendance Commons IO et la lecture de stdin.
Mise à jour 744> 752 caractères : j'ai supprimé la dépendance des communs. Il lit maintenant depuis stdin. Collez le texte dans stdin et appuyez sur Ctrl+Z
Pour obtenir le résultat.
Mise à jour 752> 742 caractères : j'ai supprimé public
et un espace, fait du nom de classe 1 caractère au lieu de 2 et il ignore maintenant une lettre mots.
Mise à jour 742> 714 caractères : mise à jour selon les commentaires de Carl: suppression de l'affectation redondante (742> 730), remplacement de m.containsKey(k)
par m.get(k)!=null
(730> 728), introduction de la sous-chaîne de ligne (728> 714).
Mise à jour 714> 680 caractères : mise à jour selon les commentaires de Rotsor: calcul de la taille de la barre amélioré pour supprimer le casting inutile et split()
améliorée pour supprimer inutile replaceAll()
.
import Java.util.*;class F{public static void main(String[]a)throws Exception{StringBuffer b=new StringBuffer();for(int c;(c=System.in.read())>0;b.append((char)c));final Map<String,Integer>m=new HashMap();for(String w:b.toString().toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(w,m.get(w)!=null?m.get(w)+1:1);List<String>l=new Vector(m.keySet());Collections.sort(l,new Comparator(){public int compare(Object l,Object r){return m.get(r)-m.get(l);}});int c=76-l.get(0).length();String s=new String(new char[c]).replace('\0','_');System.out.println(" "+s);for(String w:l.subList(0,22))System.out.println("|"+s.substring(0,m.get(w)*c/m.get(l.get(0)))+"| "+w);}}
Version plus lisible:
import Java.util.*;
class F{
public static void main(String[]a)throws Exception{
StringBuffer b=new StringBuffer();for(int c;(c=System.in.read())>0;b.append((char)c));
final Map<String,Integer>m=new HashMap();for(String w:b.toString().toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(w,m.get(w)!=null?m.get(w)+1:1);
List<String>l=new Vector(m.keySet());Collections.sort(l,new Comparator(){public int compare(Object l,Object r){return m.get(r)-m.get(l);}});
int c=76-l.get(0).length();String s=new String(new char[c]).replace('\0','_');System.out.println(" "+s);
for(String w:l.subList(0,22))System.out.println("|"+s.substring(0,m.get(w)*c/m.get(l.get(0)))+"| "+w);
}
}
Sortie:
_________________________________________________________________________ | _________________________________________________________________________ | elle | _______________________________________________________________ | vous | ____________________________________________________________ | dit | _____________________________________________________ | alice | _______________________________________________ | était | ___________________________________________ | que | ____________________________________ | comme | ________________________________ | son | _____________________________ | avec | _____________________________ | à | __________________________ | le | __________________________ | tous | _______________________ | ce | _______________________ | pour | _______________________ | avait | _______________________ | mais | ______________________ | être | _____________________ | pas | ____________________ | ils | ____________________ | donc | ___________________ | très | __________________ | quoi
Ça craint que Java n'a pas String#join()
et fermetures (pour l'instant).
Modifier par Rotsor:
J'ai apporté plusieurs modifications à votre solution:
Le code condensé est 688711 684 caractères de long:
import Java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,x,y,g=22;for(;(j=System.in.read())>0;w+=(char)j);for(String W:w.toLowerCase().split("(\\b(.|the|and|of|to|i[tns]|or)\\b|\\W)+"))m.put(W,m.get(W)!=null?m.get(W)+1:1);l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}}
La version rapide (720 693 caractères)
import Java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,x,y,g=22;for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";}}l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}}
Version plus lisible:
import Java.util.*;class F{public static void main(String[]l)throws Exception{
Map<String,Integer>m=new HashMap();String w="";
int i=0,k=0,j=8,x,y,g=22;
for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{
if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";
}}
l=m.keySet().toArray(l);x=l.length;if(x<g)g=x;
for(;i<g;++i)for(j=i;++j<x;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}
for(;k<g;k++){x=76-l[k].length();y=m.get(l[k]);if(k<1||y*i>x*j){i=x;j=y;}}
String s=new String(new char[m.get(l[0])*i/j]).replace('\0','_');
System.out.println(" "+s);
for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/j)+"| "+w);}}
}
La version sans amélioration du comportement est de 615 caractères:
import Java.util.*;class F{public static void main(String[]l)throws Exception{Map<String,Integer>m=new HashMap();String w="";int i=0,k=0,j=8,g=22;for(;j>0;){j=System.in.read();if(j>90)j-=32;if(j>64&j<91)w+=(char)j;else{if(!w.matches("^(|.|THE|AND|OF|TO|I[TNS]|OR)$"))m.put(w,m.get(w)!=null?m.get(w)+1:1);w="";}}l=m.keySet().toArray(l);for(;i<g;++i)for(j=i;++j<l.length;)if(m.get(l[i])<m.get(l[j])){w=l[i];l[i]=l[j];l[j]=w;}i=76-l[0].length();String s=new String(new char[i]).replace('\0','_');System.out.println(" "+s);for(k=0;k<g;k++){w=l[k];System.out.println("|"+s.substring(0,m.get(w)*i/m.get(l[0]))+"| "+w);}}}
Tout d'abord, une version lisible en 592 caractères:
object Alice {
def main(args:Array[String]) {
val s = io.Source.fromFile(args(0))
val words = s.getLines.flatMap("(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(_)).map(_.toLowerCase)
val freqs = words.foldLeft(Map[String, Int]())((countmap, Word) => countmap + (Word -> (countmap.getOrElse(Word, 0)+1)))
val sortedFreqs = freqs.toList.sort((a, b) => a._2 > b._2)
val top22 = sortedFreqs.take(22)
val highestWord = top22.head._1
val highestCount = top22.head._2
val widest = 76 - highestWord.length
println(" " + "_" * widest)
top22.foreach(t => {
val width = Math.round((t._2 * 1.0 / highestCount) * widest).toInt
println("|" + "_" * width + "| " + t._1)
})
}
}
La sortie de la console ressemble à ceci:
$ scalac alice.scala
$ scala Alice aliceinwonderland.txt
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| at
|______________________________| with
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what
Nous pouvons faire une minification agressive et la réduire à 415 caractères:
object A{def main(args:Array[String]){val l=io.Source.fromFile(args(0)).getLines.flatMap("(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(_)).map(_.toLowerCase).foldLeft(Map[String, Int]())((c,w)=>c+(w->(c.getOrElse(w,0)+1))).toList.sort((a,b)=>a._2>b._2).take(22);println(" "+"_"*(76-l.head._1.length));l.foreach(t=>println("|"+"_"*Math.round((t._2*1.0/l.head._2)*(76-l.head._1.length)).toInt+"| "+t._1))}}
La session de console ressemble à ceci:
$ scalac a.scala
$ scala A aliceinwonderland.txt
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| at
|______________________________| with
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what
Je suis sûr qu'un expert Scala pourrait faire encore mieux.
Mise à jour: Dans les commentaires, Thomas a donné une version encore plus courte, à 368 caractères:
object A{def main(a:Array[String]){val t=(Map[String, Int]()/:(for(x<-io.Source.fromFile(a(0)).getLines;y<-"(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r findAllIn x) yield y.toLowerCase).toList)((c,x)=>c+(x->(c.getOrElse(x,0)+1))).toList.sortBy(_._2).reverse.take(22);val w=76-t.head._1.length;print(" "+"_"*w);t map (s=>"\n|"+"_"*(s._2*w/t.head._2)+"| "+s._1) foreach print}}
Lisiblement, à 375 caractères:
object Alice {
def main(a:Array[String]) {
val t = (Map[String, Int]() /: (
for (
x <- io.Source.fromFile(a(0)).getLines
y <- "(?i)\\w+\\b(?<!\\bthe|and|of|to|a|i|it|in|or|is)".r.findAllIn(x)
) yield y.toLowerCase
).toList)((c, x) => c + (x -> (c.getOrElse(x, 0) + 1))).toList.sortBy(_._2).reverse.take(22)
val w = 76 - t.head._1.length
print (" "+"_"*w)
t.map(s => "\n|" + "_" * (s._2 * w / t.head._2) + "| " + s._1).foreach(print)
}
}
y compris l'ajustement de Word long. Des idées empruntées aux autres solutions.
Maintenant, en tant que script (a.scala
):
val t="\\w+\\b(?<!\\bthe|and|of|to|a|i[tns]?|or)".r.findAllIn(io.Source.fromFile(argv(0)).mkString.toLowerCase).toSeq.groupBy(w=>w).mapValues(_.size).toSeq.sortBy(-_._2)take 22
def b(p:Int)="_"*(p*(for((w,c)<-t)yield(76.0-w.size)/c).min).toInt
println(" "+b(t(0)._2))
for(p<-t)printf("|%s| %s \n",b(p._2),p._1)
Courir avec
scala -howtorun:script a.scala alice.txt
BTW, l'édition de 314 à 311 caractères supprime en fait seulement 1 caractère. Quelqu'un s'est trompé avant (Windows CRs?).
(let[[[_ m]:as s](->>(Slurp *in*).toLowerCase(re-seq #"\w+\b(?<!\bthe|and|of|to|a|i[tns]?|or)")frequencies(sort-by val >)(take 22))[b](sort(map #(/(- 76(count(key %)))(val %))s))p #(do(print %1)(dotimes[_(* b %2)](print \_))(apply println %&))](p " " m)(doseq[[k v]s](p \| v \| k)))
Un peu plus lisiblement:
(let[[[_ m]:as s](->> (Slurp *in*)
.toLowerCase
(re-seq #"\w+\b(?<!\bthe|and|of|to|a|i[tns]?|or)")
frequencies
(sort-by val >)
(take 22))
[b] (sort (map #(/ (- 76 (count (key %)))(val %)) s))
p #(do
(print %1)
(dotimes[_(* b %2)] (print \_))
(apply println %&))]
(p " " m)
(doseq[[k v] s] (p \| v \| k)))
Je ne m'attends pas à obtenir un score élevé en utilisant C++, mais ça ne fait rien. Je suis sûr que cela répond à toutes les exigences. Notez que j'ai utilisé le mot clé C++ 0x auto
pour la déclaration de variable, ajustez donc votre complicateur de manière appropriée si vous décidez de tester mon code.
version minimisée
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
#define C string
#define S(x)v=F/a,cout<<#x<<C(v,'_')
#define F t->first
#define G t->second
#define O &&F!=
#define L for(i=22;i-->0;--t)
int main(){map<C,int>f;char d[230];int i=1,v;for(;i<256;i++)d[i<123?i-1:i-27]=i;d[229]=0;char w[99];while(cin>>w){for(i=0;w[i];i++)w[i]=tolower(w[i]);char*p=strtok(w,d);while(p)++f[p],p=strtok(0,d);}multimap<int,C>c;for(auto t=f.end();--t!=f.begin();)if(F!="the"O"and"O"of"O"to"O"a"O"i"O"it"O"in"O"or"O"is")c.insert(pair<int,C>(G,F));auto t=--c.end();float a=0,A;L A=F/(76.0-G.length()),a=a>A?a:A;t=--c.end();S( );L S(\n|)<<"| "<<G;}
Voici une deuxième version qui est plus "C++" en utilisant string
, pas char[]
et strtok
. C'est un peu plus grand, à 669 (+22 vs ci-dessus), mais je ne peux pas le réduire pour le moment, alors j'ai pensé le publier de toute façon.
#include <iostream>
#include <map>
using namespace std;
#define C string
#define S(x)v=F/a,cout<<#x<<C(v,'_')
#define F t->first
#define G t->second
#define O &&F!=
#define L for(i=22;i-->0;--t)
#define E e=w.find_first_of(d,g);g=w.find_first_not_of(d,e);
int main(){map<C,int>f;int i,v;C w,x,d="abcdefghijklmnopqrstuvwxyz";while(cin>>w){for(i=w.size();i-->0;)w[i]=tolower(w[i]);unsigned g=0,E while(g-e>0){x=w.substr(e,g-e),++f[x],E}}multimap<int,C>c;for(auto t=f.end();--t!=f.begin();)if(F!="the"O"and"O"of"O"to"O"a"O"i"O"it"O"in"O"or"O"is")c.insert(pair<int,C>(G,F));auto t=--c.end();float a=0,A;L A=F/(76.0-G.length()),a=a>A?a:A;t=--c.end();S( );L S(\n|)<<"| "<<G;}
J'ai supprimé la version complète, car je ne peux pas être dérangé de continuer à la mettre à jour avec mes réglages pour la version minimisée. Consultez l'historique des modifications si vous êtes intéressé par la version longue (éventuellement obsolète).
Mise à jour: j'ai considérablement réduit le nombre de personnages. Omet les mots d'une seule lettre par spécification mise à jour.
J'envie tellement C # et LINQ.
import Java.util.*;import Java.io.*;import static Java.util.regex.Pattern.*;class g{public static void main(String[] a)throws Exception{PrintStream o=System.out;Map<String,Integer> w=new HashMap();Scanner s=new Scanner(new File(a[0])).useDelimiter(compile("[^a-z]+|\\b(the|and|of|to|.|it|in|or|is)\\b",2));while(s.hasNext()){String z=s.next().trim().toLowerCase();if(z.equals(""))continue;w.put(z,(w.get(z)==null?0:w.get(z))+1);}List<Integer> v=new Vector(w.values());Collections.sort(v);List<String> q=new Vector();int i,m;i=m=v.size()-1;while(q.size()<22){for(String t:w.keySet())if(!q.contains(t)&&w.get(t).equals(v.get(i)))q.add(t);i--;}int r=80-q.get(0).length()-4;String l=String.format("%1$0"+r+"d",0).replace("0","_");o.println(" "+l);o.println("|"+l+"| "+q.get(0)+" ");for(i=m-1;i>m-22;i--){o.println("|"+l.substring(0,(int)Math.round(r*(v.get(i)*1.0)/v.get(m)))+"| "+q.get(m-i)+" ");}}}
"Lisible":
import Java.util.*;
import Java.io.*;
import static Java.util.regex.Pattern.*;
class g
{
public static void main(String[] a)throws Exception
{
PrintStream o = System.out;
Map<String,Integer> w = new HashMap();
Scanner s = new Scanner(new File(a[0]))
.useDelimiter(compile("[^a-z]+|\\b(the|and|of|to|.|it|in|or|is)\\b",2));
while(s.hasNext())
{
String z = s.next().trim().toLowerCase();
if(z.equals(""))
continue;
w.put(z,(w.get(z) == null?0:w.get(z))+1);
}
List<Integer> v = new Vector(w.values());
Collections.sort(v);
List<String> q = new Vector();
int i,m;
i = m = v.size()-1;
while(q.size()<22)
{
for(String t:w.keySet())
if(!q.contains(t)&&w.get(t).equals(v.get(i)))
q.add(t);
i--;
}
int r = 80-q.get(0).length()-4;
String l = String.format("%1$0"+r+"d",0).replace("0","_");
o.println(" "+l);
o.println("|"+l+"| "+q.get(0)+" ");
for(i = m-1; i > m-22; i--)
{
o.println("|"+l.substring(0,(int)Math.round(r*(v.get(i)*1.0)/v.get(m)))+"| "+q.get(m-i)+" ");
}
}
}
Sortie d'Alice:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| with
|______________________________| at
|___________________________| on
|__________________________| all
|________________________| this
|________________________| for
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what
Sortie de Don Quichotte (également de Gutenberg):
________________________________________________________________________
|________________________________________________________________________| that
|________________________________________________________| he
|______________________________________________| for
|__________________________________________| his
|________________________________________| as
|__________________________________| with
|_________________________________| not
|_________________________________| was
|________________________________| him
|______________________________| be
|___________________________| don
|_________________________| my
|_________________________| this
|_________________________| all
|_________________________| they
|________________________| said
|_______________________| have
|_______________________| me
|______________________| on
|______________________| so
|_____________________| you
|_____________________| quixote
Je crois que celui-ci est pleinement conforme à la question. Ignorer la liste est ici, il vérifie complètement la longueur de la ligne (voir l'exemple où j'ai remplacé Alice
par Aliceinwonderlandbylewiscarroll
dans le texte faisant du cinquième élément la ligne la plus longue. Même le nom de fichier est fourni à partir de la ligne de commande à la place de codé en dur (le codage en dur supprimerait environ 10 caractères). Il a un inconvénient (mais je pense que cela convient à la question) car il calcule un diviseur entier pour rendre la ligne plus courte que 80 caractères, la ligne la plus longue est inférieure à 80 caractères, non exactement 80 caractères. La version python 3.x n'a pas ce défaut (mais est bien plus longue).
Je pense aussi que ce n'est pas si difficile à lire.
import sys,re
t=re.split("\W+(?:(?:the|and|o[fr]|to|a|i[tns]?)\W+)*",sys.stdin.read().lower())
b=sorted((-t.count(x),x)for x in set(t))[:22]
for l,w in b:print"|"+l/min(z/(78-len(e))for z,e in b)*'-'+"|",w
|----------------------------------------------------------------| she
|--------------------------------------------------------| you
|-----------------------------------------------------| said
|----------------------------------------------| aliceinwonderlandbylewiscarroll
|-----------------------------------------| was
|--------------------------------------| that
|-------------------------------| as
|----------------------------| her
|--------------------------| at
|--------------------------| with
|-------------------------| s
|-------------------------| t
|-----------------------| on
|-----------------------| all
|---------------------| this
|--------------------| for
|--------------------| had
|--------------------| but
|-------------------| be
|-------------------| not
|------------------| they
|-----------------| so
Comme il n'est pas clair si nous devons imprimer la barre max seule sur sa ligne (comme dans l'exemple de sortie). Ci-dessous est un autre qui le fait, mais 232 caractères.
import sys,re
t=re.split("\W+(?:(?:the|and|o[fr]|to|a|i[tns]?)\W+)*",sys.stdin.read().lower())
b=sorted((-t.count(x),x)for x in set(t))[:22]
f=min(z/(78-len(e))for z,e in b)
print"",b[0][0]/f*'-'
for y,w in b:print"|"+y/f*'-'+"|",w
En utilisant la classe Counter de python 3.x, il y avait de grands espoirs de la raccourcir (comme Counter fait tout ce dont nous avons besoin ici). Il ressort que ce n'est pas mieux. Ci-dessous mon essai de 266 caractères :
import sys,re,collections as c
b=c.Counter(re.split("\W+(?:(?:the|and|o[fr]|to|a|i[tns]?)\W+)*",
sys.stdin.read().lower())).most_common(22)
F=lambda p,x,w:print(p+'-'*int(x/max(z/(77.-len(e))for e,z in b))+w)
F(" ",b[0][1],"")
for w,y in b:F("|",y,"| "+w)
Le problème est que collections
et most_common
sont des mots très longs et même Counter
n'est pas court ... vraiment, ne pas utiliser Counter
ne rend le code que 2 caractères plus long ;-(
python 3.x introduit également d'autres contraintes: la division de deux entiers n'est plus un entier (nous devons donc transtyper en int), print est désormais une fonction (doit ajouter des parenthèses), etc. C'est pourquoi il sort 22 caractères plus longtemps que version python2.x, mais beaucoup plus rapide. Peut-être un peu plus expérimenté python 3.x aura des idées pour raccourcir le code.
remplacé b=map.get(a)
par b=map[a]
, remplacé par split avec matcher/iterator
def r,s,m=[:],n=0;def p={println it};def w={"_".multiply it};(new URL(this.args[0]).text.toLowerCase()=~/\b\w+\b/).each{s=it;if(!(s==~/(the|and|of|to|a|i[tns]?|or)/))m[s]=m[s]==null?1:m[s]+1};m.keySet().sort{a,b->m[b]<=>m[a]}.subList(0,22).each{k->if(n++<1){r=(m[k]/(76-k.length()));p" "+w(m[k]/r)};p"|"+w(m[k]/r)+"|"+k}
(exécuté en tant que script groovy avec l'URL comme argument de ligne cmd. Aucune importation requise!)
Version lisible ici:
def r,s,m=[:],n=0;
def p={println it};
def w={"_".multiply it};
(new URL(this.args[0]).text.toLowerCase()
=~ /\b\w+\b/
).each{
s=it;
if (!(s ==~/(the|and|of|to|a|i[tns]?|or)/))
m[s] = m[s] == null ? 1 : m[s] + 1
};
m.keySet()
.sort{
a,b -> m[b] <=> m[a]
}
.subList(0,22).each{
k ->
if( n++ < 1 ){
r=(m[k]/(76-k.length()));
p " " + w(m[k]/r)
};
p "|" + w(m[k]/r) + "|" + k
}
J'ai essayé d'écrire le code dans autant de Clojure idiomatique que possible si tard dans la nuit. Je ne suis pas trop fier du draw-chart
, mais je suppose que le code en dit long sur la brièveté de Clojure.
(ns Word-freq
(:require [clojure.contrib.io :as io]))
(defn Word-freq
[f]
(take 22 (->> f
io/read-lines ;;; Slurp should work too, but I love map/red
(mapcat (fn [l] (map #(.toLowerCase %) (re-seq #"\w+" l))))
(remove #{"the" "and" "of" "to" "a" "i" "it" "in" "or" "is"})
(reduce #(assoc %1 %2 (inc (%1 %2 0))) {})
(sort-by (comp - val)))))
(defn draw-chart
[fs]
(let [[[w f] & _] fs]
(apply str
(interpose \newline
(map (fn [[k v]] (apply str (concat "|" (repeat (int (* (- 76 (count w)) (/ v f 1))) "_") "| " k " ")) ) fs)))))
;;; (println (draw-chart (Word-freq "/Users/ghoseb/Desktop/alice.txt")))
Sortie:
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|____________________________| t
|____________________________| s
|__________________________| on
|__________________________| all
|_______________________| for
|_______________________| had
|_______________________| this
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
Je sais, cela ne suit pas les spécifications, mais bon, c'est du code Clojure très propre qui est déjà si petit :)
MATLAB 335 404410 octets357 octets.390 octets.
Le code mis à jour compte désormais 335 caractères au lieu de 404 et semble bien fonctionner pour les deux exemples.
Message d'origine (Pour un code de 404 caractères)
Cette version est un peu plus longue, cependant , elle mettra correctement à l'échelle la longueur des barres s'il y a un mot ridiculement long pour qu'aucun des les colonnes dépassent 80.
Donc, mon code est de 357 octets sans redimensionnement et 410 de long avec redimensionnement.
A=textscan(fopen('11.txt'),'%s','delimiter',' 0123456789,.!?-_*^:;=+\\/(){}[]@&#$%~`|"''');
s=lower(A{1});s(cellfun('length', s)<2)=[];s(ismember(s,{'the','and','of','to','it','in','or','is'}))=[];
[w,~,i]=unique(s);N=hist(i,max(i)); [j,k]=sort(N,'descend'); b=k(1:22); n=cellfun('length',w(b));
q=80*N(b)'/N(k(1))+n; q=floor(q*78/max(q)-n); for i=1:22, fprintf('%s| %s\n',repmat('_',1,l(i)),w{k(i)});end
Résultats:
___________________________________________________________________________| she
_________________________________________________________________| you
______________________________________________________________| said
_______________________________________________________| alice
________________________________________________| was
____________________________________________| that
_____________________________________| as
_________________________________| her
______________________________| at
______________________________| with
____________________________| on
___________________________| all
_________________________| this
________________________| for
________________________| had
________________________| but
_______________________| be
_______________________| not
_____________________| they
____________________| so
___________________| very
___________________| what
Par exemple, en remplaçant toutes les instances de "vous" dans le texte d'Alice au pays des merveilles par "superlongstringofridiculousness", mon code mettra correctement à l'échelle les résultats:
____________________________________________________________________| she
_________________________________________________________| superlongstringstring
________________________________________________________| said
_________________________________________________| alice
____________________________________________| was
________________________________________| that
_________________________________| as
______________________________| her
___________________________| with
___________________________| at
_________________________| on
________________________| all
_____________________| this
_____________________| for
_____________________| had
_____________________| but
____________________| be
____________________| not
__________________| they
__________________| so
_________________| very
_________________| what
Voici le code mis à jour écrit un peu plus lisiblement:
A=textscan(fopen('t'),'%s','delimiter','':'@');
s=lower(A{1});
s(cellfun('length', s)<2|ismember(s,{'the','and','of','to','it','in','or','is'}))=[];
[w,~,i]=unique(s);
N=hist(i,max(i));
[j,k]=sort(N,'descend');
n=cellfun('length',w(k));
q=80*N(k)'/N(k(1))+n;
q=floor(q*78/max(q)-n);
for i=1:22,
fprintf('%s| %s\n',repmat('_',1,q(i)),w{k(i)});
end
J'ai pris le code de @ seanizer , corrigé un bug (il a omis la 1ère ligne de sortie), fait quelques améliorations pour rendre le code plus 'golfy'.
import Java.util.*;
import Java.util.regex.*;
import org.Apache.commons.io.IOUtils;
public class WF{
public static void main(String[] a)throws Exception{
String t=IOUtils.toString(new Java.net.URL(a[0]).openStream());
class W implements Comparable<W> {
String w;int f=1;W(String W){w=W;}public int compareTo(W o){return o.f-f;}
String d(float r){char[]c=new char[(int)(f/r)];Arrays.fill(c,'_');return "|"+new String(c)+"| "+w;}
}
Map<String,W>M=new HashMap<String,W>();
Matcher m=Pattern.compile("\\b\\w+\\b").matcher(t.toLowerCase());
while(m.find()){String w=m.group();W W=M.get(w);if(W==null)M.put(w,new W(w));else W.f++;}
M.keySet().removeAll(Arrays.asList("the,and,of,to,a,i,it,in,or,is".split(",")));
List<W>L=new ArrayList<W>(M.values());Collections.sort(L);int l=76-L.get(0).w.length();
System.out.println(" "+new String(new char[l]).replace('\0','_'));
for(W w:L.subList(0,22))System.out.println(w.d((float)L.get(0).f/(float)l));
}
}
Sortie:
_________________________________________________________________________ | _________________________________________________________________________ | elle | _______________________________________________________________ | vous | ____________________________________________________________ | dit | _____________________________________________________ | alice | _______________________________________________ | était | ___________________________________________ | que | ____________________________________ | comme | ________________________________ | son | _____________________________ | avec | _____________________________ | à | ____________________________ | s | ____________________________ | t | __________________________ | le | __________________________ | tous | _______________________ | ce | _______________________ | pour | _______________________ | avait | _______________________ | mais | ______________________ | être | _____________________ | pas | ____________________ | ils | ____________________ | alors
Scala, 327 caractères
Ceci a été adapté de la réponse de mkneissl inspirée d'une version Python, bien qu'elle soit plus grande. Je la laisse ici au cas où quelqu'un pourrait le raccourcir.
val f="\\w+\\b(?<!\\bthe|and|of|to|a|i[tns]?|or)".r.findAllIn(io.Source.fromFile("11.txt").mkString.toLowerCase).toSeq
val t=f.toSet[String].map(x=> -f.count(x==)->x).toSeq.sorted take 22
def b(p:Int)="_"*(-p/(for((c,w)<-t)yield-c/(76.0-w.size)).max).toInt
println(" "+b(t(0)._1))
for(p<-t)printf("|%s| %s \n",b(p._1),p._2)
tr A-Z a-z|tr -Cs a-z "\n"|sort|egrep -v "^(the|and|of|to|a|i|it|in|or|is)$" |uniq -c|sort -r|head -22>g
n=1
while :
do
awk '{printf "|%0*s| %s\n",$1*'$n'/1e3,"",$2;}' g|tr 0 _>o
egrep -q .{80} o&&break
n=$((n+1))
done
cat o
Je suis surpris que personne ne semble avoir utilisé la fonctionnalité étonnante * de printf.
cat 11-very.txt> golf.sh
|__________________________________________________________________________| she
|________________________________________________________________| you
|_____________________________________________________________| said
|______________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| with
|______________________________| at
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|________________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
chat 11 | golf.sh
|_________________________________________________________________| she
|_________________________________________________________| verylongstringstring
|______________________________________________________| said
|_______________________________________________| alice
|__________________________________________| was
|_______________________________________| that
|________________________________| as
|_____________________________| her
|___________________________| with
|___________________________| at
|__________________________| s
|_________________________| t
|________________________| on
|_______________________| all
|_____________________| this
|_____________________| for
|_____________________| had
|____________________| but
|___________________| be
|___________________| not
|__________________| they
|__________________| so
(Edit: Props à ChristopheD pour des suggestions de rasage de personnage)
import sys,re
t=re.findall('[a-z]+',"".join(sys.stdin).lower())
d=sorted((t.count(w),w)for w in set(t)-set("the and of to a i it in or is".split()))[:-23:-1]
r=min((78.-len(m[1]))/m[0]for m in d)
print'','_'*(int(d[0][0]*r-2))
for(a,b)in d:print"|"+"_"*(int(a*r-2))+"|",b
Sortie:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|____________________________________________________| alice
|______________________________________________| was
|__________________________________________| that
|___________________________________| as
|_______________________________| her
|____________________________| with
|____________________________| at
|___________________________| s
|___________________________| t
|_________________________| on
|_________________________| all
|______________________| this
|______________________| for
|______________________| had
|_____________________| but
|____________________| be
|____________________| not
|___________________| they
|__________________| so
peut probablement raccourcir ...
bar <- function(w, l)
{
b <- rep("-", l)
s <- rep(" ", l)
cat(" ", b, "\n|", s, "| ", w, "\n ", b, "\n", sep="")
}
f <- "alice.txt"
e <- c("the", "and", "of", "to", "a", "i", "it", "in", "or", "is", "")
w <- unlist(lapply(readLines(file(f)), strsplit, s=" "))
w <- tolower(w)
w <- unlist(lapply(w, gsub, pa="[^a-z]", r=""))
u <- unique(w[!w %in% e])
n <- unlist(lapply(u, function(x){length(w[w==x])}))
o <- rev(order(n))
n <- n[o]
m <- 77 - max(unlist(lapply(u[1:22], nchar)))
n <- floor(m*n/n[1])
u <- u[o]
for (i in 1:22)
bar(u[i], n[i])
import sys
i="the and of to a i it in or is".split()
d={}
for j in filter(lambda x:x not in i,sys.stdin.read().lower().split()):d[j]=d.get(j,0)+1
w=sorted(d.items(),key=lambda x:x[1])[:-23:-1]
m=sorted(dict(w).values())[-1]
print" %s\n"%("_"*(76-m)),"\n".join(map(lambda x:("|%s| "+x[0])%("_"*((76-m)*x[1]/w[0][1])),w))
Je pense que cela peut être un peu plus court, mais je ne sais toujours pas comment.
|q s f m|q:=Bag new. f:=FileStream stdin. m:=0.[f atEnd]whileFalse:[s:=f nextLine.(s notNil)ifTrue:[(s tokenize:'\W+')do:[:i|(((i size)>1)&({'the'.'and'.'of'.'to'.'it'.'in'.'or'.'is'}includes:i)not)ifTrue:[q add:(i asLowercase)]. m:=m max:(i size)]]].(q:=q sortedByCount)from:1to:22 do:[:i|'|'display.((i key)*(77-m)//(q first key))timesRepeat:['='display].('| %1'%{i value})displayNl]
Solution Lua: 478 caractères.
t,u={},{}for l in io.lines()do
for w in l:gmatch("%a+")do
w=w:lower()if not(" the and of to a i it in or is "):find(" "..w.." ")then
t[w]=1+(t[w]or 0)end
end
end
for k,v in next,t do
u[#u+1]={k,v}end
table.sort(u,function(a,b)return a[2]>b[2]end)m,n=u[1][2],math.min(#u,22)for w=80,1,-1 do
s=""for i=1,n do
a,b=u[i][1],w*u[i][2]/m
if b+#a>=78 then s=nil break end
s2=("_"):rep(b)if i==1 then
s=s.." " ..s2.."\n"end
s=s.."|"..s2.."| "..a.."\n"end
if s then print(s)break end end
Version lisible:
t,u={},{}
for line in io.lines() do
for w in line:gmatch("%a+") do
w = w:lower()
if not (" the and of to a i it in or is "):find(" "..w.." ") then
t[w] = 1 + (t[w] or 0)
end
end
end
for k, v in pairs(t) do
u[#u+1]={k, v}
end
table.sort(u, function(a, b)
return a[2] > b[2]
end)
local max = u[1][2]
local n = math.min(#u, 22)
for w = 80, 1, -1 do
s=""
for i = 1, n do
f = u[i][2]
Word = u[i][1]
width = w * f / max
if width + #Word >= 78 then
s=nil
break
end
s2=("_"):rep(width)
if i==1 then
s=s.." " .. s2 .."\n"
end
s=s.."|" .. s2 .. "| " .. Word.."\n"
end
if s then
print(s)
break
end
end
Une autre solution T-SQL empruntant quelques idées à la solution de Martin (min76- etc.).
declare @ varchar(max),@w real,@j int;select s=@ into[ ]set @=(select*
from openrowset(bulk'a',single_blob)a)while @>''begin set @=stuff(@,1,
patindex('%[a-z]%',@)-1,'')+'.'set @j=patindex('%[^a-z]%',@)if @j>2insert[ ]
select lower(left(@,@j-1))set @=stuff(@,1,@j,'')end;select top(22)s,count(*)
c into # from[ ]where',the,and,of,to,it,in,or,is,'not like'%,'+s+',%'
group by s order by 2desc;select @w=min((76.-len(s))/c),@=' '+replicate(
'_',max(c)*@w)from #;select @=@+'
|'+replicate('_',c*@w)+'| '+s+' 'from #;print @
La solution entière doit être sur deux lignes (concaténer les 7 premières), bien que vous puissiez la couper, la coller et l'exécuter telle quelle. Nombre total de caractères = 507 (en comptant le saut de ligne comme 1 si vous l'enregistrez au format Unix et exécutez à l'aide de SQLCMD)
Hypothèses:
#
[ ]
C:\windows\system32\a
Et pour entrer dans la liste des solutions (<500 caractères), voici l'édition "décontractée" à 483 caractères (pas de barres verticales/pas de barre supérieure/Aucun espace de fin après Word)
declare @ varchar(max),@w real,@j int;select s=@ into[ ]set @=(select*
from openrowset(bulk'b',single_blob)a)while @>''begin set @=stuff(@,1,
patindex('%[a-z]%',@)-1,'')+'.'set @j=patindex('%[^a-z]%',@)if @j>2insert[ ]
select lower(left(@,@j-1))set @=stuff(@,1,@j,'')end;select top(22)s,count(*)
c into # from[ ]where',the,and,of,to,it,in,or,is,'not like'%,'+s+',%'
group by s order by 2desc;select @w=min((78.-len(s))/c),@=''from #;select @=@+'
'+replicate('_',c*@w)+' '+s from #;print @
declare @ varchar(max), @w real, @j int
select s=@ into[ ] -- shortcut to create table; use defined variable to specify column type
-- openrowset reads an entire file
set @=(select * from openrowset(bulk'a',single_blob) a) -- a bit shorter than naming 'BulkColumn'
while @>'' begin -- loop until input is empty
set @=stuff(@,1,patindex('%[a-z]%',@)-1,'')+'.' -- remove lead up to first A-Z char *
set @j=patindex('%[^a-z]%',@) -- find first non A-Z char. The +'.' above makes sure there is one
if @j>2insert[ ] select lower(left(@,@j-1)) -- insert only words >1 char
set @=stuff(@,1,@j,'') -- remove Word and trailing non A-Z char
end;
select top(22)s,count(*)c
into #
from[ ]
where ',the,and,of,to,it,in,or,is,' not like '%,'+s+',%' -- exclude list
group by s
order by 2desc; -- highest occurence, assume no ties at 22!
-- 80 - 2 vertical bars - 2 spaces = 76
-- @w = weighted frequency
-- this produces a line equal to the length of the max occurence (max(c))
select @w=min((76.-len(s))/c),@=' '+replicate('_',max(c)*@w)
from #;
-- for each Word, append it as a new line. note: embedded newline
select @=@+'
|'+replicate('_',c*@w)+'| '+s+' 'from #;
-- note: 22 words in a table should always fit on an 8k page
-- the order of processing should always be the same as the insert-orderby
-- thereby producing the correct output
print @ -- output
Java, se raccourcissant lentement (1500135812411020913 890 caractères)
dépouillé encore plus d'espace blanc et la longueur du nom var. supprimé les génériques dans la mesure du possible, supprimé la classe en ligne et le bloc try/catch trop mauvais, ma version 900 avait un bug
import Java.net.*;import Java.util.*;import Java.util.regex.*;import org.Apache.commons.io.*;public class G{public static void main(String[]a)throws Exception{String text=IOUtils.toString(new URL(a[0]).openStream()).toLowerCase().replaceAll("\\b(the|and|of|to|a|i[tns]?|or)\\b","");final Map<String,Integer>p=new HashMap();Matcher m=Pattern.compile("\\b\\w+\\b").matcher(text);Integer b;while(m.find()){String w=m.group();b=p.get(w);p.put(w,b==null?1:b+1);}List<String>v=new Vector(p.keySet());Collections.sort(v,new Comparator(){public int compare(Object l,Object m){return p.get(m)-p.get(l);}});boolean t=true;float r=0;for(String w:v.subList(0,22)){if(t){t=false;r=p.get(w)/(float)(80-(w.length()+4));System.out.println(" "+new String(new char[(int)(p.get(w)/r)]).replace('\0','_'));}System.out.println("|"+new String(new char[(int)(((Integer)p.get(w))/r)]).replace('\0','_')+"|"+w);}}}
Version lisible:
import Java.net.*;
import Java.util.*;
import Java.util.regex.*;
import org.Apache.commons.io.*;
public class G{
public static void main(String[] a) throws Exception{
String text =
IOUtils.toString(new URL(a[0]).openStream())
.toLowerCase()
.replaceAll("\\b(the|and|of|to|a|i[tns]?|or)\\b", "");
final Map<String, Integer> p = new HashMap();
Matcher m = Pattern.compile("\\b\\w+\\b").matcher(text);
Integer b;
while(m.find()){
String w = m.group();
b = p.get(w);
p.put(w, b == null ? 1 : b + 1);
}
List<String> v = new Vector(p.keySet());
Collections.sort(v, new Comparator(){
public int compare(Object l, Object m){
return p.get(m) - p.get(l);
}
});
boolean t = true;
float r = 0;
for(String w : v.subList(0, 22)){
if(t){
t = false;
r = p.get(w) / (float) (80 - (w.length() + 4));
System.out.println(" "
+ new String(new char[(int) (p.get(w) / r)]).replace('\0',
'_'));
}
System.out.println("|"
+ new String(new char[(int) (((Integer) p.get(w)) / r)]).replace('\0',
'_') + "|" + w);
}
}
}
Cette version Ruby version gère "superlongstringstring". (Les deux premières lignes sont presque identiques à la précédente Ruby programmes.)
Il doit être exécuté de cette façon:
Ruby -n0777 golf.rb Alice.txt
W=($_.upcase.scan(/\w+/)-%w(THE AND OF TO A I IT
IN OR IS)).group_by{|x|x}.map{|k,v|[-v.size,k]}.sort[0,22]
u=proc{|m|"_"*(W.map{|n,s|(76.0-s.size)/n}.max*m)}
puts" "+u[W[0][0]],W.map{|n,s|"|%s| "%u[n]+s}
La troisième ligne crée une fermeture ou lambda qui produit une chaîne de soulignements correctement mise à l'échelle:
u = proc {| m | "_" * (W.map {| n, s | (76.0 - s.size)/n} .max * m ) }
.max
est utilisé à la place de .min
car les nombres sont négatifs.
Perl, 188 caractères
La version Perl ci-dessus (ainsi que toute version basée sur le fractionnement d'expressions rationnelles) peut être raccourcie de quelques octets en incluant la liste des mots interdits en tant qu'affirmations d'anticipation négatives, plutôt qu'en tant que liste distincte. De plus, le point-virgule de fin peut être omis.
J'ai également inclus quelques autres suggestions (- au lieu de <=>, pour/foreach, "clés" supprimées) pour arriver à
$c{$_}++for grep{$_}map{lc=~/\b(?!(?:the|and|a|of|or|i[nts]?|to)\b)[a-z]+/g}<>;@s=sort{$c{$b}-$c{$a}}%c;$f=76-length$s[0];say$"."_"x$f;say"|"."_"x($c{$_}/$c{$s[0]}*$f)."| $_ "for@s[0..21]
Je ne connais pas Perl, mais je suppose que le (?! (?: ...)\b) peut perdre le?: Si la manipulation autour de lui est corrigée.
Après avoir fini le mien, j'ai volé quelques idées à Matt: 3
t=Prompt().toLowerCase().replace(/\b(the|and|of|to|a|i[tns]?|or)\b/gm,'');r={};o=[];t.replace(/\b([a-z]+)\b/gm,function(a,w){r[w]?++r[w]:r[w]=1});for(i in r){o.Push([i,r[i]])}m=o[0][1];o=o.slice(0,22);o.sort(function(F,D){return D[1]-F[1]});for(B in o){F=o[B];L=new Array(~~(F[1]/m*(76-F[0].length))).join('_');print(' '+L+'\n|'+L+'| '+F[0]+' \n')}
Nécessite print et Prompt support de la fonction.
L'ajout de quelques drapeaux -i peut faire chuter le trop long tr A-Z a-z | étape; la spécification n'a rien dit sur le cas affiché et uniq -ci supprime toutes les différences de cas.
egrep -oi [a-z]+|egrep -wiv 'the|and|o[fr]|to|a|i[tns]?'|sort|uniq -ci|sort -nr|head -22|Perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
C'est moins 11 pour le tr plus 2 pour les -i par rapport aux 206 caractères originaux.
edit: moins 3 pour le \\ b qui peut être omis car la correspondance de motif commencera de toute façon sur une frontière.
sort donne d'abord les minuscules et uniq -ci prend la première occurrence, donc le seul vrai changement dans la sortie sera qu'Alice conserve ses initiales majuscules.
Je dois aimer les grands ... Objectif-C (1070931 905 caractères)
#define S NSString
#define C countForObject
#define O objectAtIndex
#define U stringWithCString
main(int g,char**b){id c=[NSCountedSet set];S*d=[S stringWithContentsOfFile:[S U:b[1]]];id p=[NSPredicate predicateWithFormat:@"SELF MATCHES[cd]'(the|and|of|to|a|i[tns]?|or)|[^a-z]'"];[d enumerateSubstringsInRange:NSMakeRange(0,[d length])options:NSStringEnumerationByWords usingBlock:^(S*s,NSRange x,NSRange y,BOOL*z){if(![p evaluateWithObject:s])[c addObject:[s lowercaseString]];}];id s=[[c allObjects]sortedArrayUsingComparator:^(id a,id b){return(NSComparisonResult)([c C:b]-[c C:a]);}];g=[c C:[s O:0]];int j=76-[[s O:0]length];char*k=malloc(80);memset(k,'_',80);S*l=[S U:k length:80];printf(" %s\n",[[l substringToIndex:j]cString]),[[s subarrayWithRange:NSMakeRange(0,22)]enumerateObjectsUsingBlock:^(id a,NSUInteger x,BOOL*y){printf("|%s| %s\n",[[l substringToIndex:[c C:a]*j/g]cString],[a cString]);}];}
Passé à l'utilisation de nombreuses API dépréciées, supprimé une gestion de la mémoire qui n'était pas nécessaire, suppression des espaces blancs plus agressive
_________________________________________________________________________
|_________________________________________________________________________| she
|______________________________________________________________| said
|__________________________________________________________| you
|____________________________________________________| alice
|________________________________________________| was
|_______________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| with
|______________________________| at
|___________________________| on
|__________________________| all
|________________________| this
|________________________| for
|________________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| so
|___________________| very
|__________________| what
|_________________| they
290 caractères en python (texte lu à partir de l'entrée standard)
import sys,re
c={}
for w in re.findall("[a-z]+",sys.stdin.read().lower()):c[w]=c.get(w,0)+1-(","+w+","in",a,i,the,and,of,to,it,in,or,is,")
r=sorted((-v,k)for k,v in c.items())[:22]
sf=max((76.0-len(k))/v for v,k in r)
print" "+"_"*int(r[0][0]*sf)
for v,k in r:print"|"+"_"*int(v*sf)+"| "+k
mais ... après avoir lu d'autres solutions, j'ai soudain réalisé que l'efficacité n'était pas une demande; c'est donc un autre plus court et beaucoup plus lent (255 caractères)
import sys,re
w=re.findall("\w+",sys.stdin.read().lower())
r=sorted((-w.count(x),x)for x in set(w)-set("the and of to a i it in or is".split()))[:22]
f=max((76.-len(k))/v for v,k in r)
print" "+"_"*int(f*r[0][0])
for v,k in r:print"|"+"_"*int(f*v)+"| "+k
et après avoir lu d'autres solutions ...
import sys,re
w=re.findall("\w+",sys.stdin.read().lower())
r=sorted((-w.count(x),x)for x in set(w)-set("the and of to a i it in or is".split()))[:22]
f=max((76.-len(k))/v for v,k in r)
print"","_"*int(f*r[0][0])
for v,k in r:print"|"+"_"*int(f*v)+"|",k
Et maintenant, cette solution est presque octet par octet identique à celle d'Astatine :-D
f=scan("stdin","ch")
u=unlist
s=strsplit
a=u(s(u(s(tolower(f),"[^a-z]")),"^(the|and|of|to|it|in|or|is|.|)$"))
v=unique(a)
r=sort(sapply(v,function(i) sum(a==i)),T)[2:23] #the first item is an empty string, just skipping it
w=names(r)
q=(78-max(nchar(w)))*r/max(r)
cat(" ",rep("_",q[1])," \n",sep="")
for(i in 1:22){cat("|",rep("_",q[i]),"| ",w[i],"\n",sep="")}
La sortie est:
_________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| at
|_____________________________| with
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
|___________________| very
|__________________| what
Et si "vous" est remplacé par quelque chose de plus long:
____________________________________________________________
|____________________________________________________________| she
|____________________________________________________| veryverylongstring
|__________________________________________________| said
|___________________________________________| alice
|______________________________________| was
|___________________________________| that
|_____________________________| as
|__________________________| her
|________________________| at
|________________________| with
|______________________| on
|_____________________| all
|___________________| this
|___________________| for
|___________________| had
|__________________| but
|__________________| be
|__________________| not
|________________| they
|________________| so
|_______________| very
|_______________| what
Go, 613 caractères, pourrait probablement être beaucoup plus petit:
package main
import(r "regexp";. "bytes";. "io/ioutil";"os";st "strings";s "sort";. "container/vector")
type z struct{c int;w string}
func(e z)Less(o interface{})bool{return o.(z).c<e.c}
func main(){b,_:=ReadAll(os.Stdin);g:=r.MustCompile
c,m,x:=g("[A-Za-z]+").AllMatchesIter(b,0),map[string]int{},g("the|and|of|it|in|or|is|to")
for w:=range c{w=ToLower(w);if len(w)>1&&!x.Match(w){m[string(w)]++}}
o,y:=&Vector{},0
for k,v:=range m{o.Push(z{v,k});if v>y{y=v}}
s.Sort(o)
for i,v:=range *o{if i>21{break};x:=v.(z);c:=int(float(x.c)/float(y)*80)
u:=st.Repeat("_",c);if i<1{println(" "+u)};println("|"+u+"| "+x.w)}}
Je me sens tellement sale.
foreach w [regexp -all -inline {[a-z]+} [string tolower [read stdin]]] {if {[lsearch {the and of to it in or is a i} $w]>=0} {continue};if {[catch {incr Ws($w)}]} {set Ws($w) 1}}
set T [lrange [lsort -decreasing -stride 2 -index 1 -integer [array get Ws]] 0 43]
foreach {w c} $T {lappend L [string length $w];lappend C $c}
set N [tcl::mathfunc::max {*}$L]
set C [lsort -integer $C]
set M [lindex $C end]
puts " [string repeat _ [expr {int((76-$N) * [lindex $T 1] / $M)}]] "
foreach {w c} $T {puts "|[string repeat _ [expr {int((76-$N) * $c / $M)}]]| $w"}
Ou, plus lisiblement
foreach w [regexp -all -inline {[a-z]+} [string tolower [read stdin]]] {
if {[lsearch {the and of to a i it in or is} $w] >= 0} { continue }
if {[catch {incr words($w)}]} {
set words($w) 1
}
}
set topwords [lrange [lsort -decreasing -stride 2 -index 1 -integer [array get words]] 0 43]
foreach {Word count} $topwords {
lappend lengths [string length $Word]
lappend counts $count
}
set maxlength [lindex [lsort -integer $lengths] end]
set counts [lsort -integer $counts]
set mincount [lindex $counts 0].0
set maxcount [lindex $counts end].0
puts " [string repeat _ [expr {int((76-$maxlength) * [lindex $topwords 1] / $maxcount)}]] "
foreach {Word count} $topwords {
set barlength [expr {int((76-$maxlength) * $count / $maxcount)}]
puts "|[string repeat _ $barlength]| $Word"
}
En améliorant la version Shell publiée plus tôt, je peux la réduire à 213 caractères:
tr A-Z a-z|tr -Cs a-z \\n|sort|egrep -v '^(the|and|of|to|a|i|it|in|or|is)$'|uniq -c|sort -rn|sed 22q>g
n=1
>o
until egrep -q .{80} o
do
awk '{printf "|%0*d| %s\n",$1*'$n'/1e3,0,$2}' g|tr 0 _>o
((n++))
done
cat o
Afin d'obtenir le contour supérieur sur la barre supérieure, j'ai dû l'étendre à 240 caractères:
tr A-Z a-z|tr -Cs a-z \\n|sort|egrep -v "^(the|and|of|to|a|i|it|in|or|is)$"|uniq -c|sort -r|sed 1p\;22q>g
n=1
>o
until egrep -q .{80} o
do
awk '{printf "|%0*d| %s\n",$1*'$n'/1e3,0,NR==1?"":$2}' g|sed '1s,|, ,g'|tr 0 _>o
((n++))
done
cat o
Python, 250 caractères
emprunt à tous les autres Python
import re,sys
t=re.findall("\w+","".join(sys.stdin).lower())
W=sorted((-t.count(w),w)for w in set(t)-set("the and of to a i it in or is".split()))[:22]
Z,U=W[0],lambda n:"_"*int(n*(76.-len(Z[1]))/Z[0])
print"",U(Z[0])
for(n,w)in W:print"|"+U(n)+"|",w
Si vous êtes effronté et mettez les mots à éviter comme arguments, 223 caractères
import re,sys
t=re.findall("\w+","".join(sys.stdin).lower())
W=sorted((-t.count(w),w)for w in set(t)-set(sys.argv[1:]))[:22]
Z,U=W[0],lambda n:"_"*int(n*(76.-len(Z[1]))/Z[0])
print"",U(Z[0])
for(n,w)in W:print"|"+U(n)+"|",w
La sortie est:
$ python alice4.py the and of to a i it in or is < 11.txt _________________________________________________________________________ |_________________________________________________________________________| she |_______________________________________________________________| you |____________________________________________________________| said |_____________________________________________________| alice |_______________________________________________| was |___________________________________________| that |____________________________________| as |________________________________| her |_____________________________| at |_____________________________| with |____________________________| s |____________________________| t |__________________________| on |__________________________| all |_______________________| this |_______________________| for |_______________________| had |_______________________| but |______________________| be |_____________________| not |____________________| they |____________________| so
Code:
m=[:]
(new URL(args[0]).text.toLowerCase()=~/\w+/).each{it==~/(the|and|of|to|a|i[tns]?|or)/?:(m[it]=1+(m[it]?:0))}
k=m.keySet().sort{a,b->m[b]<=>m[a]}
b={d,c,b->println d+'_'*c+d+' '+b}
b' ',z=77-k[0].size(),''
k[0..21].each{b'|',m[it]*z/m[k[0]],it}
Exécution:
$ groovy wordcount.groovy http://www.gutenberg.org/files/11/11.txt
Sortie:
__________________________________________________________________________
|__________________________________________________________________________| she
|________________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| at
|______________________________| with
|_____________________________| s
|_____________________________| t
|___________________________| on
|__________________________| all
|________________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
N.B. cela suit des règles détendues concernant les longues cordes
{t::y;{(-1')t#(.:)[b],'(!:)[b:"|",/:(((_)70*x%(*:)x)#\:"_"),\:"|"];}desc(#:')(=)($)(`$inter\:[(,/)" "vs'" "sv/:"'"vs'a(&)0<(#:')a:(_:')read0 -1!x;52#.Q.an])except`the`and`of`to`a`i`it`in`or`is`}
la fonction prend deux arguments: l'un un fichier contenant le texte et l'autre le nombre de lignes du graphique à afficher
q){t::y;{(-1')t#(.:)[b],'(!:)[b:"|",/:(((_)70*x%(*:)x)#\:"_"),\:"|"];}desc(#:')(=)($)(`$inter\:[(,/)" "vs'" "sv/:"'"vs'a(&)0<(#:')a:(_:')read0 -1!x;52#.Q.an])except`the`and`of`to`a`i`it`in`or`is`}[`a.txt;20]
sortie
|______________________________________________________________________|she
|____________________________________________________________|you
|__________________________________________________________|said
|___________________________________________________|alice
|_____________________________________________|was
|_________________________________________|that
|__________________________________|as
|_______________________________|her
|_____________________________|with
|____________________________|at
|___________________________|t
|___________________________|s
|_________________________|on
|_________________________|all
|_______________________|this
|______________________|for
|______________________|had
|_____________________|but
|_____________________|be
|_____________________|not