Построить таблицу ASCII наиболее часто используемых слов в данном тексте [закрыто]


156

Соревнование:

Построить таблицу ASCII наиболее часто используемых слов в данном тексте.

Правила:

  • Принимайте a-zи A-Z(буквенные символы) как часть слова.
  • Игнорировать корпус ( She== sheдля нашей цели).
  • Не обращайте внимания на следующие слова (я знаю довольно произвольно): the, and, of, to, a, i, it, in, or, is
  • Пояснение: учитывая don't: это будет восприниматься как 2 разных «слова» в диапазонах a-zи A-Z: ( donи t).

  • По желанию (сейчас уже слишком поздно для формального изменения спецификаций) вы можете отказаться от всех однобуквенных «слов» (это может также привести к сокращению списка игнорирования).

Проанализируйте данные text(прочитайте файл, указанный с помощью аргументов командной строки или переданный по конвейеру; предположите us-ascii) и создайте нам a word frequency chartсо следующими характеристиками:

  • Отобразите диаграмму (см. Также пример ниже) для 22 наиболее распространенных слов (упорядоченных по убыванию частоты).
  • Столбец widthпредставляет количество вхождений (частоту) слова (пропорционально). Добавьте один пробел и напечатайте слово.
  • Убедитесь, что эти строки (плюс пробел-слово-пробел) всегда подходят : bar+ [space]+word + [space]должно быть всегда <= 80символов (убедитесь, что вы учитываете возможные различия длины строки и слова: например: второе наиболее распространенное слово может быть намного длиннее, чем первое пока не сильно отличается по частоте). Увеличьте ширину полосы в пределах этих ограничений и масштабируйте полосы соответственно (согласно частотам, которые они представляют).

Пример:

Текст для примера можно найти здесь ( Приключения Алисы в стране чудес, Льюис Кэрролл ).

Этот конкретный текст даст следующую диаграмму:

 _________________________________________________________________________
| _________________________________________________________________________ | она
| _______________________________________________________________ | ты
| ____________________________________________________________ | сказал
| ____________________________________________________ | Алиса
| ______________________________________________ | был
| __________________________________________ | который
| ___________________________________ | так как
| _______________________________ | ей
| ____________________________ | с участием
| ____________________________ | в
| ___________________________ | s
| ___________________________ | T
| _________________________ | на
| _________________________ | все
| ______________________ | этот
| ______________________ | для
| ______________________ | было
| _____________________ | но
| ____________________ | быть
| ____________________ | не
| ___________________ | Oни
| __________________ | так


К вашему сведению: это частоты, на которых построен график выше:

[(«она», 553), («ты», 481), («сказал», 462), («Алиса», 403), («был», 358), («тот
', 330), (' as ', 274), (' her ', 248), (' with ', 227), (' at ', 227), (' s ', 219), (' t '
, 218), ('on', 204), ('all', 200), ('this', 181), ('for', 179), ('had', 178), ('
но «, 175), (« быть », 167), (« не », 166), (« они », 155), (« так », 152)]

Второй пример (чтобы проверить, реализовали ли вы полную спецификацию): Замените каждый вхождение youв связанном файле Алиса в стране чудес с superlongstringstring:

 ________________________________________________________________
| ________________________________________________________________ | она
| _______________________________________________________ | superlongstringstring
| _____________________________________________________ | сказал
| ______________________________________________ | Алиса
| ________________________________________ | был
| _____________________________________ | который
| ______________________________ | так как
| ___________________________ | ей
| _________________________ | с участием
| _________________________ | в
| ________________________ | s
| ________________________ | T
| ______________________ | на
| _____________________ | все
| ___________________ | этот
| ___________________ | для
| ___________________ | было
| __________________ | но
| _________________ | быть
| _________________ | не
| ________________ | Oни
| ________________ | так

Победитель:

Кратчайшее решение (по количеству символов, по языку). Радоваться, веселиться!


Редактировать : Таблица с подведением итогов (2012-02-15) (первоначально добавлено пользователем Nas Banov):

Язык Relaxed Строгий
========= ======= ======
GolfScript 130 143
Perl 185
Windows PowerShell 148 199
Mathematica 199
Рубин 185 205
Unix Toolchain 194 228
Python 183 243
Clojure 282
Скала 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

Числа представляют длину кратчайшего решения на конкретном языке. «Строгий» относится к решению, которое полностью реализует спецификацию (рисует |____|столбцы, закрывает первый столбец сверху ____строкой, учитывает возможность длинных слов с высокой частотой и т. Д.). «Расслабленный» означает, что некоторые свободы были взяты, чтобы сократить до решения.

Только решения короче 500 символов включены. Список языков отсортирован по длине «строгого» решения. «Unix Toolchain» используется для обозначения различных решений, использующих традиционную * nix оболочку плюс набор инструментов (таких как grep, tr, sort, uniq, head, perl, awk).


4
Что ж, «самый длинный столбец» + слово = 80 может не подходить в пределах 80 столбцов, если второе наиболее распространенное слово - намного более длинное слово. Я ищу "максимальное ограничение", я думаю.
Брайан

1
Мы нормализуем корпус? «Она» = «она»?
Брайан

2
Выполнение этой задачи IMO, как с точки зрения времени выполнения, так и использования памяти, кажется более интересной задачей, чем подсчет символов.
Фрэнк Фармер

81
Я рад видеть, что мои любимые слова sи tпредставлены.
индивидуум

8
@indiv, @Nas Banov - глупый, слишком простой токенизатор читает «не» как {didn, t}, а «она есть» как {she, s} :)
Хоббс

Ответы:


123

LabVIEW 51 узел, 5 структур, 10 диаграмм

Научить слона танцевать чечетку никогда не бывает красиво. Я пропущу количество символов.

код labVIEW

полученные результаты

Программа течет слева направо:

код labVIEW объяснил


10
Оно того не стоит

4
LabVIEW очень доволен своей нишей для аппаратного контроля и измерения, но очень хорош для манипулирования струнами.
Джо Z

19
Лучший кодовый гольф-ответ, который я видел. +1 за нестандартное мышление!
Блэр Холлоуэй

1
Нужно посчитать элементы для нас ... каждый ящик и виджет, которые вы должны были перетащить на экран, имеет значение.
dmckee --- котенок экс-модератора

1
Можно ли добавить ссылку на увеличенную версию этих графиков?
Свиш

42

Рубин 1.9, 185 символов

(в значительной степени основано на других решениях 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}]

Вместо использования каких-либо ключей командной строки, как в других решениях, вы можете просто передать имя файла в качестве аргумента. (то есть ruby1.9 wordfrequency.rb Alice.txt)

Поскольку здесь я использую символьные литералы, это решение работает только в Ruby 1.9.

Редактировать: Заменены точки с запятой на разрывы строк для «читабельности». :П

Редактировать 2: Штеф указал, что я забыл конечный пробел - исправил это.

Редактировать 3: снова убрал завершающий пробел;)


Он пропускает пробел после каждого слова.
Стефан Кочен

О, стреляй, не обращай на это внимания. Похоже, что гольф был только что обновлен, больше не требуется прицепное место. :)
Стефан Кочен

Кажется, не подходит для 'superlongstringstring' во 2-й или более поздней позиции? (см. описание проблемы)
Нас Банов

2
Это выглядит действительно ремонтопригодным.
зомби

39

GolfScript, 177 175 173 167 164 163 144 131 130 символов

Медленно - 3 минуты для образца текста (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*'| '@}/

Объяснение:

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

«Правильно» (надеюсь). (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*'| '@}/

Менее медленно - полминуты. (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*'| '@}/

Вывод видим в журналах ревизий.



2
Неправильно, в том случае, если второе слово действительно длинное, оно переносится на следующую строку.
Гейб

5
"делить на ноль" ... GolfScript позволяет это?
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

хм, только что видел выше: sort -nr-> sort -nа потом head-> tail=> 208 :)
update2: эээ, конечно вышеупомянутое глупо, поскольку тогда это будет полностью изменено. Итак, 209.
update3: оптимизировано регулярное выражение исключения -> 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$_"'



для удовольствия, вот версия только для Perl (намного быстрее):

~ % 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 (SQL Server 2005) 1063 892 873 853 827 820 783 683 647 644 630 символов

Спасибо Гейбу за некоторые полезные предложения по уменьшению количества персонажей.

Примечание: добавлены разрывы строк, чтобы избежать прокрутки, требуется только последний разрыв строк.

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 @

Читаемая версия

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 @

Вывод

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

И с длинной строкой

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

12
Я дал тебе +1, потому что ты сделал это в T-SQL, и процитировал Team America - «У тебя есть шары. Я люблю шары».

Я позволил себе преобразовать некоторые пробелы в новые строки, чтобы сделать его более читабельным. Надеюсь, я не все испортил. Я также уменьшил это немного больше.
Гейб

3
Этот код кричит на меня! : O
Джои

1
Один хороший способ сэкономить - это изменить 0.000на «просто» 0, а затем использовать -Cвместо 1.0/C. И , сделав FLOATв REALсэкономите ход тоже. Но самое главное, что у вас много ASэкземпляров, которые должны быть необязательными.
Гейб

1
Хорошо, как насчет SELECT [ ] FROM (SELECT $0 O, ' '+REPLICATE('_', MAX(C)*@F)+' ' [ ] FROM # UNION SELECT $1/C, '|'+REPLICATE('_',C*@F)+'| '+W FROM #)X ORDER BY O?
Гейб

34

Рубин 207 213 211 210 207 203 201 200 символов

Улучшение Anurag, включая предложение от rfusca. Также убираются аргументы для сортировки и несколько других мелких игр в гольф.

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

Выполнить как:

ruby GolfedWordFrequencies.rb < Alice.txt

Редактировать: положить 'вводит' обратно, должно быть там, чтобы избежать вывода кавычек.
Edit2: измененный файл-> IO
Edit3: удалено / i
Edit4: удалены круглые скобки (f * 1.0), пересчитано
Edit5: использовать добавление строки для первой строки; расширить sна месте.
Edit6: Сделано м плавать, удалено 1,0. РЕДАКТИРОВАТЬ: не работает, меняет длину. РЕДАКТИРОВАТЬ: не хуже, чем до
Edit7: использовать STDIN.read.


+1 - люблю сортировку, очень умно :)
Anurag

Эй, небольшая оптимизация по сравнению с тем, чтобы в первую очередь придумать большую ее часть. :)
архунгун

Ницца! Добавлены два изменения, которые я также сделал в версии Anurag.
Бреет

Решение отклонилось от первоначального вывода, я собираюсь подвести итоги и выяснить, где это произошло.
архунгун

1
Есть более короткий вариант этого ниже.
архунгун

28

Mathematica ( 297 284 248 244 242 199 символов) Чистый Функциональный

и закон Зипфа

Смотри, мама ... нет варов, нет рук, .. нет головы

Правка 1> определены некоторые сокращения (284 символа)

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]

Некоторые объяснения

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)

Вывод

альтернативный текст http://i49.tinypic.com/2n8mrer.jpg

Mathematica не очень подходит для игры в гольф, и это только из-за длинных описательных названий функций. Такие функции, как "RegularExpression []" или "StringSplit []" просто заставляют меня рыдать :(.

Закон Зипфа

Закон Ципфа гласит, что для текста на естественном языке график « Лог (ранг) против журнала (вхождения) » следует линейному зависимости.

Закон используется при разработке алгоритмов криптографии и сжатия данных. (Но это НЕ «Z» в алгоритме LZW).

В нашем тексте мы можем проверить это следующим

 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]

Результат (довольно хорошо линейный)

альтернативный текст http://i46.tinypic.com/33fcmdk.jpg

Редактировать 6> (242 символа)

Рефакторинг Regex (больше не используется функция Select).
Удаление 1 символа слова.
Более эффективное определение для функции "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]

Редактировать 7 → 199 символов

BarChart[#2, BarOrigin->Left, ChartLabels->Placed[#1, After], Axes->None]&@@ 
  Transpose@Take[SortBy[Tally@StringSplit[ToLowerCase@Import@i, 
    RegularExpression@"(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"],Last], -22]
  • Заменяется fна Transposeи Slot( #1/ #2) аргументами.
  • Нам не нужны вонючие скобки (используйте f@xвместо, f[x]где это возможно)


9
Вы думаете, "RegularExpression" это плохо? Я плакал, когда набирал «System.Text.RegularExpressions.Regex.Split» в версии C #, пока не увидел код Objective-C: «stringWithContentsOfFile», «enumerateSubstringsInRange», «NSStringEnumerationByWords», «sortedArrayUsingCompara», soortedArrayUsingCompara ,
Гейб

2
@Gabe Спасибо ... Теперь я чувствую себя лучше. По-испански мы говорим "Mal de Muchos, consuelo de tontos" .. Что-то вроде "Многие обеспокоены, дураки с облегчением": D
Доктор Belisarius

1
Это |i|избыточно в вашем регулярном выражении, потому что у вас уже есть .|.
Гейб

1
Мне нравится эта испанская поговорка. Самая близкая вещь, о которой я могу думать в английском языке, это «страдание любит компанию». Вот моя попытка перевода: «Это дурак, который, страдая, утешает себя, думая о других в той же ситуации». Удивительная работа по реализации Mathematica, кстати.
dreeves

@dreeves Глупость легко преодолевает языковой барьер ... Рад, что ты похож на мою маленькую программу Mathematica, я только начинаю изучать язык
Dr. belisarius

26

C # - 510 451 436 446 434 426 422 символа (минимизировано)

Не так коротко, но сейчас, наверное, правильно! Обратите внимание, что предыдущая версия не показывала первую строку столбцов, неправильно масштабировала столбцы, загружала файл вместо получения его из stdin и не включала в себя все необходимые подробности C #. Вы можете легко сбрить много ударов, если C # не нужно так много лишней хрени. Может быть, Powershell мог бы сделать лучше.

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 символа с встроенным лендивизором (что делает его в 22 раза медленнее) в приведенной ниже форме (новые строки используются для выбора пробелов):

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 для умной задницы, загружающей файл в линию. :)
sarnold

1
Украдите короткий URL из ответа Мэтта.
индивидуум

2
В спецификации сказано, что файл должен быть передан в виде аргумента. Если вы предполагаете, что args [0] содержит локальное имя файла, вы можете значительно сократить его, используя args [0] вместо (new WebClient ()). DownloadString (@ " gutenberg.org/files/11/11. txt " ) -> это сэкономит вам около 70 символов
Thorkia

1
Вот версия, заменяющая вызов WebClient аргументами 0, вызов StreamReader и удаление нескольких лишних пробелов. Общее количество символов = 413 var a = Regex.Replace ((новый StreamReader (args [0])). ReadToEnd (), "[^ a-zA-Z]", "") .ToLower (). Split ('' ) .где (х =>! (новый [] { "в" и "и", "о", "к", "а", "я", "он", "в", "или",» это "}). Содержит (х)). GroupBy (х => х) .Select (г => новый {ш = g.Key, с = g.Count ()}). OrderByDescending (х => хс). 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));
Торкия

«Новый StreamReader» без «использования» грязный. File.ReadAllText (args [0]) или Console.In.ReadToEnd () намного лучше. В последнем случае вы даже можете удалить аргумент из вашего Main (). :)
Rotsor

25

Perl, 237 229 209 символов

(Обновлено снова бить версию Ruby , с большим количеством пакостей полей, замена split/[^a-z/,lcс lc=~/[a-z]+/g, и устранение чек на пустую строку в другом месте. Они были вдохновлены версии Руби, поэтому кредит , где кредит должен.)

Обновление: теперь с Perl 5.10! Замените printна sayи используйте, ~~чтобы избежать map. Это должно быть вызвано в командной строке как perl -E '<one-liner>' alice.txt. Поскольку весь сценарий находится в одной строке, его написание в виде одной строки не должно представлять никаких трудностей :).

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

Обратите внимание, что эта версия нормализуется для случая. Это не сокращает решение, так как удаление ,lc(для нижнего регистра) требует добавления A-Zк разделенному регулярному выражению, так что это мытье.

Если вы работаете в системе, где символ новой строки - это один символ, а не два, вы можете сократить его еще на два символа, используя вместо него буквальный символ новой строки \n. Тем не менее, я не написал вышеупомянутый пример таким образом, так как он "более ясен" (ха!) Таким образом.


Вот в основном правильное, но не достаточно короткое решение perl:

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

Ниже приводится краткая информация о том, насколько она может быть читаемой. (392 символа).

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

Есть несколько ошибок прямо сейчас; фиксация и укорочение.
JSB գչոգչ

4
Это не распространяется на случай, когда второе слово намного длиннее первого, верно?
Джои

1
Оба foreachс можно записать как forс. Это на 8 символов ниже. Тогда у вас есть то grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>, что, я полагаю, может быть написано, grep{!(/$_/i~~@s)}<>=~/[a-z]+/gчтобы пойти еще 4 вниз. Заменить " "с $"и вы вниз 1 больше ...
Заид

sort{$c{$b}-$c{$a}}...чтобы сохранить еще два. Вы также можете просто передать %cвместо keys %cк sortфункции и более сохранить четыре.
моб

20

Windows PowerShell, 199 символов

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

(Последний разрыв строки не обязателен, но включен здесь для удобства чтения.)

(Текущий код и мои тестовые файлы доступны в моем репозитории SVN . Я надеюсь, что мои тестовые примеры обнаруживают наиболее распространенные ошибки (длина строки, проблемы с соответствием регулярному выражению и некоторые другие))

Предположения:

  • US ASCII в качестве входных данных. Это, вероятно, становится странным с Unicode.
  • Как минимум два безостановочных слова в тексте

история

Расслабленная версия (137), так как сейчас она считается отдельно:

($x=$input-split'\P{L}'-notmatch'^(the|and|of|to|.?|i[tns]|or)$'|group|sort *)[-1..-22]|%{"|$('_'*(76*$_.Count/$x[-1].Count))| "+$_.Name}
  • не закрывает первый бар
  • не учитывает длину слова не первого слова

Различия в длинах столбцов одного символа по сравнению с другими решениями объясняются тем, что PowerShell использует округление вместо усечения при преобразовании чисел с плавающей точкой в ​​целые числа. Поскольку задача требует только длины пропорционального стержня, это должно быть хорошо.

По сравнению с другими решениями я использовал немного другой подход в определении длины самого длинного бара, просто попробовав и взяв наибольшую длину, где ни одна строка не длиннее 80 символов.

Более старая объясненная версия может быть найдена здесь .


Впечатляет, кажется, Powershell является подходящей средой для игры в гольф. Ваш подход к длине стержня - именно то, что я пытался описать (не так блестяще, я признаю) в спецификации.
ChristopheD

1
@ChristopheD: По моему опыту (Anarchy Golf, некоторые задачи Project Euler и некоторые другие задачи просто для удовольствия), PowerShell обычно лишь немного хуже, чем Ruby, и часто связан или лучше, чем Perl и Python. Впрочем, не подходит для GolfScript. Но, насколько я вижу, это может быть самое короткое решение, которое правильно учитывает длину стержней ;-)
Joey

Видимо я был прав. Powershell может сделать лучше - намного лучше! Пожалуйста, предоставьте расширенную версию с комментариями.
Гейб

Йоханнес: Вы пробовали -split("\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z]")? Меня устраивает.
Гейб

Не забудьте интерполировать выходную строку: "|$('_'*($w*$_.count/$x[0].count))| $($_.name) "(или исключить последний пробел, так как это автоматически). И вы можете использовать, -split("(?:\b(?:the|and|of|to|a|i[tns]?|or)\b|[^a-z])+")чтобы сэкономить еще несколько, не включая пробелы (или использовать [-2..-23]).
Гейб

19

Рубин, 215, 216 , 218 , 221 , 224 , 236 , 237 символов

Обновление 1: Ура ! Это связь с JS челкой ' решения . Не могу придумать способ урезать больше :)

Обновление 2: играли в грязную игру в гольф. Изменено, eachчтобы mapсохранить 1 символ :)

обновление 3: изменено File.readна IO.read+2. Array.group_byне был очень плодотворным, изменился на reduce+6. Чувствительность к регистру не требуется после нижнего кожуха сdowncase в регулярном выражении +1. Сортировка в порядке убывания легко выполняется путем отрицания значения +6. Общая экономия +15

обновление 4: [0]а не.first +3. (@ Shtééf)

обновление 5: развернуть переменную lна месте, +1. Развернуть переменнуюs на месте, +2. (@ Shtééf)

обновление 6: использовать добавление строки вместо интерполяции для первой строки +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} "}

Обновление 7: я прошел через много шумихи, чтобы обнаружить первую итерацию внутри цикла, используя переменные экземпляра. Все, что я получил, это +1, хотя, возможно, есть потенциал. Сохранение предыдущей версии, потому что я считаю, что это черная магия. (@ 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} "}

Читаемая версия

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

Использовать:

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

Вывод:

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

3
Разве «p» не является сокращением для «пут»? Это может побрить некоторых.
rfusca

1
Ницца. Ваше использование scan, тем не менее, дало мне лучшую идею, поэтому я снова стал впереди :).
JSB գչոգչ

2
Вам нужно масштабировать столбцы так, чтобы самое длинное слово плюс его столбик соответствовали 80 символам. Как предположил Брайан, длинное второе слово сломает вашу программу.
Гейб

3
Интересно, почему это все еще набирает голоса? Решение некорректно (в общем случае), и два пути решения Ruby с более короткой позицией уже здесь.
Джои

1
Теперь, поправьте меня, если я ошибаюсь, но вместо использования "downcase", почему бы вам не использовать флаг REGEXP без учета регистра, который сохраняет 6-7 байт, не так ли?
2010 года

19

Python 2.x, широтный подход = 227 183 символа

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

Принимая во внимание свободу реализации, я построил конкатенацию строк, которая содержит все слова, запрошенные для исключения ( the, and, of, to, a, i, it, in, or, is) - плюс он также исключает два печально известных «слова» sи tиз примера - и добавил бесплатно для исключения an, for, he. Я перепробовал все объединения этих слов против совокупности слов из Алисы, Библии короля Джеймса и файла Жаргона, чтобы увидеть, есть ли какие-либо слова, которые будут ошибочно исключены строкой. И вот как я закончил две строки исключения: itheandtoforinisи andithetoforinis.

PS. заимствовано из других решений, чтобы сократить код.

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

декламация

Что касается слов, которые следует игнорировать, можно подумать, что они будут взяты из списка самых употребляемых слов в английском языке. Этот список зависит от используемого текстового корпуса . По одному из самых популярных списков ( 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 ), 10 лучших слов:the be(am/are/is/was/were) to of and a in that have I

Лучшие 10 слов из текста Алисы в Стране Чудес the and to a of it she i you said
10 лучших слов из файла Jargon (v4.4.7):the a of to and in is that or for

Вопрос в том, почему or был включен в список игнорирования проблемы, где он ~ 30-й по популярности, тогда как слово that(8-е наиболее часто используемое) нет. и т. д. и т. д. Следовательно, я считаю, что список игнорирования должен предоставляться динамически (или может быть опущен).

Альтернативной идеей было бы просто пропустить первые 10 слов из результата - что на самом деле сократило бы решение (элементарно - должно отображаться только с 11 по 32 записи).


Python 2.x, точечный подход = 277 243 символа

Диаграмма, нарисованная в приведенном выше коде, упрощена (используется только один символ для столбцов). Если кто-то хочет точно воспроизвести диаграмму из описания проблемы (которая не требовалась), этот код сделает это:

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

Я беру проблему с несколько случайным выбором исключаемых 10 слов the, and, of, to, a, i, it, in, or, is, чтобы они передавались в качестве параметров командной строки, например так:
python WordFrequencyChart.py the and of to a i it in or is <"Alice's Adventures in Wonderland.txt"

Это 213 символов + 30, если мы учитываем «оригинальный» список игнорирования, переданный в командной строке = 243

PS. Второй код также выполняет «корректировку» для длин всех главных слов, поэтому ни одно из них не будет переполнено в вырожденном случае.

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

Хорошее решение до сих пор, хотя список игнорируемых слов не реализован (пока), а бары на данный момент немного зачаточны.
ChristopheD

@ChristopheD: это было там, но не было никакого "руководства пользователя". Только что добавили кучу текста
Нас Банов

Что касается вашего списка языков и решений: пожалуйста, найдите решения, которые используют расщепление \Wили использование \bв регулярном выражении, потому что они, скорее всего, не соответствуют спецификации, то есть они не будут разбиваться на цифры или _могут также не удалять стоп-слова из строк такой как the_foo_or123bar. Они могут не отображаться в тестовом тексте, но спецификация в этом случае достаточно ясна.
Джои

Удивительная работа Nas, я провел день, пытаясь оптимизировать это, и нашел только одно улучшение. Вы можете сократить его до 239 символов, удалив sys.argvхак и используя:re.findall(r'\b(?!(?:the|and|.|of|to|i[tns]|or)\b)\w+',sys.stdin.read().lower())
intgr

12

Haskell - 366 351 344 337 333 персонажа

( mainДобавлен один разрыв строки для удобства чтения, и в конце последней строки не требуется разрыв строки.)

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

Как это работает лучше всего увидеть, прочитав аргумент в interactобратном направлении:

  • map f строчные буквы алфавита, заменяет все остальное пробелами.
  • words создает список слов, отбрасывая разделяющий пробел.
  • filter (notElem words "the and of to a i it in or is")отбрасывает все записи с запрещенными словами.
  • group . sort сортирует слова и группирует идентичные слова в списки.
  • map h сопоставляет каждый список идентичных слов с кортежем вида (-frequency, word) .
  • take 22 . sort сортирует кортежи по убыванию частоты (первая запись кортежа) и сохраняет только первые 22 кортежа.
  • b сопоставляет кортежи с барами (см. ниже).
  • a добавляет первую строку подчеркивания, чтобы завершить самый верхний бар.
  • unlines объединяет все эти строки вместе с символами новой строки.

Хитрый момент - получить правильную длину стержня. Я предположил, что только длина подчеркивания учитывается по отношению к длине стержня, поэтому ||столбец будет нулевой длины. Функция bотображает c xболее x, где xсписок гистограмм. Весь список передается c, так что каждый вызов cможет вычислить коэффициент масштабирования для себя путем вызова u. Таким образом, я избегаю использования математических или рациональных чисел с плавающей точкой, чьи функции преобразования и импорта потребляют много символов.

Обратите внимание на хитрость использования -frequency. Это устраняет необходимость в с момента сортировки ( по возрастанию) будет место слова с наибольшей частотой в первую очередь. Позже в функции умножаются два значения, что отменяет отрицание.reversesort-frequencyu-frequency


Очень хорошая работа (проголосовал бы, но на сегодня не хватило голосов со всеми отличными ответами в этой теме).
ChristopheD

Это ранит мои глаза так, что даже больно думать об описании, но я многому научился на Haskell, превратив его в разборчивый код. Молодцы, сэр. :-)
Оуэн С.

Это на самом деле довольно идиоматичный Haskell, хотя и не очень эффективный. Короткие имена заставляют его выглядеть намного хуже, чем на самом деле.
Томас

@ Томас: Вы можете сказать это снова. :-)
Оуэн С.

1
На divсамом деле не может двигаться ! Попробуйте - вывод неверный. Причина в том, что выполнение divперед *теряет точность.
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)}

К сожалению, for([k,v]in z)версия от Rhino, похоже, не хочет работать в SpiderMonkey, и readFile()это немного проще, чем использование, readline()но переход на 1.8 позволяет нам использовать замыкания функций, чтобы вырезать еще несколько строк ....

Добавление пробела для удобства чтения:

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

Использование: js golf.js < input.txt

Вывод:

 _________________________________________________________________________ 
| _________________________________________________________________________ | она
| _______________________________________________________________ | ты
| ____________________________________________________________ | сказал
| ____________________________________________________ | Алиса
| ______________________________________________ | был
| ___________________________________________ | который
| ___________________________________ | так как
| ________________________________ | ей
| _____________________________ | в
| _____________________________ | с участием
| ____________________________ | s
| ____________________________ | T
| __________________________ | на
| _________________________ | все
| _______________________ | этот
| ______________________ | для
| ______________________ | было
| ______________________ | но
| _____________________ | быть
| _____________________ | не
| ___________________ | Oни
| ___________________ | так

(базовая версия - неправильно обрабатывает ширину стержня)

JavaScript (Rhino) - 405 395 387 377 368 343 304 символа

Я думаю, что моя логика сортировки отключена, но .. Я не знаю. Brainfart исправлен.

Минимизировано (злоупотребление \nинтерпретируется как ;иногда):

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

Ах, сэр. Я верю, что это твоя рукавица. Пусть ваш второй поговорит с моим.
dmckee --- котенок экс-модератора

2
Кстати, мне нравится i[tns]?немного. Очень подлый.
dmckee --- котенок экс-модератора

@dmckee - хорошо сыграно, я не думаю, что смогу побить твои 336, наслаждайся своим заслуженным голосом :)
Мэтт

Вы можете определенно превзойти 336 ... Доступно сокращение из 23 символов - .replace(/[^\w ]/g, e).split(/\s+/).map(его можно заменить .replace(/\w+/g,и использовать ту же функцию, что .mapи вы ... Также не уверен, поддерживает ли Rhino function(a,b)b.c-a.cвместо вашей функции сортировки (spidermonkey делает), но это будет бритье {return }... b.c-a.cэто лучше, чем a.c<b.cкстати ... Редактирование версии Spidermonkey внизу с этими изменениями
gnarf

Я переместил свою версию SpiderMonkey вверх, так как она соответствует ограничению ширины полосы ... Также удалось вырезать еще несколько символов в исходной версии, используя регулярное выражение с отрицательным предвкушением, чтобы отрицать слова, допускающие единственную замену (), и играл в гольф несколько ifs с отличной ?:базой для работы, хотя!
gnarf

11

PHP CLI версия (450 символов)

Это решение учитывает последнее требование, которое большинство пуристов предпочитают игнорировать. Это стоило 170 символов!

Использование: php.exe <this.php> <file.txt>

уменьшенная:

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

Человек читаемый:

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

?>

Вывод:

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

Когда есть длинное слово, столбцы настроены правильно:

|--------------------------------------------------------| 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 символов

Я думаю, что использование Counter - это вид мошенничества :) Я только что прочитал об этом около недели назад, так что это был прекрасный шанс увидеть, как это работает.

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

Распечатывает:

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

Часть кода была «заимствована» из решения AKX.


Первая строка отсутствует. И длина стержня не правильная.
Джои

в вашем коде кажется, что open('!')читает из стандартного ввода - какая версия / ОС это на? или вы должны назвать файл "!"?
Нас Банов

Назовите файл "!" :) Извините, это было довольно неясно, и я должен был упомянуть об этом.
Сэм Долан

11

Perl, 205 191 189 символов / 205 символов (полностью реализовано)

Некоторые части были вдохновлены более ранними представлениями perl / ruby, пара подобных идей была найдена независимо, другие являются оригинальными. Более короткая версия также включает в себя некоторые вещи, которые я видел / узнал из других материалов.

Оригинал:

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

Последняя версия до 191 символов:

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

Последняя версия до 189 символов:

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

Эта версия (205 символов) содержит строки со словами длиннее, чем то, что будет найдено позже.

/^(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 символов

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

Альтернативная, полная реализация, включая указанное поведение (глобальное сжатие штрихов) для патологического случая, в котором вторичное слово является одновременно популярным и достаточно длинным, чтобы его можно было объединить в более чем 80 символов ( эта реализация составляет 231 символ ):

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

В спецификации нигде не указывалось, что это должно идти в STDOUT, поэтому я использовал perl's warn () вместо print - четыре символа сохранены там. Использовал карту вместо foreach, но я чувствую, что в расколе может быть еще больше сбережений (join ()). Тем не менее, получил его до 203 - может спать на нем. По крайней мере, Perl теперь под счетчиком "shell, grep, tr, grep, sort, uniq, sort, head, perl" на данный момент;)

PS: Reddit говорит "Привет";)

Обновление: удалено join () в пользу присваивания и неявного скалярного преобразования join. До 202. Также обратите внимание, что я воспользовался необязательным правилом «игнорировать однобуквенные слова», чтобы сбрить 2 символа, поэтому имейте в виду, что подсчет частоты будет отражать это.

Обновление 2: поменялись местами назначения и неявное соединение для убийства $ /, чтобы получить файл одним залпом, используя в первую очередь <>. Тот же размер, но противнее. Поменялся местами, если (! $ Y) {} для $ y || {} &&, сохранил еще 1 символ => 201.

Обновление 3: забрал контроль над строчными буквами раньше (lc <>), переместив lc из блока карты - поменял оба регулярных выражения, чтобы больше не использовать параметр / i, поскольку он больше не нужен. Заменяемая явная условная конструкция x? Y: z для традиционного perlgolf || неявная условная конструкция - /^...$/i?1:$xndom$ } ++ для /^...$/||$x]$ } ++ Сохранено три символа! => 198, преодолел 200 барьер. Скоро спать ... возможно.

Обновление 4: лишение сна сделало меня безумным. Хорошо. Более безумный. Поняв, что для этого нужно только проанализировать нормальные текстовые файлы, я заставил его отказаться, если он достигнет нуля. Сохранены два символа. Заменили «длину» на 1 символ короче (и намного больше в гольфе) y /// c - вы меня слышите, GolfScript ?? Я иду за тобой!!! рыдать

Обновление 5: Депрессия сна заставила меня забыть о ограничении в 22 строки и последующем ограничении. Вернуться к 208 с теми, с которыми обрабатываются. Не так уж и плохо, 13 символов справиться с этим - не конец света. Поиграл с встроенным eval в регулярном выражении Perl, но не смог заставить его работать и сохранять символы ... лол. Обновлен пример, чтобы соответствовать текущему выводу.

Обновление 6: убраны ненужные скобки, защищающие (...) для, поскольку синтаксическая конфета ++ позволяет с радостью подтолкнуть ее к. Благодаря вкладу Часов. Оуэнс (напоминая мой усталый мозг), нашел решение для класса персонажей в [tns]. Вернитесь к 203.

Обновление 7: добавлена ​​вторая часть работы, полная реализация спецификаций (включая полное поведение сглаживания столбцов для вторичных длинных слов вместо усечения, которое делает большинство людей, на основе оригинальной спецификации без патологического примера)

Примеры:

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

Альтернативная реализация в примере патологического случая:

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

Вы можете сократить регулярное выражение для стоп-слов, свернувшись is|in|it|iв него i[snt]?- и тогда больше не будет разницы с необязательным правилом. (Хм, я бы никогда не подумал рассказать парню из Perl, как делать Regex: D) - единственная проблема сейчас: мне нужно посмотреть, как я могу сократить три байта из моего собственного решения, чтобы снова быть лучше Perl: - |
Джои

Хорошо, не обращайте внимания на то, что я сказал ранее. Игнорирование однобуквенных слов действительно на байт короче, чем не делать этого.
Джои

Каждый байт имеет значение;) Я подумал о том, чтобы выполнить трюк с новой строкой, но я подумал, что на самом деле это было одинаковое количество байтов, даже если было меньше печатных символов. Все еще работаю над тем, чтобы узнать, смогу ли я уменьшить это немного :)
Syntaera

Ах, хорошо, нормализация дела вернула меня к 209. Я не вижу, что еще я мог бы сократить. Хотя PowerShell может быть короче, чем Perl. ;-)
Джои

Я не вижу, где вы ограничиваете вывод верхними 22 словами, и где вы удостоверяетесь, что длинное второе слово не переносится.
Гейб

9

F #, 452 символа

Strightforward: получить последовательность aпар подсчета слов, найти лучший множитель подсчета слов на столбец k, затем распечатать результаты.

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

Пример (у меня другое количество частот, чем у вас, не знаю почему):

% 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

Оказывается, мое собственное решение было действительно немного неактивным (из-за немного другой спецификации), решения теперь соответствуют ;-)
ChristopheD

+1 за единственно правильную реализацию масштабирования баров на данный момент
Rotsor

2
(@Rotsor: Ironic, учитывая, что мое решение самое старое.)
Брайан,

Могу поспорить, что вы можете немного сократить его, объединив этапы разделения, отображения и фильтрации. Я также ожидаю, что вам не нужно так много floatс.
Гейб

Разве вложенные функции обычно не короче, чем использование оператора конвейера |>?
Джои

8

Python 2.6, 347 символов

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

Вывод:

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

1
Вы можете потерять строку, bm=(76.-len(W[0][0]))/W[0][1]так как вы используете bm только один раз (сделайте следующую строку U=lambda n:"_"*int(n*(76.-len(W[0][0]))/W[0][1]), сбрив 5 символов. Кроме того: зачем использовать 2-символьное имя переменной в игре в гольф? ;-)
ChristopheD

В последней строке пробел после печати не требуется, он сбривает один символ
ChristopheD

1
Не учитывает случай, когда второе по частоте слово очень длинное, верно?
Джои

@ChristopheD: Потому что я слишком долго смотрел на этот код. : P Хороший улов. @ Йоханнес: Это тоже можно исправить, да. Не уверен, что все другие реализации сделали это, когда я написал это тоже.
AKX

7

* sh (+ curl), частичное решение

Это неполно, но, черт возьми, вот половина частоты проблемы подсчета слов в 192 байтах:

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 (первоначально 507) персонажей

(после исправления выходного форматирования; исправления сокращений; настройки; настройки снова; удаления совершенно ненужного шага сортировки; настройки еще раз; и еще раз (к сожалению, этот нарушил форматирование); настройки еще немного; принимая вызов Мэтта, я отчаянно настраиваю более того, нашел другое место, чтобы сэкономить несколько, но дал два назад, чтобы исправить ошибку длины стержня)

Хе хе! Я на мгновение опережаю [Matt's JavaScript] [1] решение встречного вызова! ;) и [Питон AKX] [2].

Кажется, что проблема вызывает язык, который реализует нативные ассоциативные массивы, поэтому, конечно, я выбрал один с ужасно несовершенным набором операторов. В частности, вы не можете контролировать порядок, в котором awk предлагает элементы хеш-карты, поэтому я многократно сканирую всю карту, чтобы найти самый многочисленный элемент в данный момент, распечатать его и удалить из массива.

Все это ужасно неэффективно, со всеми сделанными мною играми в гольф это тоже стало довольно ужасно.

уменьшенная:

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

разрывы строк только для ясности: они не нужны и не должны учитываться.


Вывод:

$ 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

Удобочитаемый; 633 символа (первоначально 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]
    }
}

Хорошая работа, хорошо, что вы включили версию с отступом / комментарием ;-)
ChristopheD

7

Общий LISP, 670 символов

Я новичок в LISP, и это попытка использовать хэш-таблицу для подсчета (поэтому, вероятно, не самый компактный метод).

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

может быть запущен, например, с cat alice.txt | clisp -C golf.lisp.

В читабельном виде

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

Вы пытались установить пользовательский макрос для чтения, чтобы уменьшить размер ввода?
Аарон

@ Аарон, на самом деле это было не тривиально для меня, даже просто заставить это работать ... :-) для настоящей части игры в гольф, я просто использовал переменные из одной буквы, и все. В любом случае, помимо некоторой высокой детализации, присущей CL для такого масштаба проблем («concatenate» string »,« setf »или« gethash »являются убийцами ... в python они являются« + »,« = »,« [] » Я все еще чувствовал это намного хуже, чем я ожидал даже на логическом уровне. В некотором смысле у меня такое чувство, что lisp в порядке, но обычный lisp так себе, и это за пределами имен (перечитывать это очень несправедливый комментарий, так как мой опыт работы с CL близок к нулю).
6502

правда. Схема облегчит игру в гольф с единым пространством имен. вместо повсеместного добавления строки вы могли бы (letrec ((добавление строки) (b gethash)) ... (a "x" "yz") ...)
Аарон

6

С (828)

Он выглядит как запутанный код и использует glib для строки, списка и хэша. Чар считается с wc -mговорит 828 . Он не учитывает одно-символьные слова. Чтобы рассчитать максимальную длину стержня, нужно рассмотреть самое длинное слово среди всех, а не только первое 22. Это отклонение от спецификации?

Он не обрабатывает сбои и не освобождает использованную память.

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

Символы новой строки считаются символами, но вы можете удалить любую из строк, которые не являются инструкциями препроцессора. Для гольфа я бы не стал считать, что освобождение памяти - плохая практика.
Стефан Кочен

хорошо ... поместите все в строку (ожидайте макросов preproc) и дайте версы без освобождения mem (и с двумя удаленными пробелами ...) может быть сделано небольшое улучшение в "запутывании", например *v=*v*(77-lw)/m, даст 929. ... но я думаю, что это может быть хорошо, если я не найду способ сделать это намного короче)
ShinTakezou

Я думаю , что вы можете двигаться по крайней мере, int cв mainдекларации и mainнеявно int(как и любые нетипизированных аргументы, AFAIK): main(c){...}. Вы могли бы также просто написать 0вместо NULL.
Джои

выполнение этого ... конечно вызовет некоторое предупреждение с -Wallвключенным -std=c99флагом или ... но я полагаю, что это бессмысленно для код-гольфа, верно?
ShinTakezou

уф, извините за короткие промежутки времени ... Я должен перейти Without freeing memory stuff, it reaches 866 (removed some other unuseful space)на что-то другое, чтобы не думать людям, что разница с версией со свободной памятью заключается в следующем: теперь в версии без свободной памяти много больше "улучшений".
ShinTakezou

6

Perl, 185 символов

200 (немного ломаных) 199 197 195 193 187 185 знаков. Последние два перевода строки являются значительными. Соответствует спецификации.

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

Первая строка загружает количество правильных слов в %X.

Вторая строка вычисляет минимальный коэффициент масштабирования, чтобы все выходные строки были <= 80 символов.

Третья строка (содержит два символа новой строки) производит вывод.


Это не удалит стоп-слова из строк, таких как "foo_the_bar". Длина строки также слишком велика (перечитайте спецификацию: «бар + пробел + слово + пробел <= 80 символов»)
Джои

5

Ява - 886 865 756 744 742 744 752 742 714 680 символов

  • Обновления до первой версии 742 : улучшено регулярное выражение, удалены лишние параметризованные типы, удалены лишние пробелы.

  • Обновление 742> 744 символа : исправлен взлом фиксированной длины. Это зависит только от 1-го слова, а не от других слов (пока). Найдены несколько мест для сокращения кода ( \\sв регулярном выражении заменены на и ArrayListзаменены на Vector). Сейчас я ищу короткий способ удалить зависимость Commons IO и чтение из stdin.

  • Обновление 744> 752 символа : я убрал зависимость от общего достояния. Теперь он читает со стандартного ввода. Вставьте текст в стандартный ввод и нажмите, Ctrl+Zчтобы получить результат.

  • Обновление 752> 742 символа : я удалил publicпробел, сделал имя класса 1 символ вместо 2, и теперь он игнорирует однобуквенные слова.

  • Обновление 742> 714 символов : Обновленные в соответствии с комментариями Карла: удалены избыточные присваивания (742> 730), заменены m.containsKey(k)на m.get(k)!=null(730> 728), введенный substringing линии (728> 714).

  • Обновление 714> 680 символов : обновлено в соответствии с комментариями Rotsor: улучшен расчет размера стержня для удаления ненужного заброса и улучшено split()удаление ненужного 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);}}

Более читаемая версия:

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

Вывод:

 _________________________________________________________________________
| _________________________________________________________________________ | она
| _______________________________________________________________ | ты
| ____________________________________________________________ | сказал
| _____________________________________________________ | Алиса
| _______________________________________________ | был
| ___________________________________________ | который
| ____________________________________ | так как
| ________________________________ | ей
| _____________________________ | с участием
| _____________________________ | в
| __________________________ | на
| __________________________ | все
| _______________________ | этот
| _______________________ | для
| _______________________ | было
| _______________________ | но
| ______________________ | быть
| _____________________ | не
| ____________________ | Oни
| ____________________ | так
| ___________________ | очень
| __________________ | какие

Это довольно отстойно, что Java не имеет String#join()и закрывает (пока).

Редактировать от Rotsor:

Я сделал несколько изменений в вашем решении:

  • Замененный список со строкой []
  • Повторно использовал аргумент 'args' вместо объявления моего собственного массива String. Также использовал его в качестве аргумента .ToArray ()
  • Заменен StringBuffer на String (да, да, ужасная производительность)
  • Заменяемая сортировка Java заменой выбора с ранней остановкой (должны быть найдены только первые 22 элемента)
  • Объединение некоторого объявления int в одно утверждение
  • Реализован не читерский алгоритм, находящий наиболее ограничивающую строку вывода. Реализовано это без ФП.
  • Исправлена ​​проблема сбоя программы, когда в тексте было менее 22 разных слов
  • Реализован новый алгоритм чтения ввода, который быстр и всего на 9 символов длиннее медленного.

Сокращенный код длиной 688 711 684 символа:

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

Быстрая версия ( 720 693 символа)

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

Более читаемая версия:

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

Версия без улучшений поведения - 615 символов:

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

Не могли бы вы просто использовать полное имя IOUtilsвместо того, чтобы импортировать его? Насколько я понимаю, вы используете его только один раз в любом случае.
Джои

5
Вы как будто обмануты, предполагая, что самая длинная полоса будет ровно 75 символов. Вы должны убедиться, что ни одна строка + слово не длиннее 80 символов.
Гейб

Вы пропускаете пробел после слова. ;)
2010 г.,

Когда я урезал свой ответ , я надеялся, что побью представление BalusC. У меня еще осталось 200 символов, тьфу! Интересно, как долго это будет без предположения Commons IO & 75 char?
Джонатон Фауст

1
Похоже, вы могли бы побрить некоторых персонажей, создав bString вместо StringBuffer. Однако я не хочу думать о том, каким будет представление (особенно если вы добавляете по одному персонажу за раз).
Майкл Майерс

4

Scala 2.8, 311 314 320 330 332 336 341 375 символов

в том числе корректировка длинных слов. Идеи заимствованы из других решений.

Теперь как скрипт ( 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)

Бежать с

scala -howtorun:script a.scala alice.txt

Кстати, редактирование от 314 до 311 символов фактически удаляет только 1 символ. Кто-то раньше ошибся в подсчете (Windows CR?).


4

Clojure 282 строгий

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

Несколько более разборчиво:

(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

Скала, 368 символов

Во-первых, разборчивая версия в 592 символа:

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

Вывод консоли выглядит следующим образом:

$ 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

Мы можем сделать несколько агрессивных минификаций и сократить их до 415 символов:

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

Сеанс консоли выглядит так:

$ 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

Я уверен, что эксперт Scala мог бы сделать еще лучше.

Обновление: в комментариях Томас дал еще более короткую версию, на 368 символов:

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

Разборчиво, на 375 символов:

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 символа: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}}
Томас Юнг

Конечно, всегда удобно для понимания! Ницца!
pr1001

3

Ява - 896 символов

931 символ

1233 символа сделаны нечитаемыми

Символы 1977 года "без сжатия"


Обновление: я агрессивно уменьшил количество персонажей. Опускает однобуквенные слова в обновленной спецификации.

Я так завидую C # и 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)+" ");}}}

"Удобочитаемый":

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

Выход Алисы:

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

Выход Дон Кихота (также из Гутенберга):

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

8
Полностью карп, разве нет способа сделать его короче на Java? Я надеюсь, что вам, ребята, платят по количеству персонажей, а не по функциональности :-)
Нас Банов
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.