建立给定文本中最常用单词的ASCII图[关闭]


156

挑战:

建立给定文本中最常用单词的ASCII图。

规则:

  • 仅接受a-zA-Z(字母字符)作为单词的一部分。
  • 忽略大小写(出于我们的目的She= = she)。
  • 忽略以下单词(我知道很蛮横): the, and, of, to, a, i, it, in, or, is
  • 澄清:考虑don't:在a-z和和A-Zdont)中,这将被视为2个不同的“单词” 。

  • 可选(为时已晚将正式改变规格现在),你可以选择丢弃所有的单字母“词”(这可能做出的忽略列表也缩短)。

解析给定text的文件(读取通过命令行参数指定的文件或通过管道输入;假定us-ascii),并为我们构建一个word frequency chart具有以下特征的文件:

  • 显示22个最常用单词的图表(也请参见下面的示例)(按降序排列)。
  • 条形图width(按比例)代表单词的出现次数(频率)。附加一个空格并打印单词。
  • 确保这些小节(加上空格-单词-空格)始终适合bar+ [space]+ word+ [space]始终应为<= 80字符(请确保您考虑到可能不同的小节和单词长度:例如:第二个最常见的单词可能要长得多,然后第一个频率差异不大)。在这些限制范围内最大化条形宽度并适当地缩放条形(根据它们表示的频率)。

一个例子:

可以在此处找到示例文本(Lewis Carroll的《爱丽丝梦游仙境》)。

此特定文本将产生以下图表:

 _________________________________________________________________________
| _________________________________________________________________________ | 她
| _______________________________________________________________ | 您
| ____________________________________________________________ | 说过
| ____________________________________________________ | 爱丽丝
| ______________________________________________ | 原为
| __________________________________________ | 那
| ___________________________________ | 如
| _______________________________ || 她的
| ____________________________ | 与
| ____________________________ | 在
| ___________________________ | s
| ___________________________ | Ť
| _________________________ | 上
| _________________________ | 所有
| ______________________ | 这个
| ______________________ | 对于
| ______________________ | 有
| _____________________ | 但
| ____________________ | 是
| ____________________ | 不
| ___________________ | 他们
| __________________ | 所以


供您参考:以上图表基于以下频率:

[('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),('
但是”,175),(“ be”,167),(“非”,166),(“他们”,155),(“ so”,152)]

第二个示例(检查您是否实施了完整的规范):you链接的“ 爱丽丝梦游仙境”文件中所有出现的内容替换为superlongstringstring

 ________________________________________________________________
| ________________________________________________________________ | 她
| _______________________________________________________ | 超长弦
| _____________________________________________________ | 说过
| ______________________________________________ | 爱丽丝
| ________________________________________ | 原为
| _____________________________________ | 那
| ______________________________ | 如
| ___________________________ | 她的
| _________________________ | 与
| _________________________ | 在
| ________________________ | s
| ________________________ | Ť
| ______________________ | 上
| _____________________ | 所有
| ___________________ | 这个
| ___________________ | 对于
| ___________________ | 有
| __________________ | 但
| _________________ | 是
| _________________ | 不
| ________________ | 他们
| ________________ | 所以

获胜者,冠军:

最短的解决方案(按字符数,每种语言)。玩得开心!


编辑:表总结了到目前为止的结果(2012-02-15)(最初由用户Nas Banov添加):

语言宽松严格
======================
高尔夫脚本130143
Perl 185
Windows PowerShell 148199
Mathematica 199
红宝石185205
Unix工具链194228
Python 183243
Clojure 282
斯卡拉311
哈斯克尔333
AWK 336
R 298
Javascript 304354
Groovy 321
Matlab 404
C#422
Smalltalk 386
PHP 450
F#452
TSQL 483507

数字代表特定语言中最短解决方案的长度。“严格”是指完全实施规范的解决方案(画出|____|条形,用____线条将顶部的第一个条形闭合,考虑长单词出现频率高的可能性等)。“放松”是指采取一些自由来缩短解决时间。

仅包含少于500个字符的解决方案。语言列表按“严格”解决方案的长度排序。“ Unix工具链”用于表示使用传统* nix shell 以及各种工具(例如grep,tr,sort,uniq,head,perl,awk)混合使用的各种解决方案。


4
好吧,如果第二个最常见的单词更长,那么'longest bar'+ word = 80可能不适合80列。我在寻找“最大约束”。
Brian

1
我们是否将套管归一化?“她” =“她”?
Brian

2
在执行时间和内存使用方面,使IMO发挥作用似乎比字符计数更具挑战性。
Frank Farmer 2010年

81
我很高兴看到我最喜欢的单词st被代表。
indiv 2010年

8
@indiv,@Nas Banov-愚蠢的过于简单的令牌生成器将“ did n't”读为{didn,t},将“ she's”读为{she,s} :)
hobbs

Answers:


123

LabVIEW 51个节点,5个结构,10个图表

教大象踢踏舞从来都不是一件漂亮的事。我会啊,跳过字符数。

labVIEW代码

结果

程序从左向右流动:

labVIEW代码说明


10
这不值得

4
LabVIEW在硬件控制和测量领域非常满意,但对于字符串操作确实非常糟糕。
乔Z

19
我见过的最好的高尔夫答案代码。+1跳出框框思考!
布莱尔·霍洛威

1
必须为我们计算元素...每个必须拖到屏幕上的框和小部件的数量。
dmckee ---前主持人小猫,2010年

1
是否可以将链接添加到这些图表的更大版本?
Svish 2010年

42

Ruby 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中有效。

编辑:用换行符代替分号,以提高“可读性”。:P

编辑2:Shtééf指出我忘记了尾随空格-对此进行了修复。

编辑3:再次删除尾随空格;)


每个字之后都缺少尾随空格。
斯蒂芬Kochen

Aww笋,无视。看起来高尔夫刚刚更新,不再需要尾随空间。:)
斯蒂芬Kochen

似乎不适合第二或更高位置的“ superlongstringstring”吗?(请参阅问题描述)
Nas Banov

2
看起来确实可以维护。
僵尸

39

GolfScript,177 175 173 167 164 163 144 131 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

壳,grep,tr,grep,排序,uniq,排序,头,perl

~ % wc -c wfg
209 wfg
~ % cat wfg
egrep -oi \\b[a-z]+|tr A-Z a-z|egrep -wv 'the|and|of|to|a|i|it|in|or|is'|sort|uniq -c|sort -nr|head -22|perl -lape'($f,$w)=@F;$.>1or($q,$x)=($f,76-length$w);$b="_"x($f/$q*$x);$_="|$b| $w ";$.>1or$_=" $b\n$_"'
~ % # usage:
~ % sh wfg < 11.txt

hm,如上所示:sort -nr-> sort -n然后head-> tail=> 208 :)
update2:erm,当然上面的内容很愚蠢,因为它将被逆转。因此,
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 827 820 783 683 647 644 630字符

感谢Gabe提供了一些有用的建议,以减少字符数。

注意:添加了换行符以避免滚动条,仅需要最后一个换行符。

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中完成的,并引用美国队的话-“您有球。我喜欢球。”

我自由地将一些空格转换为换行符,以使其更具可读性。希望我没有把事情搞砸。我还缩小了一点。
加布

3
该代码对我大叫!:O
Joey

1
保存的一种好方法是更改0.000为just 0,然后使用-C代替1.0/C。而制作FLOATREAL会节省一举多得。不过,最大的事情是看起来您有很多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

编辑:将“ puts”放回去,需要放在那里以避免在输出中包含引号。
编辑2:更改文件-> IO
编辑3:删除/ i
编辑4:删除括号(f * 1.0),重新
计数编辑5:第一行使用字符串添加;s就地扩展。
Edit6:使m浮动,删除1.0。编辑:无效,更改长度。编辑:不差于
Edit7:使用STDIN.read


+1-喜欢排序部分,非常聪明:)
Anurag

嘿,与一开始就提出大量优化措施相比,进行小的优化。:)
archgoon

真好!添加了我也在Anurag版本中进行的两项更改。刮掉另一个4。
StéphanKochen

解决方案与原始输出有所不同,我将尝试找出发生了什么。
archgoon”,2010年

1
这有一个更短的变体。
archgoon” 2010年

28

数学(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 []”之类的功能只会让我抽泣:(。

Zipf定律测试

齐普夫定律预测的自然语言文本的日志(等级) VS 日志(事件)地块遵循线性关系。

该法则用于开发加密和数据压缩算法。(但不是LZW算法中的“ Z”)。

在我们的文字中,我们可以使用以下内容对其进行测试

 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个字符)

重构正则表达式(不再使用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]
  • fTransposeSlot#1/ #2)参数替换。
  • 我们不需要臭气的括号(尽可能使用f@x代替f[x]


9
您认为“ RegularExpression”不好吗?我在C#版本中键入“ System.Text.RegularExpressions.Regex.Split”时哭了,直到看到Objective-C代码:“ stringWithContentsOfFile”,“ enumerateSubstringsInRange”,“ NSStringEnumerationByWords”,“ sortedArrayUsingComparator”等等。
加布

2
@Gabe谢谢...我现在感觉好多了。在西班牙语中,我们说“ mal de muchos,consuelo de tontos” ..之类的东西“很多麻烦,傻瓜都松了口气”:D
belisarius博士10年

1
|i|,因为你已经在你的正则表达式的冗余.|
加布

1
我喜欢那个西班牙谚语。我能用英语想到的最接近的东西是“痛苦的爱伴”。这是我的翻译尝试:“这是一个傻瓜,当遭受苦难时,他会以慰藉来思考处于相同情况的其他人。” 顺便说一下,Mathematica实现方面的惊人工作。
dreeves 2010年

@dreeves愚蠢轻易超越语言障碍...很高兴看到您喜欢我的Mathematica小程序,我才刚刚开始学习语言
belisarius博士10年

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个字符,以lendivisor内联(使其变慢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
从Matt的答案中窃取简短的URL。
indiv 2010年

2
规范说该文件必须通过管道传递或作为args传递。如果假设args [0]包含本地文件名,则可以通过使用args [0]而不是(new WebClient())。DownloadString(@“ gutenberg.org/files/11/11)来大大缩短它。 txt“)->这样可以节省大约70个字符
thorkia

1
这是一个用args 0代替WebClient调用,对StreamReader的调用并删除一些额外空间的版本。总字符数= 413 var a = Regex.Replace((new StreamReader(args [0]))。ReadToEnd(),“ [^ a-zA-Z]”,“”).ToLower()。Split('' ).Where(x =>!(new [] {“ the”,“ and”,“ of”,“ to”,“ a”,“ i”,“ it”,“ in”,“ or”,“是“})。包含(x))。GroupBy(x => x)。选择(g => new {w = g.Key,c = g.Count()})。OrderByDescending(x => xc)。跳过(1).Take(22).ToList(); var m = a.OrderByDescending(x => xc).First(); a.ForEach(x => Console.WriteLine(“ |” + new String(' _',xc *(80-mwLength-4)/ mc)+“ |” + xw));
thorkia

没有“使用”的“新StreamReader”很脏。File.ReadAllText(args [0])或Console.In.ReadToEnd()更好。在后一种情况下,您甚至可以从Main()中删除参数。:)
Rotsor 2010年

25

Perl中,237 229 209个字符

(再次更新以用更肮脏的高尔夫技巧击败Ruby版本,将其替换split/[^a-z/,lclc=~/[a-z]+/g,并取消了在其他地方检查空字符串的操作。这些灵感来自Ruby版本,因此应归功于此。)

更新:现在有了Perl 5.10!替换printsay,并~~避免使用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。但是,我还没有那样写上面的示例,因为那样“更清晰”(ha!)。


这是一个最正确的,但不够简短的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ձոգչ2010年

4
这不包括第二个单词比第一个单词长得多的情况,对吗?
乔伊

1
两个foreach都可以写为for。减少了8个字符。然后您有了grep{!($_~~@s)}map{lc=~/[a-z]+/g}<>,我相信可以将它写成 grep{!(/$_/i~~@s)}<>=~/[a-z]+/g再下降4个。替换为" "$"您就会再落后1个...
Zaid 2010年

sort{$c{$b}-$c{$a}}...再省两个。您也可以只传递%c而不是传递keys %csort函数,然后再保存四个。
暴民

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存储库中找到。我希望我的测试用例能够捕获最常见的错误(条长,正则表达式匹配问题以及其他一些错误))

假设:

  • 美国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:根据我的经验(无政府状态高尔夫,一些Project Euler任务以及一些其他任务只是为了好玩),PowerShell通常只比Ruby稍差一点,并且经常与Perl和Python结合在一起或优于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,216218221224236237个字符

更新1:万岁!这与JS Bangs解决方案有关。想不到一种方法来减少更多:)

更新2:打了一个肮脏的高尔夫技巧。更改eachmap保存1个字符:)

更新3:更改File.readIO.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:我使用实例变量遍历了很多hoopla来检测循环的第一次迭代。我所能得到的只是+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”不是“ puts”的捷径吗?那可以刮一些。
rfusca

1
真好 scan但是,您对的使用给了我一个更好的主意,所以我再次走上了:)。
JSBձոգչ2010年

2
您需要缩放条形图,以便最长的单词及其条形图可容纳80个字符。正如Brian所建议的那样,第二个单词很长会破坏您的程序。
加布

3
我不知道为什么它仍在收集选票。该解决方案是不正确的(在一般情况下),到目前为止,这里有两种较短的Ruby解决方案。
乔伊

1
现在,如果我错了,请纠正我,而不是使用“ downcase”,为什么不使用REGEXP不区分大小写的标志,它节省6-7个字节,不是吗?
st0le 2010年

19

Python 2.x,纬度= 227183个字符

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。我试过将所有这些单词与爱丽丝,詹姆斯国王圣经和行话文件中的单词的语料库串联起来,看看是否有任何单词会被字符串误排除。这就是我以两个排除字符串结尾的方式:itheandtoforinisandithetoforinis

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_Englishhttp://www.english-for-students.com/Frequently-Used-Words.htmlHTTP:// 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个单词是行话档案(v4.4.7)中的前10个单词the a of to and in is that or for

所以问题是,为什么将or它包含在问题的忽略列表中,而当该单词that(最常用的第8个)没有出现时,它的流行程度排在第30位。因此,我相信忽略列表应动态提供(或可以省略)。

另一种想法是简单地跳过结果中的前10个字-这实际上会缩短解决方案(基本-必须只显示第11至第32个条目)。


Python 2.x,精确的方法= 277243个字符

上面代码中绘制的图表已简化(条形图仅使用一个字符)。如果要从问题描述中完全复制图表(不需要),则此代码可以做到:

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。

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:在那里,但是没有“用户指南”。刚刚添加了一些文本
Nas Banov

关于您的语言和解决方案列表:请查找使用拆分\W\b正则表达式的解决方案,因为这些解决方案很可能符合规范,这意味着它们不会拆分成数字,或者_也可能不会从字符串中删除停用词如the_foo_or123bar。它们可能不会出现在测试文本中,但在这种情况下的规格非常清晰。
乔伊,2010年

Nas的工作很棒,我花了一个下午试图优化它,却发现有一个改进。您可以删除sys.argv黑客并使用以下re.findall(r'\b(?!(?:the|and|.|of|to|i[tns]|or)\b)\w+',sys.stdin.read().lower())
命令

12

哈斯克尔- 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 xxx直方图列表。整个列表都传递给c,因此,每次调用都c可以通过调用自己计算比例因子u。这样,我避免使用浮点数学或有理数,它们的转换函数和导入将占用许多字符。

请注意使用的技巧-frequency。这样就不需要了reversesort因为排序(升序)-frequency会将频率最高的单词放在第一位。稍后,在函数中u,两个-frequency值相乘,这将取消求反。


非常棒的工作(本会投票赞成,但今天用完了所有很好的答案后,投票都没有了)。
ChristopheD 2010年

即使以考虑描述的方式,这也以痛苦的方式伤害了我的眼睛,但是通过将其反向工程为清晰的代码,我学到了很多Haskell。干得好,先生。:-)
Owen S.

尽管效率不是很高,但实际上它还是相当惯用的Haskell。短名称使它看起来比实际情况差得多。
托马斯

@托马斯:你可以再说一遍。:-)
Owen S.

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
| ____________________________ | Ť
| __________________________ | 上
| _________________________ | 所有
| _______________________ | 这个
| ______________________ | 对于
| ______________________ | 有
| ______________________ | 但
| _____________________ | 是
| _____________________ | 不
| ___________________ | 他们
| ___________________ | 所以

(基本版本-无法正确处理钢筋宽度)

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 ---前主持人小猫,2010年

2
顺便说一句-我喜欢这个i[tns]?位。很偷偷摸摸。
dmckee ---前主持人小猫,2010年

@dmckee-发挥出色,我认为我不能击败您的336,享受您当之无愧的投票:)
Matt

您绝对可以打败336。。。有23个字符可用- .replace(/[^\w ]/g, e).split(/\s+/).map(可以替换为您.replace(/\w+/g,并使用与您.map以前使用的相同的功能...也不确定Rhino是否支持function(a,b)b.c-a.c而不是您的sort函数(spidermonkey可以),但这会刮胡子{return }... b.c-a.c是一种更好的选择a.c<b.c...通过这些更改在底部编辑Spidermonkey版本
gnarf 2010年

我将SpiderMonkey版本移至顶部,因为它符合条形宽度限制...还通过使用负的超前正则表达式拒绝了允许单个replace()的单词,从而设法在原始版本中减少了一些字符并从那里打了几个if,而且打得?:很好!
gnarf'7

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 charaters

我想使用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('!')从stdin读取的-它在哪个版本/ OS上?还是您必须将文件命名为“!”?
Nas Banov

将文件命名为“!” :)抱歉,目前还不清楚,我应该提到它。
山姆·多兰

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的warn()而不是print -在此保存了四个字符。使用map而不是foreach,但是我觉得split(join())仍然可以节省更多。不过,将其降低到203-可能会睡在上面。至少现在Perl的字符数为“ shell,grep,tr,grep,sort,uniq,sort,head,perl”;)

PS:Reddit说“嗨”;)

更新:删除了join()以支持赋值和隐式标量转换连接。降至202。还请注意,我利用了可选的“忽略1个字母的单词”规则来减少2个字符,因此请记住,频率计数将反映这一点。

更新2:交换分配和隐式联接以杀死$ /首先使用<>将文件放在一个大口中。大小相同,但更脏。将if(!$ y){}换成$ y ||| {} &&,另存1个char => 201。

更新3:通过将lc移出映射块来控制早期改写(lc <>)-不再使用两个正则表达式以不再使用/ i选项。交换传统perlgolf的显式有条件x?y:z构造|| 隐式条件构造-/^... $ /||$x { $ } ++的/^...$/i?1:$x{$ } ++保存三个字符!=> 198,突破了200的关口。也许很快就可以入睡...也许。

更新4:睡眠不足使我发疯。好。更疯狂。考虑到这只需要解析正常的快乐文本文件,如果它碰到一个空值,我就放弃了。保存了两个字符。将“长度”替换为较短的1个字符(和更多高尔夫)y /// c-您听到了吗,GolfScript?我为你而来!!!哭泣

更新5:睡眠部使我忘记了22行限制和后续行限制。处理完后最多备份208个。还算不错,要处理的13个字符并不是世界末日。玩过perl的regex内联评估,但是在使它同时工作保存字符方面遇到困难。更新了示例以匹配当前输出。

更新6:删除了不需要的大括号保护(...),因为语法糖果++允许将其愉快地推向。感谢Chas的投入。Owens(提醒我疲倦的大脑)在那里找到了字符类解决方案。回到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|ii[snt]?– 来缩短停用词的正则表达式,然后与可选规则不再有任何区别。(嗯,我从没想过要告诉一个Perl家伙如何做正则表达式:D)–现在唯一的问题:我必须看看如何从自己的解决方案中删除三个字节,再一次优于Perl:-|
乔伊

好的,不要理会我之前所说的部分内容。忽略一个字母的单词确实比不做一个字母短一个字节。
乔伊

每个字节都很重要;)我考虑过换行技巧,但我发现实际上它是相同数量的字节,即使它的可打印字符较少。仍在研究是否可以将其缩小一些:)
Syntaera

好的,大小写归一化使我回到了209。我看不到其他可以削减的内容。尽管PowerShell 可以比Perl短。;-)
乔伊(Joey)2010年

我看不到将输出限制在前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 2010年

+1是迄今为止唯一正确的钢筋缩放实施方式
Rotsor 2010年

2
(@Rotsor:具有讽刺意味的,因为我的是最古老的解决方案。)
Brian

我敢打赌,通过合并split,map和filter阶段,您可以将其大大缩短。我也希望您不需要那么多float
加布

嵌套函数通常不比使用管道运算符短|>吗?
乔伊,2010年

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 2010年

在最后一行,不需要打印后的空格,刮掉一个字符
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的挑战等等;找到另一个保存一些的地方,但是又给了两个地方以修复小节长度错误)

呵呵!我暂时领先[Matt's JavaScript] [1]解决方案反挑战!;) [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]
    }
}

做得好,很好,您包括缩进/注释版本;-)
ChristopheD 2010年

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

您是否尝试安装自定义阅读器宏以节省一些输入大小?
亚伦2010年

@Aaron实际上,即使只是开始工作,对我来说也不是一件小事……:-)对于实际的高尔夫部分,我只使用了一个字母的变量,仅此而已。无论如何,除了CL固有的针对此类问题的冗长冗长(“ concatenate'string”,“ setf”或“ gethash”都是杀手...……在python中,它们是“ +”,“ =“,“ []” )即使在逻辑上我仍然感到比我预期的要糟糕得多。从某种意义上说,我感觉Lisp可以,但是普通Lisp是这样的,这超出了命名范围(重新阅读它是非常不公平的评论,因为我在CL方面的经验接近于零)。
6502

真正。使用单一名称空间,该方案将使打高尔夫球更加容易。而不是在整个地方都附加字符串,您可以(letrec((一个字符串附加)(b gethash))...(a“ x”“ yz”)...)
Aaron 2010年

6

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

换行符确实算作字符,但是您可以从不是预处理程序指令的行中去除任何换行符。对于高尔夫,我不会认为不释放记忆是一种不好的做法。
斯蒂芬Kochen

好的...全部放到一行中(期待preproc宏),然后在不释放mem的情况下(并删除其他两个空格...)可以对“混淆”进行一些改进,例如*v=*v*(77-lw)/m将得到929。 ..但我认为这是可以的,除非我找到一种更短的方法)
ShinTakezou 2010年

我想你至少可以在移动int cmain申报和main被隐含int的(如同任何非类型化的参数,据我所知): main(c){...}。您可能也可以只写0而不是NULL
乔伊,2010年

这样做……当然会触发带有-Wall或带有-std=c99标志的警告……但是我想这对于代码高尔夫毫无意义,对吧?
ShinTakezou,2010年

抱歉,我对短间隔时间进行了编辑,...我应该改用Without freeing memory stuff, it reaches 866 (removed some other unuseful space)别的方式,以使人们不要认为免费内存版本的不同之处在于:现在,免费内存版本有很多优点更多的“改进”。
ShinTakezou,2010年

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个字符”)
Joey

5

爪哇- 886 865 756 744 742 744 752 742 714 680个字符

  • 首先742之前的更新:改进了正则表达式,删除了多余的参数化类型,删除了多余的空格。

  • 更新742> 744个字符:修复了固定长度的hack。它仅取决于第一个单词,尚未取决于其他单词。发现了几个地方,以缩短码(\\s在正则表达式替换 ArrayList替换Vector)。我现在正在寻找一种删除Commons IO依赖关系并从stdin中读取的简短方法。

  • 更新744> 752个字符:我删除了commons依赖项。现在从标准输入中读取。将文本粘贴到stdin中,然后单击Ctrl+Z以获取结果。

  • 更新752> 742个字符:我删除public了一个空格,将类名改为1个字符而不是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);
 }
}

输出:

 _________________________________________________________________________
| _________________________________________________________________________ | 她
| _______________________________________________________________ | 您
| ____________________________________________________________ | 说过
| _____________________________________________________ | 爱丽丝
| _______________________________________________ | 原为
| ___________________________________________ | 那
| ____________________________________ | 如
| ________________________________ | 她的
| _____________________________ || 与
| _____________________________ || 在
| __________________________ | 上
| __________________________ | 所有
| _______________________ | 这个
| _______________________ | 对于
| _______________________ | 有
| _______________________ | 但
| ______________________ | 是
| _____________________ | 不
| ____________________ | 他们
| ____________________ | 所以
| ___________________ | 非常
| __________________ | 什么

它几乎是吸Java没有String#join()关闭(还)。

由Rotsor编辑:

我对您的解决方案进行了几处更改:

  • 用字符串替换列表[]
  • 重用了'args'参数,而不是声明我自己的String数组。也将它用作.ToArray()的参数
  • 用String替换了StringBuffer(是的,是的,性能很差)
  • 用早期停止的选择排序替换了Java排序(只需找到前22个元素)
  • 将一些int声明汇总为一个语句
  • 实现非作弊算法,找到输出的最大限制线。无需FP即可实施。
  • 修复了文本少于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个字符。
加布

您在单词后面缺少空格。;)
st0le 2010年

当我缩小答案时,我希望能击败BalusC的提交。我还有200个字符要走,嗯!我想知道如果没有Commons IO和75个char的假设会持续多久。
Jonathon Faust

1
看起来您可以通过创建bString而不是StringBuffer 来剃一些字符。不过,我不想考虑性能如何(特别是因为您一次要添加一个字符)。
Michael Myers

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

Scala,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专家可以做得更好。

更新:在评论中,Thomas给出了一个简短的版本,长度为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}}
Thomas Jung

当然,对于理解而言,它总是非常方便!真好!
pr1001 2010年

3

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

唐吉x德的输出(同样来自古腾堡):

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

8
鱼,真的没有办法用Java来缩短它吗?我希望你们能按字符数而不是按功能获得报酬:-)
Nas Banov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.