代码高尔夫:查找所有字谜

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 代表-uniquesort 默认不区分大小写:

$k=@;$input|sort -u|%$k["$([char[]]$_|%$_+0|sort)"]+=@($_) 
$k.Values|?$_[1]|%"$_" 

[char[]]$_|%$_+0|sort -part 的解释

它是哈希表条目的键,其中存储了单词的字谜。我最初的解决方案是:$_.ToLower().ToCharArray()|sort。然后我发现我不需要 ToLower() 作为键,因为哈希表查找不区分大小写。

[char[]]$_|sort 是理想的,但键的字符排序需要不区分大小写(否则 Cababc 将存储在不同的键下)。不幸的是,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 &lt; 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!

以上是关于代码高尔夫:查找所有字谜的主要内容,如果未能解决你的问题,请参考以下文章

在给定的字符串列表中查找字符串的所有字谜

javascript [438。查找字符串中的所有字谜] #tags:leetcode

Python:字谜查找器

正则表达式 - 查找字谜和子字谜

如何在不递归的情况下找到所有可能的字谜?

javascript中的字谜查找器