代码高尔夫七月四日版:计算前十个出现最多的单词

11
给定以下总统列表,请在最小的程序中进行前十个单词计数:
输入文件 Washington Washington Adams Jefferson Jefferson Madison Madison Monroe Monroe John Quincy Adams Jackson Jackson Van Buren Harrison DIES Tyler Polk Taylor DIES Fillmore Pierce Buchanan Lincoln Lincoln DIES Johnson Grant Grant Hayes Garfield DIES Arthur Cleveland Harrison Cleveland McKinley McKinley DIES Teddy Roosevelt Teddy Roosevelt Taft Wilson Wilson Harding Coolidge Hoover FDR FDR FDR FDR Dies Truman Truman Eisenhower Eisenhower Kennedy DIES Johnson Johnson Nixon Nixon ABDICATES Ford Carter Reagan Reagan Bush Clinton Clinton Bush Bush Obama
以bash 97字符开始
cat input.txt | tr " " "\n" | tr -d "\t " | sed 's/^$//g' | sort | uniq -c | sort -n | tail -n 10

输出:

      2 尼克松
      2 里根
      2 罗斯福
      2 杜鲁门
      2 华盛顿
      2 威尔逊
      3 布什
      3 约翰逊
      4 富兰克林·罗斯福
      7 迪斯(DIES)

如有平局,请按您的喜好处理!祝第四个总统节快乐!

如果您关心更多总统信息,请访问这里


列表不应该区分布什小布什和老布什吗? - gnovice
1
还有,罗斯福总统也去世了吧?看起来很多解决方案没有仔细阅读问题,很多答案没有拆分单词,只是在 group by 后对列表进行排序。 - jasonmw
嘿 FDR FDR FDR FDR 这是我凭记忆写的,你要知道... 我同意两个观点,但为了好玩... 就让它继续吧... - ojblass
@Jawson,请放心编辑问题的内容... - ojblass
很好的工作,我太菜了无法编辑。我会选择让它保持原样.... :) - jasonmw
重复:https://dev59.com/7HNA5IYBdhLWcg3wPbSe - Sampson
16个回答

12

C#,153:

读取 p 文件并将结果打印到控制台:

File.ReadLines(p)
    .SelectMany(s=>s.Split(' '))
    .GroupBy(w=>w)
    .OrderBy(g=>-g.Count())
    .Take(10)
    .ToList()
    .ForEach(g=>Console.WriteLine(g.Count()+"|"+g.Key));

如果仅产生列表而不打印到控制台,则长度为93个字符。

6|DIES
4|FDR
3|Johnson
3|Bush
2|Washington
2|Adams
2|Jefferson
2|Madison
2|Monroe
2|Jackson

1
我对Java和CSharp的主要抱怨是它们太啰嗦了...你能用一些相当于“使用”的简洁语句来简化它吗? - ojblass
2
这相当整洁,我想。至少是半可理解的,至少与Perl版本相比是这样。 - Jonathan Leffler
'ReadLines' 应该改为 'ReadAllLines'。如果您删除 .ToList(),则可以更短,因为您可以使用 Take 返回的 IEnumerable 进行 foreach。所以:foreach (var v in File.ReadAllLines(p) .SelectMany(s => s.Split(' ')) .GroupBy(w => w) .OrderBy(g => -1 * g.Count()) .Take(10)) Console.WriteLine(v.Count() + "|" + v.Key); - JulianR
@JulianR:ReadLines 似乎是有效的,因为这样的函数在 .NET 4.0 中列出:http://msdn.microsoft.com/zh-cn/library/dd383503%28VS.100%29.aspx - Ahmad Mageed
@ Ahmad - 很奇怪。ReadAllLines和ReadLines之间的区别是什么,他们为什么在.NET 4.0中添加了这个功能?唯一的区别是一个返回IENumerable<string>而另一个返回string[]吗? - JulianR
@JulianR:请参考Lippert的这篇文章:http://blogs.msdn.com/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx - jason

11
一个更短的Shell版本:
xargs -n1 < input.txt | sort | uniq -c | sort -nr | head
如果你想进行大小写不敏感的排名,将uniq -c改为uniq -ci即可。稍微更短一点,如果你可以接受排名颠倒并因缺少空格而影响可读性。这个版本只有46个字符。
xargs -n1<input.txt|sort|uniq -c|sort -n|tail

如果允许将输入文件重命名为"i",则可以将此内容缩减至38。

观察到在这种特殊情况下,没有单词出现超过9次,因此我们可以通过从最后的排序中删除"-n"参数来节省3个字符:

xargs -n1<input.txt|sort|uniq -c|sort|tail

使用xargs -n1将文件拆分为每行一个单词的方式,而不是使用tr \ \\n的解决方案更好,因为后者会创建许多空行。这意味着该解决方案不正确,因为它遗漏了"Nixon"并显示出一个空字符串出现了256次。但是,一个空字符串不是一个“单词”。

通过这种方法,不需要重命名输入文件,就可以使该解决方案缩短至43个字符(如果您愿意,则为35个字符)。


使用xargs很聪明 - 即使数据带有前导和尾随空格,它也能正常工作。而且,“tail”单独打印输出的最后十行是一个很好的观察(我已经忘记了);这可以节省4个字符。 - Jonathan Leffler
有没有一种方法可以在vim中作弊,使用xargs并且不失去文件名长度? - ojblass

7

vim 60

    :1,$!tr " " "\n" | tr -d "\t " | sort | uniq -c | sort -n | tail -n 10
这是一个用于在 Vim 编辑器中执行的命令。它将文本转换为单词列表,并对其进行排序和计数,然后输出最常见的十个单词。

1
“:1,$!” 可以被替换为 “:%!”,不是吗? - ephemient

7

Vim 36

:%s/\W/\r/g|%!sort|uniq -c|sort|tail

绝对可以。但/鉴于这个输入,我可以不用那多余的三个字符 :) - Josef Pfleger
2
你可以省略4个字符,因为"tail"等同于"tail -10" 或者 "tail -n10"。 - Jonathan Leffler
哦,你少了一个冒号... 我讨厌漏掉冒号的时候。 - ojblass
我喜欢这个,但是xargs的人懂得...你得到了第二名...祝第四个快乐! - ojblass
这很聪明,但不幸的是与使用tr命令的解决方案产生了相同的错误输出 - 它创建了256个空行并错误地将它们显示为单词,同时在结果中遗漏了“Nixon”。 - Stig Brautaset
显示剩余4条评论

5

Haskell,102个字符(哇,与原始文本非常接近):

import List
(take 10.map snd.sort.map(\(x:y)->(-length y,x)).group.sort.words)`fmap`readFile"input.txt"

J,仅55个字符:

10{.\:~~.(,.~[:<"0@(+/)=/~);;:&.><;._2[1!:1<'input.txt'

(我还没有找到一种优雅的方法在J中进行文本操作...它更擅长于处理数组结构化数据。)


   NB. 读取文件
   <1!:1<'input.txt'
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------...
|    Washington     Washington     Adams     Jefferson     Jefferson     Madison     Madison     Monroe     Monroe     John Quincy Adams     Jackson     Jackson     Van Buren     Harrison DIES     Tyler     Polk     Taylor DIES     Fillmore     Pierce     ...
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------...
   NB. 按行分割
   <;._2[1!:1<'input.txt'
+--------------+--------------+---------+-------------+-------------+-----------+-----------+----------+----------+---------------------+-----------+-----------+-------------+-----------------+---------+--------+---------------+------------+----------+----...
|    Washington|    Washington|    Adams|    Jefferson|    Jefferson|    Madison|    Madison|    Monroe|    Monroe|    John Quincy Adams|    Jackson|    Jackson|    Van Buren|    Harrison DIES|    Tyler|    Polk|    Taylor DIES|    Fillmore|    Pierce|    ...
+--------------+--------------+---------+-------------+-------------+-----------+-----------+----------+----------+---------------------+-----------+-----------+-------------+-----------------+---------+--------+---------------+------------+----------+----...
   NB. 按单词分割
   ;;:&.><;._2[1!:1<'input.txt'
+----------+----------+-----+---------+---------+-------+-------+------+------+----+------+-----+-------+-------+---+-----+--------+----+-----+----+------+----+--------+------+--------+-------+-------+----+-------+-----+-----+-----+--------+----+------+---...
|Washington|Washington|Adams|Jefferson|Jefferson|Madison|Madison|Monroe|Monroe|John|Quincy|Adams|Jackson|Jackson|Van|Buren|Harrison|DIES|Tyler|Polk|Taylor|DIES|Fillmore|Pierce|Buchanan|Lincoln|Lincoln|DIES|Johnson|Grant|Grant|Hayes|Garfield|DIES|Arthur|Cle...
+----------+----------+-----+---------+---------+-------+-------+------+------+----+------+-----+-------+-------+---+-----+--------+----+-----+----+------+----+--------+------+--------+-------+-------+----+-------+-----+-----+-----+--------+----+------+---...
   NB. 计数重复项
   |:~.(,.~[:<"0@(+/)=/~);;:&.><;._2[1!:1<'input.txt'
+----------+-----+---------+-------+------+----+------+-------+---+-----+--------+----+-----+----+------+--------+------+--------+-------+-------+-----+-----+--------+------+---------+--------+---------+----+------+-------+--------+------+---+------+------...
|2         |2    |2        |2      |2     |1   |1     |2      |1  |1    |2       |6   |1    |1   |1     |1       |1     |1       |2      |3      |2    |1    |1       |1     |2        |2       |2        |1   |2     |1      |1       |1     |4  |2     |2     ...
+----------+-----+---------+-------+------+----+------+-------+---+-----+--------+----+-----+----+------+--------+------+--------+-------+-------+-----+-----+--------+------+---------+--------+---------+----+------+-------+--------+------+---+------+------...
|Washington|Adams|Jefferson|Madison|Monroe|John|Quincy|Jackson|Van|Buren|Harrison|DIES|Tyler|Polk|Taylor|Fillmore|Pierce|Buchanan|Lincoln|Johnson|Grant|Hayes|Garfield|Arthur|Cleveland|McKinley|Roosevelt|Taft|Wilson|Harding|Coolidge|Hoover|FDR|Truman|Eisenh...
+----------+-----+---------+-------+------+----+------+-------+---+-----+--------+----+-----+----+------+--------+------+--------+-------+-------+-----+-----+--------+------+---------+--------+---------+----+------+-------+--------+------+---+------+------...
   NB. 排序
   |

我认为最明显的问题是,如果不知道J的字符集和词汇表,符号流就没有意义...但除此之外,情况并不太糟。有哪些语言可以促进可维护的单行代码? - ephemient
我的答案提供了迄今为止最易读的解决方案。 - SilentGhost
对于 OP 使用的反向顺序,请将 10{.:~ 替换为 10{:/:~。 - ephemient

3

缺少 AWK 是令人不安的。

xargs -n1<input.txt|awk '{c[$1]++}END{for(p in c)print c[p],p|"sort|tail"}'

75个字符。

如果你想要更加熟练一些,可以忘记xargs:

awk -v RS='[^a-zA-Z]' /./'{c[$1]++}END{for(p in c)print c[p],p|"sort|tail"}' input.txt

开始使用awk吧!嗯,这有点可怕...祝第四个七十六快乐! - ojblass

3

Perl: 90

Perl:90

Perl: 114 (包括perl、命令行开关、单引号和文件名)

Perl:114(包括perl、命令行开关、单引号和文件名)
perl -nle'$h{$_}++for split/ /;END{$i++<=10?print"$h{$_} $_":0for reverse sort{$h{$a}cmp$h{$b}}keys%h}' input.txt

几个简单的技巧将整个命令压缩到84:perl -ne'${$.$/}++for+split}print+(sort{${$b}<=>${$a}}keys%_)[0..9];{' input.txt - ephemient

2
这是一个压缩版的shell脚本,需要注意的是,如果输入数据没有前导或尾随空格,则原始脚本中的第二个'tr'和'sed'命令不会改变数据(通过在适当的位置插入“tee out.N”并检查输出文件大小进行验证-相同)。 shell需要的空间比人类少-使用cat而不是输入I / O重定向浪费空间。
tr \  \\n<input.txt|sort|uniq -c|sort -n|tail -10

这段脚本总共有50个字符,包括最后换行符。

通过其他人的答案,我们可以得到两个观察结果:

  1. tail命令默认等同于'tail -10'。
  2. 在这种情况下,数字和字母排序是等价的。

因此,我们可以进一步缩短脚本长度7个字符(包括末尾换行符),达到43个字符。

tr \  \\n<input.txt|sort|uniq -c|sort|tail

使用“xargs -n1”(未给出命令前缀)代替“tr”非常聪明,它处理了前导、尾随和多个嵌入空格的情况(而此解决方案没有)。

2

我的ruby最好的尝试,至今只有166个字符:

h = Hash.new
File.open('f.l').each_line{|l|l.split(/ /).each{|e|h[e]==nil ?h[e]=1:h[e]+=1}}
h.sort{|a,b|a[1]<=>b[1]}.last(10).each{|e|puts"#{e[1]} #{e[0]}"}

我很惊讶还没有人发布疯狂的J语言解决方案。


你可以用h = {}来代替第一行。 - Cuervo's Laugh
此外,您可以替换 .each_line 位,使第一行变为:File.open('f.1').each {|l|l.split(/ /).each{|e|h[e]==nil ?h[e]=1:h[e]+=1}}这样可以节省 4 个字符。 - Cuervo's Laugh

2

python 3.1 (88 chars)

import collections
collections.Counter(open('input.txt').read().split()).most_common(10)

计数器位于集合中,而不是itertools。这也不会打印输出,并且与原始问题的输出相比是反向的顺序。 - mthurlin
是的,那是个打字错误。但我看不出满足OP所有奇 whims 的意义所在。为什么要升序而不是降序?在解释器中运行时会打印输出。 - SilentGhost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接