2012-06-21 180 views
14
之间

例如与五个字母ABCDE一个字,每个字母出现正好一次,以任意顺序,没有休息,字崩溃会因为debac工作,但海底将不起作用,因为:1.在任何可以形成的5个字符的序列中没有c,并且2.字母e出现两次。又如,反馈将因为edbac而工作。请记住,解决方案必须仅使用正则表达式来完成。使用正则表达式来查找

我试图实施的策略是:匹配第一个字母,如果它在[a-e]里面,并记住它。然后找到[a-e]中的下一个字母,但不是第一个字母。等等。我不知道语法是什么(或者即使某些语法存在的),所以我的代码没有工作:

open(DICT, "dictionary.txt"); 
@words = <DICT>; 

foreach my $word(@words){ 

if ($word =~ /([a-e])([a-e^\1])([a-e^\1^\2])([a-e^\1^\2^\3])([a-e^\1^\2^\3^\4])/ 
){ 
    print $word; 
} 
} 

我也在想使用(=正则表达式?)和\ G变的,但我没”确定它会如何工作。

回答

15
/ 
    (?= .{0,4}a) 
    (?= .{0,4}b) 
    (?= .{0,4}c) 
    (?= .{0,4}d) 
    (?= .{0,4}e) 
/xs 

这可能导致更快的匹配,生成所有组合的模式。

use Algorithm::Loops qw(NextPermute); 
my @pats; 
my @chars = 'a'..'e'; 
do { push @pats, quotemeta join '', @chars; } while NextPermute(@chars); 
my $re = join '|', @pats; 

ABCDE | abced | abdce | ABDEC | ABECD | abedc | acbde | acbed | acdbe | acdeb | acebd | acedb | adbce | adbec | adcbe | adceb | adebc | adecb | aebcd | aebdc | aecbd | aecdb | aedbc | aedcb | bacde | baced | badce | badec | baecd | baedc | bcade | bcaed | bcdae | BCDEA | bcead | bceda | bdace | bdaec | bdcae | bdcea | bdeac | bdeca | beacd | beadc | becad | becda | bedac | bedca | cabde | cabed | cadbe | cadeb | caebd | caedb | cbade | cbaed | cbdae | cbdea | cbead | cbeda | cdabe | cdaeb | cdbae | cdbea | cdeab | cdeba | ceabd | ceadb | cebad | cebda |中央评价数据库| cedba | dabce | dabec | dacbe | daceb | daebc | daecb | dbace | dbaec | dbcae | dbcea | dbeac | dbeca | dcabe | dcaeb | dcbae | dcbea | dceab | dceba | DEABC | deacb | debac | debca | decab | decba | EABCD | eabdc | eacbd | eacdb | eadbc | eadcb | ebacd | ebadc | ebcad | ebcda | ebdac | ebdca | ecabd | ecadb | ecbad | ecbda | ecdab | ecdba | edabc | edacb | edbac | edbca | edcab | edcba

(这将在Perl 5.10+中得到优化。 5.10之前,使用正则表达式::列表。)

+1

+1 - 我比我自己的解决方案更喜欢这个。为了向其他人解释,这些预测保证:在接下来的5个字母中,至少有一个'a',至少一个'b',至少一个'c',至少一个'd'和至少一个' E”。鉴于只有五个“插槽”,它保证每个只出现一次。 –

+0

增加了替代解决方案。 – ikegami

+0

如果你想找到重复的东西(例如abcdd而不是abcde) – ikegami

6
#! perl -lw 
for (qw(debacle seabed feedback)) { 
    print if /([a-e])(?!\1) 
     ([a-e])(?!\1)(?!\2) 
     ([a-e])(?!\1)(?!\2)(?!\3) 
     ([a-e])(?!\1)(?!\2)(?!\3)(?!\4) 
     ([a-e])/x; 
} 
7

你的解决方案是聪明,但遗憾的是[a-e^...]不起作用,因为你发现了。我不相信有一种方法可以混合规则和否定字符类。我能想到用向前看符号虽然一种解决方法:

/(([a-e])(?!\2)([a-e])(?!\2)(?!\3)([a-e])(?!\2)(?!\3)(?!\4])([a-e])(?!\2)(?!\3)(?!\4])(?!\5)([a-e]))/ 

见这里:http://rubular.com/r/6pFrJe78b6

UPDATE:暴徒在下面的评论中指出,该交替可以用来压缩以上:

/(([a-e])(?!\2)([a-e])(?!\2|\3)([a-e])(?!\2|\3|\4])([a-e])(?!\2|\3|\4|\5)([a-e]))/ 

新的演示:http://rubular.com/r/UUS7mrz6Ze

+0

请注意,你不能在字符类中有反向引用。因此需要多个反向引用而不是像''(?![\ 2 \ 3 \ 4 \ 5])''。此外,我不得不从2开始计数,因为我想为rubular演示包含一个“整体”捕获组。 –

+1

但你可以使用替代:'...(?!\ 2 | \ 3 | \ 4 | \ 5)' – mob