代码高尔夫:查找所有字谜
Posted
技术标签:
【中文标题】代码高尔夫:查找所有字谜【英文标题】:Code golf: find all anagrams 【发布时间】:2011-02-03 16:29:19 【问题描述】:如果单词中的字母可以重新排列以形成不同的单词,则该单词是anagram。
任务:
按字符数查找给定单词列表的所有字谜集的最短源代码。
空格和换行应该算作字符
使用码尺
---------10--------20--------30--------40--------50- -------60--------70--------80--------90--------100------ -110-------120
输入:
来自标准输入的list of words,每个单词由一个新行分隔。
例如
A
A's
AOL
AOL's
Aachen
Aachen's
Aaliyah
Aaliyah's
Aaron
Aaron's
Abbas
Abbasid
Abbasid's
输出:
所有字谜组,每组由单独的行分隔。
示例运行:
./anagram < words
marcos caroms macros
lump's plum's
dewar's wader's
postman tampons
dent tend
macho mocha
stoker's stroke's
hops posh shop
chasity scythia
...
我有一个 149 字符 perl 解决方案,我会在更多人发布后立即发布 :)
玩得开心!
编辑:澄清
假设字谜不区分大小写(即大小写字母相同) 只应打印多于 1 件的套装 每组字谜只能打印一次 字谜集中的每个单词只能出现一次EDIT2:更多说明
如果两个单词仅大小写不同,则应将它们折叠成同一个单词,由您决定为折叠的单词使用哪种大写方案 单词集只需要以新行结尾,只要每个单词以某种方式分开,例如逗号分隔或空格分隔有效。我了解某些语言内置了快速数组打印方法,因此如果它不输出空格分隔的数组,您应该可以利用它。【问题讨论】:
听起来 Prolog 中的解决方案可以很短。 大小写是否等价? 只打印多于一项的套装? 两个问题:1) 如果单词列表中有两次相同的单词但在不同的情况下,“Azalea”和“azalea”,这算作一个字谜(就像下面的大多数解决方案一样),还是必须将它们折叠成一个单词,如果没有其他字谜,不输出? 2)输出格式是否必须与上述完全匹配?还是可以接受像 '["milepost","polemist"]' 这样的每行输出? 您应该在问题meta.stackexchange.com/questions/24242中明确添加最短代码要求 【参考方案1】:Powershell,104 97 91 86 83 个字符
$k=@;$input|%$k["$([char[]]$_|%$_+0|sort)"]+=@($_)
$k.Values|?$_[1]|%"$_"
新要求的更新(+8 个字符):
要排除仅大小写不同的单词,我们可以从输入列表中删除重复项(不区分大小写),即$input|sort -u
,其中-u
代表-unique
。 sort
默认不区分大小写:
$k=@;$input|sort -u|%$k["$([char[]]$_|%$_+0|sort)"]+=@($_)
$k.Values|?$_[1]|%"$_"
[char[]]$_|%$_+0|sort
-part 的解释
它是哈希表条目的键,其中存储了单词的字谜。我最初的解决方案是:$_.ToLower().ToCharArray()|sort
。然后我发现我不需要 ToLower()
作为键,因为哈希表查找不区分大小写。
[char[]]$_|sort
是理想的,但键的字符排序需要不区分大小写(否则 Cab
和 abc
将存储在不同的键下)。不幸的是,sort
对字符不区分大小写(仅适用于字符串)。
我们需要的是[string[]][char[]]$_|sort
,但我发现了一种将每个字符转换为字符串的更短的方法,即将其他内容连接到它,在本例中为整数0
,因此[char[]]$_|%$_+0|sort
。这不会影响排序顺序,实际的键最终类似于:d0 o0 r0 w0
。它不漂亮,但它可以完成工作:)
【讨论】:
这个 Powershell 开始吓到我了 ;) 我接受这个是因为 1. 它符合所有要求 2. 它是投票最高的答案,以及 3. 我之前没有见过太多的 power shell code 打高尔夫球 :)【参考方案2】:Perl,59 个字符
chop,$_join'',sort split//,lc.="$_ "for<>;/ ./&&say for%_
请注意,这需要 Perl 5.10(对于 say
函数)。
【讨论】:
我机器上的 Perl 5.10 说:“在 ana-perl.pl 第 1 行的 &say 之前缺少运算符或分号。在 ana-perl.pl 第 1 行将 & 解析为运算符 & 的使用不明确。” @MtnViewMark:为了保护向后兼容性,必须明确启用在 5.10 版中添加到 Perl 的功能:perl -M5.010 ana-perl.pl < wordlist
这应该如何影响高尔夫成绩尚待商榷。【参考方案3】:
Haskell,147 个字符
以前的大小:150 159 个字符
import Char
import List
x=sort.map toLower
g&a=g(x a).x
main=interact$unlines.map unwords.filter((>1).length).groupBy((==)&).sortBy(compare&).lines
这个 165 个字符的版本满足新的、明确的规则:
import Char
import List
y=map toLower
x=sort.y
g&f=(.f).g.f
w[_]="";w a=show a++"\n"
main=interact$concatMap(w.nubBy((==)&y)).groupBy((==)&x).sortBy(compare&x).lines
这个版本处理:
-
输入中仅大小写不同的单词只能算作一个单词
输出必须是每行一组字谜,但可以接受额外的标点符号
【讨论】:
只是我的第一次尝试——我相信它可以被挤压。 很高兴看到一些接近惯用、易读的 Haskell 在代码高尔夫中也取得了不错的成绩! 同意,这可能是我最喜欢的答案:)【参考方案4】:Ruby,94 个字符
h=;(h[$_.upcase.bytes.sort]||=[])<<$_ while gets&&chomp;h.each|k,v|puts v.join' 'if v.at 1
【讨论】:
这是一种非常类似于 Perl 的方法,所以我希望有人能够使用 Perl 解决方案至少敲掉 5-10 个字符。【参考方案5】:Python,167 个字符,包括 I/O
import sys
d=
for l in sys.stdin.readlines():
l=l[:-1]
k=''.join(sorted(l)).lower()
d[k]=d.pop(k,[])+[l]
for k in d:
if len(d[k])>1: print(' '.join(d[k]))
没有输入代码(即如果我们假设单词列表已经在列表中w
),它只有 134 个字符:
d=
for l in w:
l=l[:-1]
k=''.join(lower(sorted(l)))
d[k]=d.pop(k,[])+[l]
for k in d:
if len(d[k])>1: print(' '.join(d[k]))
【讨论】:
去掉:
和print
之间的空格,并使用分号。我想你可以使用input()
。
这会产生区分大小写的结果。与 Dan Andreatta 或我的解决方案进行比较。
已修复,现在已根据需要指定不区分大小写。
我机器上的 Python 2.6.1 声称:“NameError: name 'lower' is not defined”
是的,这是我的一个错误,我已修复它(应该是 .lower()
而不是 lower(...)
)。【参考方案6】:
AWK - 119
split(toupper($1),a,"");asort(a);s="";for(i=1;a[i];)s=a[i++]s;x[s]=x[s]$1" "
ENDfor(i in x)if(x[i]~/ .* /)print x[i]
AWK 没有像 Python 那样的 join
函数,或者它可以更短...
假设大写和小写不同。
【讨论】:
这只会打印出字谜的单词吗?或者它还会打印出没有其他字谜的单词吗? 原始版本打印所有内容。更新修复。 我认为这必须仅适用于 Gnu awk (gawk)。标准 awk 没有 asort 函数。【参考方案7】:C++,542 个字符
#include <iostream>
#include <map>
#include <vector>
#include <boost/algorithm/string.hpp>
#define ci const_iterator
int main()using namespace std;typedef string s;typedef vector<s> vs;vs l;
copy(istream_iterator<s>(cin),istream_iterator<s>(),back_inserter(l));map<s, vs> r;
for (vs::ci i=l.begin(),e=l.end();i!=e;++i)s a=boost::to_lower_copy(*i);
sort(a.begin(),a.end());r[a].push_back(*i);for (map<s,vs>::ci i=r.begin(),e=r.end();
i!=e;++i)if(i->second.size()>1)*copy(i->second.begin(),i->second.end(),
ostream_iterator<s>(cout," "))="\n";
【讨论】:
注意:(1) 显示的实际计数要高一些,因为我添加了一些换行符以提高可读性(main() 可以在一行上)(2) 稍微压缩但可读的版本:@ 987654321@【参考方案8】:Python,O(n^2)
import sys;
words=sys.stdin.readlines()
def s(x):return sorted(x.lower());
print '\n'.join([''.join([a.replace('\n',' ') for a in words if(s(a)==s(w))]) for w in words])
【讨论】:
这...非常慢。 :P 它还多次输出每组字谜,等于集合中字谜的数量。 (哦,它还会在自己的行上输出不是字谜的单个单词,这似乎不是指定输出的一部分。) 为什么;在行尾,那不是 Python!以上是关于代码高尔夫:查找所有字谜的主要内容,如果未能解决你的问题,请参考以下文章