Costruisci un grafico ASCII delle parole più comunemente usate in un dato testo [chiuso]


156

La sfida:

Costruisci un grafico ASCII delle parole più comunemente usate in un dato testo.

Le regole:

  • Accetta a-ze A-Z(caratteri alfabetici) solo come parte di una parola.
  • Ignora involucro ( She== sheai nostri scopi).
  • Ignora le seguenti parole (abbastanza arbitrario, lo so): the, and, of, to, a, i, it, in, or, is
  • Chiarimento: considerando don't: questo verrebbe preso come 2 "parole" diverse negli intervalli a-ze A-Z: ( done t).

  • Opzionalmente (è troppo tardi per essere formalmente cambiando le specifiche ora) si può scegliere di abbandonare 'espressione' tutta la singola lettera (questo potrebbe potenzialmente fare per un accorciamento della lista ignora troppo).

Analizza un dato text(leggi un file specificato tramite argomenti della riga di comando o reindirizzato; presume us-ascii) e creaci un word frequency chartcon le seguenti caratteristiche:

  • Visualizza il grafico (vedi anche l'esempio seguente) per le 22 parole più comuni (ordinate per frequenza decrescente).
  • La barra widthrappresenta il numero di occorrenze (frequenza) della parola (proporzionalmente). Aggiungi uno spazio e stampa la parola.
  • Assicurati che queste barre (più spazio-parola-spazio) si adattino sempre : bar+ [space]+ word+ [space]deve essere sempre <= 80caratteri (assicurati di tenere conto di possibili barre diverse e lunghezze delle parole: ad esempio: la seconda parola più comune potrebbe essere molto più lunga di il primo pur non differendo molto in frequenza). Massimizza la larghezza della barra all'interno di questi vincoli e ridimensiona le barre in modo appropriato (in base alle frequenze che rappresentano).

Un esempio:

Il testo per l'esempio è disponibile qui ( Alice's Adventures in Wonderland, di Lewis Carroll ).

Questo testo specifico produrrebbe il seguente diagramma:

 _________________________________________________________________________
| _________________________________________________________________________ | lei
| _______________________________________________________________ | tu
| ____________________________________________________________ | disse
| ____________________________________________________ | alice
| ______________________________________________ | era
| __________________________________________ | quello
| ___________________________________ | come
| _______________________________ | sua
| ____________________________ | con
| ____________________________ | a
| ___________________________ | S
| ___________________________ | t
| _________________________ | sopra
| _________________________ | tutti
| ______________________ | Questo
| ______________________ | per
| ______________________ | aveva
| _____________________ | ma
| ____________________ | essere
| ____________________ | non
| ___________________ | essi
| __________________ | così


Per tua informazione: queste sono le frequenze su cui si basa la tabella sopra:

[('she', 553), ('you', 481), ('detto', 462), ('alice', 403), ('was', 358), ('that
', 330), (' as ', 274), (' her ', 248), (' with ', 227), (' at ', 227), (' s ', 219), (' t '
, 218), ('on', 204), ('all', 200), ('this', 181), ('for', 179), ('had', 178), ('
ma ', 175), (' be ', 167), (' not ', 166), (' they ', 155), (' so ', 152)]

Un secondo esempio (per verificare se sono state implementate le specifiche complete): Sostituisci tutte le occorrenze nel file Alice nel paese delle meraviglieyou collegato con :superlongstringstring

 ________________________________________________________________
| ________________________________________________________________ | lei
| _______________________________________________________ | superlongstringstring
| _____________________________________________________ | disse
| ______________________________________________ | alice
| ________________________________________ | era
| _____________________________________ | quello
| ______________________________ | come
| ___________________________ | sua
| _________________________ | con
| _________________________ | a
| ________________________ | S
| ________________________ | t
| ______________________ | sopra
| _____________________ | tutti
| ___________________ | Questo
| ___________________ | per
| ___________________ | aveva
| __________________ | ma
| _________________ | essere
| _________________ | non
| ________________ | essi
| ________________ | così

Il vincitore:

Soluzione più breve (per numero di caratteri, per lingua). Divertiti!


Modifica : tabella riassuntiva dei risultati finora (15/02/2012) (originariamente aggiunta dall'utente Nas Banov):

Lingua rilassata rigorosa
========= ======= ======
GolfScript 130 143
Perl 185
Windows PowerShell 148 199
Mathematica 199
Rubino 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

I numeri rappresentano la lunghezza della soluzione più breve in una lingua specifica. "Strict" si riferisce a una soluzione che implementa completamente la specifica (disegna |____|barre, chiude la prima barra in cima con una ____linea, tiene conto della possibilità di parole lunghe ad alta frequenza ecc.). "Rilassato" significa che alcune libertà sono state prese per accorciare alla soluzione.

Sono incluse solo soluzioni inferiori a 500 caratteri. L'elenco delle lingue è ordinato in base alla lunghezza della soluzione "rigorosa". 'Unix Toolchain' è usato per indicare varie soluzioni che usano la tradizionale shell * nix più un mix di strumenti (come grep, tr, sort, uniq, head, perl, awk).


4
Bene, 'barra più lunga' + parola = 80 potrebbe non rientrare in 80 caratteri se la seconda parola più comune è una parola molto più lunga. Sto cercando il "limite massimo" credo.
Brian

1
Normalizziamo l'involucro? 'She' = 'lei'?
Brian

2
La realizzazione da parte dell'IMO, sia in termini di tempo di esecuzione che di utilizzo della memoria, sembra una sfida più interessante del conteggio dei personaggi.
Frank Farmer,

81
Sono felice di vedere che le mie parole preferite se tsono rappresentate.
indiv

8
@indiv, @Nas Banov - il tokenizer troppo stupido e semplice legge "non" come {didn, t} e "lei è" come {lei, s} :)
hobbs

Risposte:


123

LabVIEW 51 nodi, 5 strutture, 10 diagrammi

Insegnare all'elefante a tap-dance non è mai carino. Ah, salterò il conteggio dei personaggi.

codice labVIEW

risultati

Il programma scorre da sinistra a destra:

spiegazione del codice labVIEW


10
Non ne vale la pena

4
LabVIEW è molto contento del suo controllo hardware e della sua nicchia di misurazione, ma è davvero terribile per la manipolazione delle stringhe.
Joe Z,

19
La migliore risposta di golf del codice che abbia mai visto. +1 per pensare fuori dagli schemi!
Blair Holloway il

1
Devo contare gli elementi per noi ... ogni casella e widget che hai dovuto trascinare sullo schermo conta.
dmckee --- ex-moderatore gattino

1
Sarebbe possibile aggiungere un collegamento a una versione più grande di quei grafici?
Svish,

42

Ruby 1.9, 185 caratteri

(fortemente basato sulle altre soluzioni di Ruby)

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}]

Invece di utilizzare qualsiasi opzione della riga di comando come le altre soluzioni, puoi semplicemente passare il nome file come argomento. (ie ruby1.9 wordfrequency.rb Alice.txt)

Dato che sto usando letterali di personaggi qui, questa soluzione funziona solo in Ruby 1.9.

Modifica: sostituisce i punti e virgola con interruzioni di riga per "leggibilità". : P

Modifica 2: Shtééf ha sottolineato che ho dimenticato lo spazio finale - risolto ciò.

Modifica 3: rimosso di nuovo lo spazio finale;)


Manca lo spazio finale, dopo ogni parola.
Stéphan Kochen,

Aww sparare, ignorare quello. Sembra che il golf sia stato appena aggiornato, non è più necessario lo spazio finale. :)
Stéphan Kochen,

Non sembra adattarsi a "superlongstringstring" in seconda o successiva posizione? (vedi descrizione del problema)
Nas Banov,

2
Sembra davvero mantenibile.
Zombi,

39

GolfScript, 177 175 173 167 164 163 144 131 130 caratteri

Lento - 3 minuti per il testo di esempio (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*'| '@}/

Spiegazione:

{           #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
}/

"Corretto" (si spera). (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*'| '@}/

Meno lento - mezzo minuto. (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*'| '@}/

Output visibile nei registri di revisione.


2
Informazioni su GolfScript: golfscript.com/golfscript
Assaf Lavie

2
Non è corretto, nel senso che se la seconda parola è davvero lunga passerà alla riga successiva.
Gabe,

5
"dividi per zero" ... GolfScript lo consente?
JAB,

35

206

shell, grep, tr, grep, sort, uniq, sort, head, perl

~ % 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, appena visto sopra: sort -nr-> sort -ne poi head->tail => 208 :)
update2: erm, ovviamente quanto sopra è sciocco, poiché verrà invertito in seguito. Quindi, 209.
update3: ottimizzato regexp di esclusione -> 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$_"'



per divertimento, ecco una versione solo perl (molto più veloce):

~ % 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

35

Transact SQL set based solution (SQL Server 2005) 1063 892 873 853 827 820 783 683 647 644 630 caratteri

Grazie a Gabe per alcuni suggerimenti utili per ridurre il conteggio dei personaggi.

NB: le interruzioni di riga aggiunte per evitare le barre di scorrimento sono necessarie solo l'ultima interruzione di riga.

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 @

Versione leggibile

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 @

Produzione

 _________________________________________________________________________ 
|_________________________________________________________________________| she
|_______________________________________________________________| You
|____________________________________________________________| said
|_____________________________________________________| Alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| at
|_____________________________| with
|__________________________| on
|__________________________| all
|_______________________| This
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| So
|___________________| very
|__________________| what

E con la lunga corda

 _______________________________________________________________ 
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| Alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| at
|_________________________| with
|_______________________| on
|______________________| all
|____________________| This
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| So
|________________| very
|________________| what

12
Ti ho dato un +1 perché l'hai fatto in T-SQL, e per citare il Team America: "Hai le palle. Mi piacciono le palle."

Mi sono preso la libertà di convertire alcuni spazi in nuove righe per renderlo più leggibile. Spero di non aver rovinato tutto. L'ho anche minimizzato un po 'di più.
Gabe,

3
Quel codice mi sta urlando! : O
Joey,

1
Un buon modo per salvare è passare 0.000a just 0, quindi usando al -Cposto di 1.0/C. E fare FLOATin REALsalverà un colpo troppo. La cosa più grande, tuttavia, è che sembra che tu abbia molti AScasi che dovrebbero essere facoltativi.
Gabe,

1
OK, che ne dici SELECT [ ] FROM (SELECT $0 O, ' '+REPLICATE('_', MAX(C)*@F)+' ' [ ] FROM # UNION SELECT $1/C, '|'+REPLICATE('_',C*@F)+'| '+W FROM #)X ORDER BY O?
Gabe,

34

Rubino 207 213 211 210 207 203 201 200 caratteri

Un miglioramento su Anurag, che incorpora suggerimenti di rfusca. Rimuove anche l'argomento per ordinare e alcuni altri golf minori.

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} "}

Eseguire come:

ruby GolfedWordFrequencies.rb < Alice.txt

Modifica: rimetti 'mette' dentro, deve essere lì per evitare di avere virgolette nell'output.
Edit2: File modificato-> IO
Edit3: rimosso / i
Edit4: parentesi rimosse intorno (f * 1.0),
ricominciato Edit5: usa l'aggiunta di stringa per la prima riga; espandersi ssul posto.
Edit6: Made m float, rimosso 1.0. EDIT: non funziona, cambia lunghezza. EDIT: non peggio di prima
Edit7: utilizzare STDIN.read.


+1 - Adoro la parte di smistamento, molto intelligente :)
Anurag

Ehi, piccola ottimizzazione rispetto a trovarne la maggior parte in primo luogo. :)
archgoon,

Bello! Aggiunte due delle modifiche che ho apportato anche nella versione di Anurag. Si rade via un altro 4.
Stéphan Kochen

La soluzione si è discosta dall'output originale, sto andando a cercare e capire dove è successo.
archgoon,

1
C'è una variante più breve di questo verso il basso ulteriormente.
archgoon,

28

Mathematica ( 297 284 248 244 242 199 caratteri) Pure funzionale

e Test di legge di Zipf

Guarda mamma ... niente vars, niente mani, .. niente testa

Modifica 1> alcuni shorthands definiti (284 caratteri)

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]

Alcune spiegazioni

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)

Produzione

testo alternativo http://i49.tinypic.com/2n8mrer.jpg

Mathematica non è adatta per giocare a golf, e questo è solo per via dei nomi lunghi e descrittivi delle funzioni. Funzioni come "RegularExpression []" o "StringSplit []" mi fanno solo singhiozzare :(.

Test di legge di Zipf

La legge di Zipf prevede che per un testo in linguaggio naturale, il diagramma Log (Rank) vs Log (occorrenze) segue un lineare relazione .

La legge viene utilizzata nello sviluppo di algoritmi per la crittografia e la compressione dei dati. (Ma NON è la "Z" dell'algoritmo LZW).

Nel nostro testo, possiamo provarlo con il seguente

 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]

Il risultato è (abbastanza ben lineare)

testo alternativo http://i46.tinypic.com/33fcmdk.jpg

Modifica 6> (242 caratteri)

Refactoring del Regex (nessuna funzione Select più)
Eliminazione di 1 parola carattere
Definizione più efficiente per la funzione "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]

Modifica 7 → 199 caratteri

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]
  • Sostituito fcon Transposee Slot( #1/#2 ) argomenti.
  • Non abbiamo bisogno di parentesi puzzolenti (usare f@xinvece che f[x]dove possibile)


9
Pensi che "RegularExpression" sia male? Ho pianto quando ho digitato "System.Text.RegularExpressions.Regex.Split" nella versione C #, fino a quando non ho visto il codice Objective-C: "stringWithContentsOfFile", "enumerateSubstringsInRange", "NSStringEnumerationByWords", "ordinatoArrayUsingComparator" e così via .
Gabe,

2
@Gabe Grazie ... mi sento meglio ora. In spagnolo diciamo "mal de muchos, consuelo de tontos". Qualcosa del tipo "Molti travagliati, sciocchi sollevati": D
Dr. belisarius

1
Il |i|è ridondante nella vostra regex perché avete già .|.
Gabe,

1
Mi piace quel detto spagnolo. La cosa più vicina a cui riesco a pensare in inglese è "la miseria ama la compagnia". Ecco il mio tentativo di traduzione: "È uno sciocco che, quando soffre, si consola nel pensare agli altri nella stessa situazione". Incredibile lavoro sull'implementazione di Mathematica, tra l'altro.
Dreeves,

@dreeves La follia supera facilmente la barriera linguistica ... Sono contento di vederti come il mio piccolo programma Mathematica, sto appena iniziando a imparare la lingua
Dr. belisarius,

26

C # - 510 451 436 446 434 426 422 caratteri (minimizzato)

Non così breve, ma ora probabilmente corretto! Nota, la versione precedente non mostrava la prima riga delle barre, non ridimensionava correttamente le barre, scaricava il file invece di ottenerlo da stdin e non includeva tutta la verbosità C # richiesta. Potresti facilmente radere molti tratti se C # non avesse bisogno di troppe schifezze extra. Forse Powershell potrebbe fare di meglio.

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 caratteri con lendivisor inline (che lo rende 22 volte più lento) nella forma seguente (newline utilizzate per spazi selezionati):

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));}}

+1 per lo smart-ass che scarica il file in linea. :)
sarnold,

1
Ruba l'URL breve dalla risposta di Matt.
indiv

2
Secondo le specifiche, il file deve essere reindirizzato o passato come args. Se dovessi supporre che args [0] contenesse il nome del file locale, potresti accorciarlo considerevolmente usando args [0] invece di (new WebClient ()). DownloadString (@ " gutenberg.org/files/11/11. txt " ) -> ti farebbe risparmiare circa 70 caratteri
thorkia,

1
Ecco una versione che sostituisce la chiamata WebClient con args 0, una chiamata a StreamReader e la rimozione di alcuni spazi extra. Conteggio totale dei caratteri = 413 var a = Regex.Replace ((nuovo StreamReader (args [0])). ReadToEnd (), "[^ a-zA-Z]", "") .ToLower (). Split ('' ) .Dove (x =>! (new [] { "il", "e", "di", "a", "a", "i", "it", "in", "o"," è "}). Contiene (x)). GroupBy (x => x) .Select (g => new {w = g.Key, c = g.Count ()}). OrderByDescending (x => xc). Skip (1) .Take (22) .ToList (); var m = a.OrderByDescending (x => xc) .First (); a.ForEach (x => Console.WriteLine ("|" + new String (' _ ', xc * (80-mwLength-4) / mc) + "|" + xw));
thorkia,

"nuovo StreamReader" senza "utilizzo" è sporco. File.ReadAllText (args [0]) o Console.In.ReadToEnd () sono molto meglio. In quest'ultimo caso puoi anche rimuovere l'argomento dal tuo Main (). :)
Rotsor

25

Perl, 237 229 209 caratteri

(Aggiornato di nuovo per battere la versione Ruby con più trucchi da golf sporchi, sostituendo split/[^a-z/,lcconlc=~/[a-z]+/g , ed eliminando un assegno di stringa vuota in un altro luogo. Questi sono stati ispirati dalla versione di Ruby, quindi credito quando il credito è dovuto.)

Aggiornamento: ora con Perl 5.10! Sostituire printcon saye utilizzare ~~per evitare a map. Questo deve essere invocato sulla riga di comando come perl -E '<one-liner>' alice.txt. Poiché l'intera sceneggiatura è su una riga, scriverla come una riga non dovrebbe presentare alcuna difficoltà :).

 @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];

Si noti che questa versione si normalizza per caso. Questo non accorcia la soluzione, poiché la rimozione ,lc(per il case inferiore) richiede l'aggiunta A-Zal regex diviso, quindi è un lavaggio.

Se sei su un sistema in cui una nuova riga è un personaggio e non due, puoi accorciarlo di altri due caratteri usando una nuova riga letterale al posto di \n. Tuttavia, non ho scritto l'esempio sopra in quel modo, dato che è "più chiaro" (ah!) In quel modo.


Ecco una soluzione perl per lo più corretta, ma non abbastanza remota:

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";
}

Quanto segue è il più breve possibile ma rimane relativamente leggibile. (392 caratteri).

%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;

Ha alcuni bug in questo momento; fissaggio e accorciamento.
JSB ձոգչ

4
Questo non copre il caso in cui la seconda parola è molto più lunga della prima, giusto?
Joey,

1
Entrambi gli foreachs possono essere scritti come fors. Sono 8 caratteri in meno. Quindi hai il grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>, che credo possa essere scritto grep{!(/$_/i~~@s)}<>=~/[a-z]+/gper andare 4 più in basso. Sostituisci " "con $"e sei in calo di 1 altro ...
Zaid

sort{$c{$b}-$c{$a}}...per salvarne altri due. Puoi anche semplicemente passare %cinvece keys %calla sortfunzione e salvarne altri quattro.
mob

20

Windows PowerShell, 199 caratteri

$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]

(L'ultima interruzione di riga non è necessaria, ma inclusa qui per la leggibilità.)

(Il codice corrente e i miei file di test sono disponibili nel mio repository SVN . Spero che i miei casi di test rilevino gli errori più comuni (lunghezza della barra, problemi con la corrispondenza regex e alcuni altri))

ipotesi:

  • ASCII USA come input. Probabilmente diventa strano con Unicode.
  • Almeno due parole non-stop nel testo

Storia

Versione rilassata (137), dato che ormai è conteggiato separatamente, apparentemente:

($x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *)[-1..-22]|%{"|$('_'*(76*$_.Count/$x[-1].Count))| "+$_.Name}
  • non chiude la prima barra
  • non tiene conto della lunghezza della parola della non prima parola

Le variazioni della lunghezza della barra di un carattere rispetto ad altre soluzioni sono dovute al fatto che PowerShell utilizza l'arrotondamento anziché il troncamento durante la conversione di numeri in virgola mobile in numeri interi. Tuttavia, poiché l'attività richiede solo una lunghezza della barra proporzionale, ciò dovrebbe andare bene.

Rispetto ad altre soluzioni ho adottato un approccio leggermente diverso nel determinare la lunghezza della barra più lunga semplicemente provando e prendendo la massima lunghezza tale dove nessuna linea è più lunga di 80 caratteri.

Una versione precedente spiegata può essere trovata qui .


Impressionante, sembra Powershell è un ambiente adatto per il golf. Il tuo approccio considerando la lunghezza della barra è esattamente quello che ho cercato di descrivere (non così brillantemente, lo ammetto) nelle specifiche.
ChristopheD,

1
@ChristopheD: Nella mia esperienza (Anarchy Golf, alcune attività di Project Euler e altre attività solo per divertimento), PowerShell è in genere solo leggermente peggiore di Ruby e spesso legato o migliore di Perl e Python. Nessuna corrispondenza per GolfScript, però. Ma per quanto posso vedere, questa potrebbe essere la soluzione più breve che rappresenta correttamente la lunghezza delle barre ;-)
Joey

Apparentemente avevo ragione. Powershell può fare di meglio, molto meglio! Fornisci una versione estesa con commenti.
Gabe,

Johannes: Ci hai provato -split("\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z]")? Per me funziona.
Gabe,

Non dimenticare di interpolare la stringa di output: "|$('_'*($w*$_.count/$x[0].count))| $($_.name) "(o eliminare l'ultimo spazio, in quanto è una specie di automatico). E puoi usarlo -split("(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z])+")per salvarne un po 'di più non includendo gli spazi (o usare [-2..-23]).
Gabe,

19

Ruby, 215, 216 , 218 , 221 , 224 , 236 , 237 caratteri

aggiornamento 1: Evviva ! È un pareggio con la soluzione di JS Bangs . Non riesco a pensare a un modo per ridurre ulteriormente :)

aggiornamento 2: ha giocato un trucco da golf sporco. Modificato eachinmap salvare 1 carattere :)

aggiornamento 3: modificato File.reada IO.read+2. Array.group_bynon è stato molto fruttuoso, cambiato in reduce+6. Il controllo insensibile al maiuscolo / minuscolo non è necessario dopo l'involucro inferiore condowncase regex +1. L'ordinamento in ordine decrescente avviene facilmente negando il valore +6. Risparmio totale +15

aggiornamento 4: [0]anziché .first+3. (@ Shtééf)

aggiornamento 5: espandi la variabile lsul posto, +1. Espandi variabile ssul posto, +2. (@ Shtééf)

aggiornamento 6: utilizzare l'aggiunta di stringa anziché l'interpolazione per la prima riga, +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} "}

aggiornamento 7: ho attraversato molti hoopla per rilevare la prima iterazione all'interno del ciclo, usando le variabili di istanza. Tutto quello che ho è +1, anche se forse c'è potenziale. Preservare la versione precedente, perché credo che questa sia magia nera. (@ 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} "}

Versione leggibile

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

Usare:

echo "Alice.txt" | ruby -ln GolfedWordFrequencies.rb

Produzione:

 _________________________________________________________________________
|_________________________________________________________________________| she 
|_______________________________________________________________| you 
|____________________________________________________________| said 
|_____________________________________________________| alice 
|_______________________________________________| was 
|___________________________________________| that 
|____________________________________| as 
|________________________________| her 
|_____________________________| with 
|_____________________________| at 
|____________________________| s 
|____________________________| t 
|__________________________| on 
|__________________________| all 
|_______________________| this 
|_______________________| for 
|_______________________| had 
|_______________________| but 
|______________________| be 
|_____________________| not 
|____________________| they 
|____________________| so 

3
"P" non è una scorciatoia per "put"? Ciò potrebbe radere alcuni.
rfusca,

1
Bello. Il tuo uso scan, però, mi ha dato un'idea migliore, quindi sono andato di nuovo avanti :).
JSB ձոգչ

2
Devi ridimensionare le barre in modo che la parola più lunga più la sua barra si adattino a 80 caratteri. Come ha suggerito Brian, una lunga seconda parola interromperà il tuo programma.
Gabe,

3
Mi chiedo perché questo stia ancora raccogliendo voti. La soluzione non è corretta (nel caso generale) e le soluzioni Ruby a due vie più brevi sono ora disponibili.
Joey,

1
Ora, correggimi se sbaglio, ma invece di usare "downcase", perché non usi il flag insensibile al maiuscolo / minuscolo REGEXP, che salva 6-7 byte, non è vero?
st0le

19

Python 2.x, approccio latitudinale = 227 183 caratteri

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

Consentendo la libertà nell'implementazione, ho costruito una concatenazione di stringhe che contiene tutte le parole richieste per esclusione ( the, and, of, to, a, i, it, in, or, is) - inoltre esclude le due famigerate "parole" se tdall'esempio - e ho lanciato gratuitamente l'esclusione per an, for, he. Ho provato tutte le concatenazioni di quelle parole contro il corpus delle parole di Alice, la Bibbia di King James e il file Jargon per vedere se ci sono parole che verranno erroneamente escluse dalla stringa. Ed è così che sono finito con due stringhe di esclusione: itheandtoforinise andithetoforinis.

PS. preso in prestito da altre soluzioni per abbreviare il codice.

=========================================================================== she 
================================================================= you
============================================================== said
====================================================== alice
================================================ was
============================================ that
===================================== as
================================= her
============================== at
============================== with
=========================== on
=========================== all
======================== this
======================== had
======================= but
====================== be
====================== not
===================== they
==================== so
=================== very
=================== what
================= little

declamazione

Per quanto riguarda le parole da ignorare, si potrebbe pensare che sarebbero state prese dall'elenco delle parole più utilizzate in inglese. Tale elenco dipende dal corpus di testo utilizzato. Per uno degli elenchi più popolari ( 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 ), le prime 10 parole sono:the be(am/are/is/was/were) to of and a in that have I

Le prime 10 parole del testo di Alice nel Paese delle Meraviglie sono the and to a of it she i you said
Le prime 10 parole del File Jargon (v4.4.7) sonothe a of to and in is that or for

Quindi la domanda è: perché è orstato incluso nell'elenco dei problemi ignorati, dove è ~ 30 ° in popolarità quando la parola that(8 ° più usata) non lo è. ecc. ecc. Quindi credo che la lista da ignorare debba essere fornita in modo dinamico (o potrebbe essere omessa).

Un'idea alternativa sarebbe semplicemente quella di saltare le prime 10 parole dal risultato - che in realtà accorcerebbe la soluzione (elementare - dovrebbe mostrare solo le voci dall'undicesima alla trentaduesima).


Python 2.x, approccio puntiglioso = 277 243 caratteri

Il grafico disegnato nel codice sopra è semplificato (usando solo un carattere per le barre). Se si desidera riprodurre esattamente il grafico dalla descrizione del problema (che non era richiesto), questo codice lo farà:

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

Prendo un problema con la scelta in qualche modo casuale delle 10 parole da escludere, the, and, of, to, a, i, it, in, or, isquindi quelle devono essere passate come parametri della riga di comando, in questo modo:
python WordFrequencyChart.py the and of to a i it in or is <"Alice's Adventures in Wonderland.txt"

Sono 213 caratteri + 30 se si tiene conto dell'elenco "originale" ignora trasmesso sulla riga di comando = 243

PS. Il secondo codice fa anche "aggiustamento" per le lunghezze di tutte le parole in alto, quindi nessuna di esse traboccerà in caso degenerato.

 _______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|_____________________________________________________| said
|______________________________________________| alice
|_________________________________________| was
|______________________________________| that
|_______________________________| as
|____________________________| her
|__________________________| at
|__________________________| with
|_________________________| s
|_________________________| t
|_______________________| on
|_______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|___________________| not
|_________________| they
|_________________| so

Bella soluzione finora, sebbene la parola ignora elenco non sia implementata (ancora) e le barre siano un po 'rudimentali al momento.
ChristopheD,

@ChristopheD: era lì, ma non c'era una "guida per l'utente". Ho appena aggiunto il testo del mazzo
Nas Banov,

Per quanto riguarda il tuo elenco di lingue e soluzioni: cerca le soluzioni che utilizzano la divisione \Wo l'uso \bin una regex perché molto probabilmente non sono conformi alle specifiche, il che significa che non si suddividono in cifre o _potrebbero anche non rimuovere le parole di arresto dalle stringhe come the_foo_or123bar. Potrebbero non apparire nel testo di prova, ma la specifica è abbastanza chiara in questo caso.
Joey,

Lavoro straordinario Nas, ho trascorso un pomeriggio cercando di ottimizzare questo e ho trovato solo un miglioramento. Puoi sys.argvre.findall(r'\b(?!(?:the|and|.|of|to|i[tns]|or)\b)\w+',sys.stdin.read().lower())
ridurlo

12

Haskell - 366 351 344 337 333 caratteri

(È stata mainaggiunta un'interruzione di riga per la leggibilità e nessuna interruzione di riga necessaria alla fine dell'ultima riga.)

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

Come funziona si vede meglio leggendo l'argomento al interactcontrario:

  • map f alfabeti minuscoli, sostituisce tutto il resto con spazi.
  • words produce un elenco di parole, eliminando lo spazio bianco di separazione.
  • filter (notElem words "the and of to a i it in or is")scarta tutte le voci con parole proibite.
  • group . sort ordina le parole e raggruppa quelle identiche in elenchi.
  • map hmappa ogni elenco di parole identiche a una tupla del modulo (-frequency, word).
  • take 22 . sort ordina le tuple in ordine decrescente di frequenza (la prima voce di tupla) e mantiene solo le prime 22 tuple.
  • b mappa le tuple alle barre (vedi sotto).
  • a antepone la prima riga di trattini bassi, per completare la barra più in alto.
  • unlines unisce tutte queste linee insieme a nuove linee.

La parte difficile è ottenere la lunghezza della barra corretta. Supponevo che solo i trattini bassi contassero per la lunghezza della barra, quindi ||sarebbe una barra di lunghezza zero. La funzione bmappe c xsopra x, dove xl'elenco dei istogrammi. L'intero elenco viene passato a c, in modo che ogni invocazione di cpossa calcolare il fattore di scala per sé chiamando u. In questo modo, evito di usare la matematica a virgola mobile o razionali, le cui funzioni di conversione e importazioni consumerebbero molti caratteri.

Nota il trucco dell'uso -frequency. Questo elimina la necessità reversedel sortdato di ordinamento (ascendente) -frequencysaranno posti le parole con il maggior frequenza di prima. Successivamente, nella funzione u, -frequencyvengono moltiplicati due valori, che annullano la negazione.


Un lavoro molto bello (voterebbe a buon fine, ma ha esaurito i voti per oggi con tutte le grandi risposte in questa discussione).
ChristopheD,

Questo mi fa male agli occhi in un modo che è doloroso anche solo a pensare di descriverlo, ma ho imparato molto di Haskell decodificandolo in codice leggibile. Ben fatto signore. :-)
Owen S.

In realtà è ancora abbastanza idiomatico Haskell, anche se non molto efficiente. I nomi brevi lo fanno sembrare molto peggio di quello che è in realtà.
Thomas,

@Thomas: puoi dirlo di nuovo. :-)
Owen S.

1
Impossibile spostare div, in realtà! Provalo, l'uscita è sbagliata. Il motivo è che fare il divprima *perde la precisione.
MtnViewMark,

11

JavaScript 1.8 (SpiderMonkey) - 354

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)}

Purtroppo, for([k,v]in z)dalla versione di Rhino non sembra voler funzionare in SpiderMonkey, ed readFile()è un po 'più semplice rispetto all'utilizzo, readline()ma spostandosi fino alla 1.8 ci consente di usare le chiusure delle funzioni per tagliare qualche altra riga ....

Aggiunta di spazi bianchi per la leggibilità:

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)
}

Uso: js golf.js < input.txt

Produzione:

 _________________________________________________________________________ 
| _________________________________________________________________________ | lei
| _______________________________________________________________ | tu
| ____________________________________________________________ | disse
| ____________________________________________________ | alice
| ______________________________________________ | era
| ___________________________________________ | quello
| ___________________________________ | come
| ________________________________ | sua
| _____________________________ | a
| _____________________________ | con
| ____________________________ | S
| ____________________________ | t
| __________________________ | sopra
| _________________________ | tutti
| _______________________ | Questo
| ______________________ | per
| ______________________ | aveva
| ______________________ | ma
| _____________________ | essere
| _____________________ | non
| ___________________ | essi
| ___________________ | così

(versione base - non gestisce correttamente le larghezze della barra)

JavaScript (Rhino) - 405 395 387 377 368 343 304 caratteri

Penso che la mia logica di smistamento sia disattivata, ma ... io duno. Brainfart riparato.

Minificato (l'abuso \nè interpretato come a ;volte):

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)}

Ah signore. Credo che questo sia il tuo guanto. Chiedi al tuo secondo di parlare al mio.
dmckee --- ex gattino moderatore

2
A proposito ... mi piace un i[tns]?po '. Molto subdolo.
dmckee --- ex gattino moderatore

@dmckee - ben suonato, non credo di poter battere il tuo 336, goditi il ​​tuo meritato voto :)
Matt

Puoi sicuramente battere 336 ... C'è un taglio di 23 caratteri disponibile - .replace(/[^\w ]/g, e).split(/\s+/).map(può essere sostituito con .replace(/\w+/g,e usare la stessa funzione che hai .mapfatto ... Inoltre, non sei sicuro che Rhino supporti function(a,b)b.c-a.cinvece della tua funzione di ordinamento (lo spidermonkey lo fa), ma lo farà rasatura {return }... b.c-a.cè un tipo migliore che a.c<b.ctra ... Modifica una versione di Spidermonkey in fondo con queste modifiche
gnarf

Ho spostato la mia versione di SpiderMonkey in alto poiché è conforme al vincolo della larghezza della barra ... Sono anche riuscito a ritagliare alcuni caratteri in più nella versione originale utilizzando una regexp lookahead negativa per negare le parole consentendo un singolo rimpiazzo (), e ho giocato a golf alcuni se con ottima ?:base su cui lavorare però!
Gnarf,

11

Versione CLI PHP (450 caratteri)

Questa soluzione tiene conto dell'ultimo requisito che la maggior parte dei puristi ha deciso di ignorare. Questo è costato 170 caratteri!

Uso: php.exe <this.php> <file.txt>

minified:

<?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";?>

Leggibile dagli umani:

<?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";

?>

Produzione:

|-------------------------------------------------------------------------| she
|---------------------------------------------------------------| you
|------------------------------------------------------------| said
|-----------------------------------------------------| alice
|-----------------------------------------------| was
|-------------------------------------------| that
|------------------------------------| as
|--------------------------------| her
|-----------------------------| at
|-----------------------------| with
|--------------------------| on
|--------------------------| all
|-----------------------| this
|-----------------------| for
|-----------------------| had
|-----------------------| but
|----------------------| be
|---------------------| not
|--------------------| they
|--------------------| so
|-------------------| very
|------------------| what

Quando c'è una parola lunga, le barre sono regolate correttamente:

|--------------------------------------------------------| she
|---------------------------------------------------| thisisareallylongwordhere
|-------------------------------------------------| you
|-----------------------------------------------| said
|-----------------------------------------| alice
|------------------------------------| was
|---------------------------------| that
|---------------------------| as
|-------------------------| her
|-----------------------| with
|-----------------------| at
|--------------------| on
|--------------------| all
|------------------| this
|------------------| for
|------------------| had
|-----------------| but
|-----------------| be
|----------------| not
|---------------| they
|---------------| so
|--------------| very

11

Python 3.1 - 245 229 caratteri

Immagino che usare Counter sia una specie di imbroglio :) Ne ho appena letto circa una settimana fa, quindi questa è stata l'occasione perfetta per vedere come funziona.

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))

Stampa:

|____________________________________________________________________________| she
|__________________________________________________________________| you
|_______________________________________________________________| said
|_______________________________________________________| alice
|_________________________________________________| was
|_____________________________________________| that
|_____________________________________| as
|__________________________________| her
|_______________________________| with
|_______________________________| at
|______________________________| s
|_____________________________| t
|____________________________| on
|___________________________| all
|________________________| this
|________________________| for
|________________________| had
|________________________| but
|______________________| be
|______________________| not
|_____________________| they
|____________________| so

Parte del codice è stato "preso in prestito" dalla soluzione di AKX.


Manca la prima riga. E la lunghezza della barra non è corretta.
Joey,

nel tuo codice sembra che open('!')legga da stdin - su quale versione / sistema operativo è quella? o devi nominare il file '!'?
Nas Banov,

Denominare il file "!" :) Mi dispiace che non sia stato chiaro e avrei dovuto menzionarlo.
Sam Dolan,

11

perl, 205 191 189 caratteri / 205 caratteri (completamente implementato)

Alcune parti sono state ispirate dai precedenti contributi perl / ruby, un paio di idee simili sono state realizzate in modo indipendente, le altre sono originali. La versione più breve comprende anche alcune cose che ho visto / imparato da altri contributi.

Originale:

$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];

Ultima versione fino a 191 caratteri:

/^(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]

Ultima versione fino a 189 caratteri:

/^(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]

Questa versione (205 caratteri) tiene conto delle righe con parole più lunghe di quelle che verrebbero trovate in seguito.

/^(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]

10

Perl: 203 202 201 198 195 208 203/231 caratteri

$/=\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]

Implementazione alternativa e completa, incluso il comportamento indicato (bar-squishing globale) per il caso patologico in cui la parola secondaria è sia popolare che abbastanza lunga da combinare con oltre 80 caratteri ( questa implementazione è 231 caratteri ):

$/=\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"}

Le specifiche non hanno indicato da nessuna parte che questo doveva andare su STDOUT, quindi ho usato perl's warn () invece di print - quattro personaggi salvati lì. Mappa usata invece di foreach, ma credo che ci potrebbero essere ancora alcuni risparmi nella divisione (join ()). Comunque, è arrivato a 203 - potrebbe dormirci sopra. Almeno Perl ora è sotto il conteggio dei caratteri "shell, grep, tr, grep, sort, uniq, sort, head, perl" per ora;)

PS: Reddit dice "Ciao";)

Aggiornamento: rimosso join () a favore dell'assegnazione e della conversione scalare implicita. Fino a 202. Nota anche che ho approfittato della regola opzionale "ignora parole di 1 lettera" per eliminare 2 caratteri, quindi tieni presente che il conteggio delle frequenze rifletterà questo.

Aggiornamento 2: scambio scambiato e join implicito per l'uccisione di $ / per ottenere il file in un unico sorso usando <> in primo luogo. Stesse dimensioni, ma più cattive. Sostituito se (! $ Y) {} per $ y || {} &&, risparmiato un altro carattere => 201.

Aggiornamento 3: ha assunto il controllo della minuscola in anticipo (lc <>) spostando lc fuori dal blocco della mappa - Sostituito entrambi i regex per non utilizzare più l'opzione / i, poiché non più necessario. Costruito condizionato esplicito x? Y: z scambiato con perlgolf tradizionale || costrutto condizionale implicito - /^...$/i?1:$x{$ } ++ per /^...$/||$x{$ } ++ Hai salvato tre caratteri! => 198, ha rotto la barriera 200. Potrebbe dormire presto ... forse.

Aggiornamento 4: la privazione del sonno mi ha fatto impazzire. Bene. Più pazzo. Pensando che questo debba solo analizzare i normali file di testo felici, l'ho lasciato perdere se colpisce un valore nullo. Hai salvato due personaggi. Sostituito "lunghezza" con il più corto di 1 carattere (e molto più golfistico) y /// c - mi senti, GolfScript ?? Sto venendo per te!!! singhiozzare

Aggiornamento 5: Sleep Dep mi ha fatto dimenticare il limite di 22row e la limitazione della linea successiva. Eseguire il backup fino a 208 con quelli gestiti. Non male, 13 personaggi per gestirlo non è la fine del mondo. Giocato con regex di perl inline eval, ma avendo problemi a farlo funzionare e salvare i caratteri ... lol. Aggiornato l'esempio in modo che corrisponda all'output corrente.

Aggiornamento 6: Rimosse le parentesi graffe non necessarie che proteggono (...) per, poiché la caramella sintattica ++ consente di spingerla felicemente contro. Grazie al contributo di Chas. Owens (ricordando al mio cervello stanco), ho trovato la soluzione di classe di carattere [tns] lì dentro. Torna indietro a 203.

Aggiornamento 7: aggiunto il secondo pezzo di lavoro, l'implementazione completa delle specifiche (incluso il comportamento completo della barra per le parole lunghe secondarie, invece del troncamento che la maggior parte delle persone sta facendo, basato sulle specifiche originali senza l'esempio patologico)

Esempi:

 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|___________________________________________| that
|____________________________________| as
|________________________________| her
|_____________________________| with
|_____________________________| at
|__________________________| on
|__________________________| all
|_______________________| this
|_______________________| for
|_______________________| had
|_______________________| but
|______________________| be
|_____________________| not
|____________________| they
|____________________| so
|___________________| very
|__________________| what

Implementazione alternativa nell'esempio di un caso patologico:

 _______________________________________________________________
|_______________________________________________________________| she
|_______________________________________________________| superlongstringstring
|____________________________________________________| said
|______________________________________________| alice
|________________________________________| was
|_____________________________________| that
|_______________________________| as
|____________________________| her
|_________________________| with
|_________________________| at
|_______________________| on
|______________________| all
|____________________| this
|____________________| for
|____________________| had
|____________________| but
|___________________| be
|__________________| not
|_________________| they
|_________________| so
|________________| very
|________________| what

Puoi abbreviare la regex per le parole di arresto collassando is|in|it|iin i[snt]?- e quindi non c'è più alcuna differenza con la regola opzionale. (Hm, non avrei mai pensato di dire a un ragazzo di Perl come fare Regex: D) - unico problema ora: devo vedere come posso radere tre byte dalla mia soluzione per essere di nuovo migliore di Perl: - |
Joey,

Ok, ignora parte di ciò che ho detto prima. Ignorare le parole di una lettera è in effetti un byte più breve del non farlo.
Joey,

Ogni byte conta;) Ho pensato di fare il trucco newline, ma ho pensato che fosse in realtà lo stesso numero di byte, anche se c'erano meno caratteri stampabili. Sto ancora lavorando per vedere se riesco a ridurlo ancora un po ':)
Syntaera,

Ah bene, la normalizzazione del caso mi ha riportato a 209. Non vedo cos'altro potrei tagliare. Sebbene PowerShell possa essere più corto di Perl. ;-)
Joey

Non vedo dove limiti l'output alle prime 22 parole, né dove ti assicuri che una lunga seconda parola non venga a capo.
Gabe,

9

F #, 452 caratteri

Semplice: ottieni una sequenza adi coppie di conteggio parole, trova il miglior moltiplicatore di conteggio parole per colonna k, quindi stampa i risultati.

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

Esempio (ho conteggi freq diversi da te, non so perché):

% 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

risulta che la mia soluzione era davvero un po 'fuori uso (a causa di un po' di specifiche diverse), le soluzioni corrispondono ora ;-)
ChristopheD

+1 per l'unica corretta implementazione del ridimensionamento della barra finora
Rotsor

2
(@Rotsor: Ironico, dato che la mia è la soluzione più antica.)
Brian

Scommetto che potresti accorciarlo un po 'unendo le fasi di divisione, mappa e filtro. Mi aspetto anche che non avresti bisogno di così tanti floats.
Gabe,

Le funzioni di annidamento non sono in genere più brevi rispetto all'utilizzo dell'operatore pipeline |>?
Joey,

8

Python 2.6, 347 caratteri

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))

Produzione:

 _________________________________________________________________________
|_________________________________________________________________________| she 
|_______________________________________________________________| you 
|____________________________________________________________| said 
|_____________________________________________________| alice 
|_______________________________________________| was 
|___________________________________________| that 
|____________________________________| as 
|________________________________| her 
|_____________________________| with 
|_____________________________| at 
|____________________________| s 
|____________________________| t 
|__________________________| on 
|__________________________| all 
|_______________________| this 
|_______________________| for 
|_______________________| had 
|_______________________| but 
|______________________| be 
|_____________________| not 
|____________________| they 
|____________________| so 

1
Puoi perdere la linea bm=(76.-len(W[0][0]))/W[0][1]poiché stai usando bm solo una volta (crea la riga successiva U=lambda n:"_"*int(n*(76.-len(W[0][0]))/W[0][1]), elimina 5 caratteri. Inoltre: perché dovresti usare un nome variabile di 2 caratteri nel golf del codice? ;-)
ChristopheD

Nell'ultima riga lo spazio dopo la stampa non è necessario, si rade un personaggio
ChristopheD,

1
Non considera il caso in cui la seconda parola più frequente è molto lunga, giusto?
Joey,

@ChristopheD: Perché stavo fissando quel codice da troppo tempo. : P Buona cattura. @Johannes: anche questo potrebbe essere risolto, sì. Non sono sicuro che tutte le altre implementazioni lo abbiano fatto anche quando ho scritto questo.
AKX,

7

* sh (+ curl), soluzione parziale

Questo è incompleto, ma per l'inferno, ecco la frequenza delle parole che conta la metà del problema in 192 byte:

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

7

Gawk - 336 (originariamente 507) personaggi

(dopo aver corretto la formattazione dell'output; risolto il problema delle contrazioni; ottimizzazione; ottimizzazione ancora; eliminazione di un passaggio di ordinamento del tutto inutile; ottimizzazione ancora una volta; e ancora (ancora una volta ho rotto la formattazione); modificare un po 'di più; raccogliere la sfida di Matt, modificare disperatamente così altro; trovato un altro posto per salvarne alcuni, ma ne ha restituiti due per correggere il bug della lunghezza della barra)

Eh eh! Sono momentaneamente in vantaggio rispetto a [Matt's JavaScript] [1] counter counter challenge! ;) e [AKX's python] [2].

Il problema sembra richiedere un linguaggio che implementa array associativi nativi, quindi ovviamente ne ho scelto uno con un set di operatori orribilmente carente. In particolare, non è possibile controllare l'ordine in cui awk offre gli elementi di una mappa hash, quindi eseguo ripetutamente la scansione dell'intera mappa per trovare l'elemento attualmente più numeroso, stamparlo ed eliminarlo dall'array.

È tutto terribilmente inefficiente, con tutte le golfizzazioni che ho realizzato è diventato anche abbastanza orribile.

minified:

{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]}}

le interruzioni di riga solo per chiarezza: non sono necessarie e non devono essere conteggiate.


Produzione:

$ 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

Leggibile; 633 caratteri (originariamente 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]
    }
}

Bel lavoro, bene hai incluso una versione rientrata / commentata ;-)
ChristopheD

7

LISP comune, 670 caratteri

Sono un principiante LISP, e questo è un tentativo di utilizzare una tabella hash per il conteggio (quindi probabilmente non è il metodo più compatto).

(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)))))

può essere eseguito ad esempio con cat alice.txt | clisp -C golf.lisp.

In forma leggibile è

(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)))))

hai provato a installare una macro del lettore personalizzata per eliminare alcune dimensioni di input?
Aaron,

@Aaron in realtà non è stato banale nemmeno per me farlo funzionare ... :-) per la parte del golf ho usato solo variabili di una lettera e basta. Ad ogni modo, oltre alla verbosità piuttosto elevata che è inerente a CL per questa scala di problemi ("concatenate 'string", "setf" o "gethash" sono assassini ... in Python sono "+", "=", "[]" ), tuttavia, mi sono sentito molto peggio di quanto mi sarei aspettato anche a livello logico. In un certo senso ho la sensazione che lisp sia ok, ma il lisp comune è così e questo va oltre la denominazione (rileggendolo un commento molto ingiusto poiché la mia esperienza con CL è vicina allo zero).
6502

vero. schema renderebbe il golf un po 'più facile, con il singolo spazio dei nomi. invece di aggiungere una stringa ovunque, potresti (letrec ((una stringa) (b gethash)) ... (a "x" "yz") ...)
Aaron

6

C (828)

Sembra un sacco di codice offuscato e usa glib per string, list e hash. Il conteggio dei caratteri wc -mindica 828 . Non considera le parole a carattere singolo. Per calcolare la lunghezza massima della barra, considera la parola più lunga possibile tra tutte, non solo le prime 22. È una deviazione dalle specifiche?

Non gestisce gli errori e non rilascia memoria utilizzata.

#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);}

Le nuove righe vengono conteggiate come caratteri, ma puoi rimuoverle dalle righe che non sono istruzioni per il preprocessore. Per un golf, non considererei la liberazione della memoria una cattiva pratica.
Stéphan Kochen

ok ... metti tutto in una riga (aspettati le macro di preproc) e dato un versetto senza liberare mem (e con altri due spazi rimossi ... un piccolo miglioramento può essere fatto sulla "offuscamento", ad esempio *v=*v*(77-lw)/mdarà 929. .. ma penso che possa essere ok a meno che non trovo un modo per farlo molto più breve)
ShinTakezou

Penso che si possa spostare almeno int cnella maindichiarazione e mainviene implicitamente int(come lo sono tutti gli argomenti non tipizzati, afaik): main(c){...}. Probabilmente potresti anche semplicemente scrivere 0invece di NULL.
Joey,

farlo ... ovviamente attiverà qualche avvertimento con -Wallo con la -std=c99bandiera accesa ... ma suppongo che ciò sia inutile per un code-golf, giusto?
ShinTakezou,

uff, scusate le modifiche temporali a breve distanza, ... dovrei cambiare Without freeing memory stuff, it reaches 866 (removed some other unuseful space)qualcos'altro per non pensare alle persone che la differenza con la versione di memoria libera sia tutta in questo: ora la versione senza memoria libera ha un sacco di più "miglioramenti".
ShinTakezou,

6

Perl, 185 char

200 (leggermente rotto) 199 197 195 193 187 185 caratteri. Le ultime due nuove linee sono significative. Conforme alle specifiche.

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 prima riga carica i conteggi di parole valide in %X .

La seconda riga calcola il fattore di ridimensionamento minimo in modo che tutte le righe di output siano <= 80 caratteri.

La terza riga (contiene due caratteri di nuova riga) produce l'output.


Ciò non rimuoverà le parole di arresto da stringhe come "foo_the_bar". Anche la lunghezza della linea è troppo lunga (rileggi la specifica: "bar + spazio + parola + spazio <= 80 caratteri")
Joey,

5

Java - 886 865 756 744 742 744 752 742 714 680 caratteri

  • Aggiornamenti prima del primo 742 : regex migliorato, rimossi i tipi parametrici superflui, rimosso gli spazi bianchi superflui.

  • Aggiornamento 742> 744 caratteri : risolto l'hacking a lunghezza fissa. Dipende solo dalla prima parola, non da altre (ancora). Trovati diversi posti per abbreviare il codice ( \\sin regex sostituito e ArrayListsostituito da Vector). Ora sto cercando un modo breve per rimuovere la dipendenza e la lettura di Commons IO dallo stdin.

  • Aggiornamento 744> 752 caratteri : ho rimosso la dipendenza comune. Ora legge dallo stdin. Incolla il testo in stdin e premi Ctrl+Zper ottenere il risultato.

  • Aggiorna 752> 742 caratteri : ho rimosso publice uno spazio, ho creato il nome di classe 1 carattere anziché 2 e ora ignora le parole di una lettera.

  • Aggiornamento 742> 714 caratteri : aggiornato secondo i commenti di Carl: rimosso il compito ridondante (742> 730), sostituito m.containsKey(k)da m.get(k)!=null(730> 728), introdotto la sottostringa della linea (728> 714).

  • Aggiornamento 714> 680 caratteri : aggiornato secondo i commenti di Rotsor: miglioramento del calcolo della dimensione della barra per rimuovere il casting non necessario e migliorato split()per rimuovere inutili 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);}}

Versione più leggibile:

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);
 }
}

Produzione:

 _________________________________________________________________________
| _________________________________________________________________________ | lei
| _______________________________________________________________ | tu
| ____________________________________________________________ | disse
| _____________________________________________________ | alice
| _______________________________________________ | era
| ___________________________________________ | quello
| ____________________________________ | come
| ________________________________ | sua
| _____________________________ | con
| _____________________________ | a
| __________________________ | sopra
| __________________________ | tutti
| _______________________ | Questo
| _______________________ | per
| _______________________ | aveva
| _______________________ | ma
| ______________________ | essere
| _____________________ | non
| ____________________ | essi
| ____________________ | così
| ___________________ | molto
| __________________ | che cosa

Fa schifo che Java non abbia String#join()e chiuda (ancora).

Modifica di Rotsor:

Ho apportato diverse modifiche alla tua soluzione:

  • Elenco sostituito con una stringa []
  • Riutilizzato l'argomento "args" invece di dichiarare il mio array di stringhe. Utilizzato anche come argomento per .ToArray ()
  • Sostituito StringBuffer con una stringa (sì, sì, prestazioni terribili)
  • Sostituito l'ordinamento Java con un ordinamento selezione con arresto anticipato (devono essere trovati solo i primi 22 elementi)
  • Aggregato alcune dichiarazioni int in una singola istruzione
  • Implementato l'algoritmo non cheat trovando la linea di output più limitante. Lo ha implementato senza FP.
  • Risolto il problema del crash del programma quando c'erano meno di 22 parole distinte nel testo
  • Implementato un nuovo algoritmo di input di lettura, che è veloce e solo 9 caratteri più lungo di quello lento.

Il codice condensato è lungo 688 711 684 caratteri:

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 versione veloce ( 720 693 caratteri)

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);}}}

Versione più leggibile:

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 versione senza miglioramenti del comportamento è di 615 caratteri:

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);}}}

Non potresti semplicemente usare il nome completo IOUtilsinvece di importarlo? Per quanto posso vedere lo stai usando solo una volta comunque.
Joey,

5
In un certo senso, hai barato supponendo che la barra più lunga avrà esattamente 75 caratteri. Devi assicurarti che nessuna barra + parola sia più lunga di 80 caratteri.
Gabe,

Ti manca uno spazio dopo la parola. ;)
st0le

Mentre stavo tagliando la mia risposta , speravo di battere la proposta di BalusC. Devo ancora 200 personaggi, ugh! Mi chiedo quanto sarebbe lungo senza l'ipotesi di IO IO e 75 caratteri.
Jonathon Faust,

1
Sembra che potresti radere alcuni personaggi creando buna stringa invece di una StringBuffer. Non voglio pensare a quale sarebbe la performance (soprattutto perché stai aggiungendo un personaggio alla volta).
Michael Myers

4

Scala 2.8, 311 314 320 330 332 336 341 375 caratteri

compresa la regolazione delle parole lunghe. Idee prese in prestito dalle altre soluzioni.

Ora come 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)

Corri con

scala -howtorun:script a.scala alice.txt

A proposito, la modifica da 314 a 311 caratteri in realtà rimuove solo 1 carattere. Qualcuno ha sbagliato il conteggio prima (CR di Windows?).


4

Clojure 282 rigoroso

(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 po 'più leggibile:

(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)))

4

Scala, 368 caratteri

Innanzitutto, una versione leggibile con 592 caratteri:

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)
    })
  }
}

L'output della console è simile al seguente:

$ 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

Possiamo fare un po 'di minimizzazione aggressiva e arrivare a 415 caratteri:

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 sessione della console è simile alla seguente:

$ 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

Sono sicuro che un esperto di Scala potrebbe fare ancora meglio.

Aggiornamento: nei commenti Thomas ha fornito una versione ancora più breve, con 368 caratteri:

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}}

Leggibilmente, con 375 caratteri:

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)
  }
}

383 caratteri: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}}
Thomas Jung,

Certo, il sempre utile per la comprensione! Bello!
pr1001,

3

Java - 896 caratteri

931 caratteri

1233 caratteri resi illeggibili

1977 caratteri "non compressi"


Aggiornamento: ho ridotto in modo aggressivo il conteggio dei personaggi. Omette parole di una sola lettera per specifica aggiornata.

Invidio tanto C # e 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)+" ");}}}

"Leggibile":

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)+" ");
      }
   }
}

Uscita di Alice:

 _________________________________________________________________________
|_________________________________________________________________________| she
|_______________________________________________________________| you
|_____________________________________________________________| said
|_____________________________________________________| alice
|_______________________________________________| was
|____________________________________________| that
|____________________________________| as
|_________________________________| her
|______________________________| with
|______________________________| at
|___________________________| on
|__________________________| all
|________________________| this
|________________________| for
|_______________________| had
|_______________________| but
|______________________| be
|______________________| not
|____________________| they
|____________________| so
|___________________| very
|___________________| what

Uscita di Don Chisciotte (anche di Gutenberg):

 ________________________________________________________________________
|________________________________________________________________________| that
|________________________________________________________| he
|______________________________________________| for
|__________________________________________| his
|________________________________________| as
|__________________________________| with
|_________________________________| not
|_________________________________| was
|________________________________| him
|______________________________| be
|___________________________| don
|_________________________| my
|_________________________| this
|_________________________| all
|_________________________| they
|________________________| said
|_______________________| have
|_______________________| me
|______________________| on
|______________________| so
|_____________________| you
|_____________________| quixote

8
Totalmente carpa, non c'è davvero modo di accorciarla in Java? Spero che vieni pagato per numero di personaggi e non per funzionalità :-)
Nas Banov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.