Ответ 1
LabVIEW 51 узел, 5 структур, 10 диаграмм
Преподавание слона, чтобы танцевать, никогда не бывает красивым. Я, ах, пропущу количество символов.
Программа перемещается слева направо:
Создайте диаграмму 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
) и создайте нам word frequency chart
со следующими характеристиками:
width
представляет количество вхождений (частоты) слова (пропорционально). Добавьте одно место и напечатайте слово.bar
+ [space]
+ word
+ [space]
должны быть всегда <= 80
символов (убедитесь, что вы учитываете возможные разница между строками и длиной слова: например: второе наиболее распространенное слово может быть намного длиннее, чем первое, но не так сильно различающееся по частоте). Увеличьте ширину штриха в пределах этих ограничений и соответствующим образом нарисуйте полосы (в соответствии с представленными частотами).Пример:
Текст примера можно найти здесь (Alice Adventures in Wonderland, Льюис Кэрролл).
В этом конкретном тексте будет приведена следующая диаграмма:
_________________________________________________________________________ |_________________________________________________________________________| she |_______________________________________________________________| you |____________________________________________________________| said |____________________________________________________| alice |______________________________________________| was |__________________________________________| that |___________________________________| as |_______________________________| her |____________________________| with |____________________________| at |___________________________| s |___________________________| t |_________________________| on |_________________________| all |______________________| this |______________________| for |______________________| had |_____________________| but |____________________| be |____________________| not |___________________| they |__________________| so
Для вашей информации: это частоты, на которых построена вышеприведенная диаграмма:
[('she', 553), ('you', 481), ('said', 462), ('alice', 403), ('was', 358), ('that ', 330), ('as', 274), ('her', 248), ('with', 227), ('at', 227), ('s', 219), ('t' , 218), ('on', 204), ('all', 200), ('this', 181), ('for', 179), ('had', 178), (' but', 175), ('be', 167), ('not', 166), ('they', 155), ('so', 152)]
Второй пример (чтобы проверить, была ли реализована полная спецификация):
Замените каждое событие you
в связанном файле Alice in Wonderland с помощью superlongstringstring
:
________________________________________________________________ |________________________________________________________________| she |_______________________________________________________| superlongstringstring |_____________________________________________________| said |______________________________________________| alice |________________________________________| was |_____________________________________| that |______________________________| as |___________________________| her |_________________________| with |_________________________| at |________________________| s |________________________| t |______________________| on |_____________________| all |___________________| this |___________________| for |___________________| had |__________________| but |_________________| be |_________________| not |________________| they |________________| so
Победитель:
Кратчайшее решение (по количеству символов, по языку). Получайте удовольствие!
Изменить: таблица, обобщающая результаты до сих пор (2012-02-15) (первоначально добавленный пользователем Нас Банов):
Language Relaxed Strict ========= ======= ====== GolfScript 130 143 Perl 185 Windows PowerShell 148 199 Mathematica 199 Ruby 185 205 Unix Toolchain 194 228 Python 183 243 Clojure 282 Scala 311 Haskell 333 Awk 336 R 298 Javascript 304 354 Groovy 321 Matlab 404 C# 422 Smalltalk 386 PHP 450 F# 452 TSQL 483 507
Цифры представляют длину кратчайшего решения на определенном языке. "Строгий" относится к решению, полностью реализующему спецификацию (рисует строки |____|
, закрывает первый балл сверху линией ____
, учитывает возможность длинных слов с высокой частотой и т.д.). "Relaxed" означает, что некоторые свободы были сокращены до решения.
В комплект включены только решения длиной менее 500 символов. Список языков сортируется по длине "строгого" решения. "Unix Toolchain" используется для обозначения различных решений, которые используют традиционную оболочку * nix плюс набор инструментов (например, grep, tr, sort, uniq, head, perl, awk).
Преподавание слона, чтобы танцевать, никогда не бывает красивым. Я, ах, пропущу количество символов.
Программа перемещается слева направо:
(в значительной степени основанный на других решениях 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.
Изменить: Заменены точки с запятой разрывами строк для "удобочитаемости".: P
Отредактируйте 2: Shtééf указал, что я забыл конечное пространство - исправил это.
Правка 3: снова удалено конечное пространство;)
Медленно - 3 минуты для текста примера (130)
{32|.123%97<[email protected]}%]''*n%"oftoitinorisa"2/-"theandi"3/-$([email protected]{.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
[email protected] #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
([email protected] #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<[email protected]}%]''*n%"oftoitinorisa"2/-"theandi"3/-$([email protected]{.3$>1{;)}if}/]2/{~~\;}$22<..0=1=:^;{[email protected],-^*\/}%$0=:1'_':0*' '\@{"
|"\~1*^/0*'| '@}/
Менее медленный - полминуты. (162)
'"'/' ':S*n/S*'"#{%q
'\+"
.downcase.tr('^a-z','
')}\""+~n%"oftoitinorisa"2/-"theandi"3/-$([email protected]{.3$>1{;)}if}/]2/{~~\;}$22<.0=~:2;,76\-:1'_':0*S\@{"
|"\~1*2/0*'| '@}/
Выход отображается в журналах изменений.
~ % 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)[email protected];$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
~ % # usage:
~ % sh wfg < 11.txt
hm, как видно выше: sort -nr
→ sort -n
, а затем head
→ tail
= > 208:)
update2: erm, конечно, это глупо, так как тогда оно будет отменено. Итак, 209.
update3: оптимизировано исключение regexp → 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)[email protected];$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
для удовольствия, здесь версия perl-only (намного быстрее):
~ % 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)."| $_"[email protected]'
~ % # usage:
~ % sh pgolf < 11.txt
Спасибо Gabe за полезные советы, чтобы уменьшить количество символов.
NB: добавлены разрывы строк, чтобы избежать полос прокрутки, требуется только последний разрыв строки.
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 @[email protected]+'
|'+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 guaranteed but it works on my machine :-) */
SELECT @F=MIN(($76-LEN(W))/-C),
@ =' ' +REPLICATE('_',-MIN(C)*@F)+' '
FROM #
SELECT @[email protected]+'
|'+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
Улучшение 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
Изменить: поставить 'puts' обратно, нужно быть там, чтобы избежать наличия кавычек в выводе.
Edit2: Измененный файл- > IO
Edit3: удален /i
Edit4: Удаленные круглые скобки вокруг (f * 1.0), пересчитанные
Edit5: используйте добавление строк для первой строки; разверните s
на месте.
Edit6: Сделано m float, удалено 1.0. EDIT: не работает, изменяется длина. EDIT: не хуже, чем раньше
Edit7: используйте STDIN.read
.
Посмотрите, мама... нет варов, нет рук, нет головы
Изменить 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)
Выход
alt text http://i49.tinypic.com/2n8mrer.jpg
Mathematica не очень подходит для игры в гольф, и это происходит только из-за длинных описательных имен функций. Такие функции, как "RegularExpression []" или "StringSplit []", просто заставляют меня рыдать: (.
Закон Zipf предсказывает, что для текста на естественном языке Журнал (ранг) vs Журнал (вхождения) Участок следует за линейной.
Закон используется при разработке алгоритмов криптографии и сжатия данных. (Но это НЕ "Z" в алгоритме LZW).
В нашем тексте мы можем протестировать его с помощью следующих
f[x_, y_] := Flatten[Take[x, All, y]];
ListLogLogPlot[
Reverse[f[{##}, -1]],
AxesLabel -> {"Log (Rank)", "Log Counter"},
PlotLabel -> "Testing Zipf Law"]
& @@
Take[
SortBy[
Tally[
StringSplit[ToLowerCase[b], RegularExpression["\\W+"]]
],
Last],
-1000]
Результат (довольно хорошо линейный)
alt text http://i46.tinypic.com/33fcmdk.jpg
Рефакторинг регулярного выражения (больше нет функции выбора)
Отбрасывание 1 char слов
Более эффективное определение функции "f"
f = Flatten[Take[#1, All, #2]]&;
BarChart[
f[{##}, -1],
BarOrigin -> Left,
ChartLabels -> Placed[f[{##}, 1], After],
Axes -> None]
& @@
Take[
SortBy[
Tally[
StringSplit[ToLowerCase[Import[i]],
RegularExpression["(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"]]
],
Last],
-22]
BarChart[#2, BarOrigin->Left, ChartLabels->Placed[#1, After], Axes->None]&@@
[email protected][SortBy[[email protected][[email protected]@i,
[email protected]"(\\W|\\b(.|the|and|of|to|i[tns]|or)\\b)+"],Last], -22]
f
аргументами Transpose
и Slot
(#1
/#2
).[email protected]
вместо f[x]
, где это возможно)Не так коротка, но теперь, наверное, правильно! Обратите внимание, что предыдущая версия не отображала первую строку столбцов, не правильно масштабировала бары, загружала файл, а не получала его из stdin, и не включала в себя всю требуемую детальность С#. Вы могли бы легко побрить много ударов, если бы С# не требовалось столько лишнего дерьма. Возможно, 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 символа с lendivisor inlined (что делает его в 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));}}
(Обновлен снова, чтобы обыграть версию Ruby с более грязными трюками для гольфа, заменив split/[^a-z/,lc
на lc=~/[a-z]+/g
и устранив проверку пустой строки в другом месте. Они были вдохновлены версией Ruby, поэтому кредит, из-за.)
Обновление: теперь с Perl 5.10! Замените print
на say
и используйте ~~
, чтобы избежать map
. Это нужно вызвать в командной строке как perl -E '<one-liner>' alice.txt
. Поскольку весь script находится на одной строке, запись его как однострочного слоя не должна представлять никаких трудностей:).
@s=qw/the and of to a i it in or is/;$c{$_}++foreach grep{!([email protected])}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)."| $_ "[email protected][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;
$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. Надеюсь, что в моих тестовых случаях обнаружены наиболее распространенные ошибки (длина бара, проблемы с совпадением регулярных выражений и несколькими другими))
Предположения:
Расслабленная версия (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 символов.
Более старую версию можно найти здесь.
update 1: Ура! Это связь с JS Bangs . Не могу придумать способ срубить больше:)
update 2: сыграл грязный трюк в гольф. Изменено each
до map
, чтобы сохранить 1 символ:)
update 3: Изменено File.read
до IO.read
+2. Array.group_by
был не очень плодотворным, его заменили на reduce
+6. Нечувствительность к регистру не нужна после нижнего корпуса с downcase
в регулярном выражении +1. Сортировка в порядке убывания легко выполняется путем отрицания значения +6. Общая экономия +15
обновить 4: [0]
, а не .first
, +3. (@Shtééf)
update 5: Развернуть переменную l
на месте, +1. Разверните переменную s
на месте, +2. (@Shtééf)
update 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} "}
update 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
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-332-ю записи).
График, нарисованный в приведенном выше коде, упрощается (используя только один символ для баров). Если вы хотите точно воспроизвести диаграмму из описания проблемы (что не требовалось), этот код сделает это:
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 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
(Один разрыв строки в 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
. Это устраняет необходимость reverse
sort
, так как сортировка (восходящая) -frequency
сначала помещает слова с наибольшей частотой. Позже, в функции u
, умножаются два значения -frequency
, которые отменяют отрицание.
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
Вывод:
_________________________________________________________________________ |_________________________________________________________________________| she |_______________________________________________________________| you |____________________________________________________________| said |____________________________________________________| alice |______________________________________________| was |___________________________________________| that |___________________________________| as |________________________________| her |_____________________________| at |_____________________________| with |____________________________| s |____________________________| t |__________________________| on |_________________________| all |_______________________| this |______________________| for |______________________| had |______________________| but |_____________________| be |_____________________| not |___________________| they |___________________| so
(базовая версия - неправильно обрабатывает ширину столбца)
Я думаю, что моя логика сортировки отключена, но.. я duno. Brainfart исправлена.
Minified (злоупотребление \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)}
Некоторые части были вдохновлены более ранними представлениями 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 [email protected][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 char) учитываются строки со словами дольше, чем то, что будет найдено позже.
/^(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]
Я предполагаю, что использование 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.
Это решение учитывает последнее требование, которое большинство пуристов выбрали для удобства. Это стоило 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
$/=\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 warn() вместо print - там было сохранено четыре символа. Используемая карта вместо foreach, но я чувствую, что все еще можно сэкономить на сплите (join()). Тем не менее, добрался до 203 года - мог бы спать на нем. По крайней мере, Perl теперь находится под заголовками "shell, grep, tr, grep, sort, uniq, sort, head, perl" char;)
PS: Reddit говорит "Привет";)
Обновление: Удалено join() в пользу назначения и неявное скалярное преобразование. До 202. Также обратите внимание, что я воспользовался необязательным правилом "игнорировать однобуквенные слова", чтобы скрыть два символа, поэтому помните, что частота будет отражать это.
Обновление 2: Помененное назначение и неявное объединение для убийства $/, чтобы получить файл в одном gulp, используя < > в первую очередь. Такой же размер, но более неприятный. Выровнено, если (! $Y) {} для $y || {} & &, сохранено еще 1 char = > 201.
Обновление 3: Взял управление ранним ранжированием (lc < > ), перемещая lc из блока карты. Поменял оба регулярных выражения, чтобы больше не использовать параметр /i, поскольку он больше не нужен. Обменивается явным условным x? Y: z конструкцией для традиционного перлгольфа || неявная условная конструкция -/^...$/i?1:$x{$}++ для /^...$/||$x{$}++ Сохранено три символа! = > 198, сломал барьер 200. Может скоро спать... возможно.
Обновление 4: лишение сна сделало меня сумасшедшим. Что ж. Более сумасшедший. Полагая, что это только должно разбирать нормальные счастливые текстовые файлы, я заставил его отказаться, если он ударил нуль. Сохранено два символа. Заменена "длина" с 1- char короче (и гораздо больше гольфистов) y///c - вы меня слышите, GolfScript?? Я иду за тобой!!! рыдать
Обновление 5: Sleep dep заставил меня забыть о пределе 22row и последующем лимитировании. Резервное копирование до 208 с обработанными. Не так уж плохо, 13 символов для его обработки - это не конец света. Играется с регулярным выражением perl regex inline eval, но у него проблемы с его работой и сохранением символов... lol. Обновлен пример для соответствия текущему результату.
Обновление 6: Удалены ненужные фигурные скобки, защищающие (...), поскольку синтаксическая конфета ++ позволяет с уверенностью отталкивать ее. Благодаря вкладу Chas. Оуэнс (напоминая мой усталый мозг), получил решение класса я [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
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
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
(после исправления выходного форматирования, исправления сундуков, настройки, повторной настройки, удаления полностью ненужного шага сортировки, повторной настройки, и снова (если это сломало форматирование), еще немного подкорректируйте, Я отчаянно подстроил так, нашел другое место, чтобы сохранить несколько, но дал два назад, чтобы исправить ошибку длины бара)
Хе-хе! Я на мгновение опередил решение [Matt JavaScript] [1] решение counter!;) и [AKX python] [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]
}
}
Это неполное, но, черт возьми, здесь слово-частота подсчитывает половину проблемы в 192 байтах:
curl -s http://www.gutenberg.org/files/11/11.txt|sed -e '[email protected][^a-z]@\[email protected]'|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
Я новичок 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)))))
Он выглядит как обфусканный код и использует glib для строки, списка и хэша. Char count с wc -m
говорит 828. Он не учитывает одиночные слова char. Чтобы вычислить максимальную длину бара, он рассматривает самое длинное слово среди всех, а не только первое 22. Является ли это отклонением от spec?
Он не обрабатывает сбои и не освобождает используемую память.
#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);}
200 (слегка сломан)
<Удаp > 199удаp > <Удаp > 197удаp > <Удаp > 195удаp > <Удаp > 193удаp > <Удаp > 187удаp > 185 символов. Последние две строки новой строки значительны. Соответствует спецификации.
map$X{+lc}+=!/^(.|the|and|to|i[nst]|o[rf])$/i,/[a-z]+/gfor<>;
$n=$n>($:=$X{$_}/(76-y+++c))?$n:$:[email protected]=(sort{$X{$b}-$X{$a}}%X)[0..21];
die map{$U='_'x($X{$_}/$n);" $U
"x!$z++,"|$U| $_
"}@w
Первая строка загружает количество допустимых слов в %X
.
Вторая строка вычисляет минимальный коэффициент масштабирования, так что все выходные строки будут <= 80 символов.
Третья строка (содержит два символа новой строки) выводит результат.
Обновления до первого 742: улучшено регулярное выражение, удалены избыточные параметризованные типы, удалены лишние пробелы.
Обновление 742 > 744 символов: исправлен взлом фиксированной длины. Это зависит только от 1-го слова, а не от других слов (пока). Нашел несколько мест, чтобы сократить код (\\s
в регулярном выражении заменен на и
ArrayList
заменен на Vector
). Я сейчас ищу короткий способ удалить зависимость IO от Commons и чтение из stdin.
Обновление 744 > 752 символов. Я удалил зависимость от сообщества. Теперь он читается из stdin. Вставьте текст в stdin и нажмите Ctrl+Z
, чтобы получить результат.
Обновление 752 > 742 символов. Я удалил public
и пробел, сделав имя класса 1 char вместо 2, и теперь он игнорирует однобуквенные слова.
Обновление 742 > 714 символов: обновлено в соответствии с комментариями Carl: удаленное резервирование (742 > 730), заменено m.containsKey(k)
на m.get(k)!=null
(730 > 728), введено подстрока линии (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);
}
}
Вывод:
_________________________________________________________________________ |_________________________________________________________________________| she |_______________________________________________________________| you |____________________________________________________________| said |_____________________________________________________| alice |_______________________________________________| was |___________________________________________| that |____________________________________| as |________________________________| her |_____________________________| with |_____________________________| at |__________________________| on |__________________________| all |_______________________| this |_______________________| for |_______________________| had |_______________________| but |______________________| be |_____________________| not |____________________| they |____________________| so |___________________| very |__________________| what
Это довольно отстой, что Java не имеет String#join()
и закрывает (пока).
Редактировать Rotsor:
Я сделал несколько изменений в вашем решении:
Конденсированный код 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);}}}
Во-первых, четкая версия с 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)
}
}
включая длинную настройку слова. Идеи, заимствованные из других решений.
Теперь как script (a.scala
):
val t="\\w+\\b(?<!\\bthe|and|of|to|a|i[tns]?|or)".r.findAllIn(io.Source.fromFile(argv(0)).mkString.toLowerCase).toSeq.groupBy(w=>w).mapValues(_.size).toSeq.sortBy(-_._2)take 22
def b(p:Int)="_"*(p*(for((w,c)<-t)yield(76.0-w.size)/c).min).toInt
println(" "+b(t(0)._2))
for(p<-t)printf("|%s| %s \n",b(p._2),p._1)
Запустить с помощью
scala -howtorun:script a.scala alice.txt
BTW, редактирование с 314 до 311 символов фактически удаляет только 1 символ. Кто-то неправильно подсчитал (Windows CRs?).
(let[[[_ m]:as s](->>(slurp *in*).toLowerCase(re-seq #"\w+\b(?<!\bthe|and|of|to|a|i[tns]?|or)")frequencies(sort-by val >)(take 22))[b](sort(map #(/(- 76(count(key %)))(val %))s))p #(do(print %1)(dotimes[_(* b %2)](print \_))(apply println %&))](p " " m)(doseq[[k v]s](p \| v \| k)))
Несколько более разборчиво:
(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)))
Обновление: я агрессивно уменьшил количество символов. Опускает однобуквенные слова по обновленной спецификации.
Я очень завидую С# и 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