最短的简单正则表达式匹配二进制单词


20

任务

简单的正则表达式定义为仅包含以下内容的非空正则表达式

  • 字符01
  • 分组括号()
  • 一个或多个重复量词+

给定0s和1s 的非空字符串,您的程序应找到与完整输入字符串匹配的最短简单正则表达式。(也就是说,当匹配一个简单的正则表达式时,假装它由^ 和  预定$。)如果有多个最短的正则表达式,请打印其中的一个或全部。

,所以最短的提交(以字节为单位)获胜。

测试用例

1 -> 1
00 -> 00 or 0+
010 -> 010
1110 -> 1+0
01010 -> 01010
0101010 -> 0(10)+ or (01)+0
011111 -> 01+
10110110 -> (1+0)+
01100110 -> (0110)+ or (01+0)+
010010010 -> (010)+
111100111 -> 1+001+ or 1+0+1+
00000101010 -> 0+(10)+ or (0+1)+0
1010110001 -> 1(0+1+)+ or (1+0+)+1

3
您应该阐明,您要我们编写一个编写正则表达式的程序,而不是自己编写正则表达式。但这看起来很有趣。
gcampbell '16

1
在我的测试中,这01100110是一个有趣的案例...天真的算法会写出01+0+1+0或者(0+1+)+0不是最佳算法。
尼尔

Answers:


2

Pyth,20个字节

hf.x}z:zT1Zy*4"()01+

这大约需要30秒钟才能运行,因此需要离线运行。

说明:

hf.x}z:zT1Zy*4"()01+
                        Implicit: z is the input string.
              "()01+    "()01+"
            *4          Repeated 4 times
           y            All subsequences in length order
hf                      Output the first one such that
      :zT1              Form all regex matches of z with the candidate string
    }z                  Check if the input is one of the strings
  .x      Z             Discard errors

我不完全确定每个最短的字符串都是“()01 +” * 4的子序列,但是如果需要,可以将4增大为9,而无需花费任何字节。


9

JavaScript(ES6),488341字节

s=>[s.replace(/(.)\1+/g,'$1+'),...[...Array(60)].map((_,i)=>`(${(i+4).toString(2).slice(1)})+`),...[...Array(1536)].map((_,i)=>`${i>>10?(i>>8&1)+(i&2?'+':''):''}(${i&1}${i&4?i>>4&1:i&16?'+':''}${i&8?''+(i>>7&1)+(i&64?i>>5&1:i&32?'+':''):''})+${i&512?(i>>8&1)+(i&2?'+':''):''}`)].filter(r=>s.match(`^${r}$`)).sort((a,b)=>a.length-b.length)[0]

说明:由于六个正则表达式可以表达所有可能的二进制单词,并且最长的两个正则表达式长度为9个字符,因此足以检查这些正则表达式和所有较短的正则表达式。一个候选者显然是带有“游程长度编码”的字符串(即用适当的+s 替换所有数字游程),但也()需要检查一组s的字符串。我生成了1596个这样的正则表达式(包括重复项和无用的正则表达式,但是它们将被淘汰),并测试所有1597个正则表达式,以找出最短的匹配项。生成的正则表达式分为两种类型:\(\d{2,5}\)\+(60个正则表达式)和(\d\+?)?\(\d[\d+]?(\d[\d+]?)?\)(\d\+?)?(1536个正则表达式,因为我避免使用前导和尾随数字生成正则表达式)。


@LeakyNun最初我以为有4个长度为9的正则表达式,但这显然是不正确的,因此我澄清了我的解释。
尼尔


1

Ruby,109个字节

这是无聊的暴力手段。之所以有效,是因为正则表达式的长度不必超过9个字符(如Neil所述),并且每个字符都不需要重复超过4次(尝试使用它'01()+'.chars*9会使我的CPU感到不满意)。

10.times{|i|('01()+'.chars*4).combination(i).map{|s|begin
/^#{s*''}$/=~$*[0]&&[puts(s*''),exit]
rescue
end}}
$ for word in `grep -Po '^\S+' test_cases.txt`; do nice -n20 ruby sre.rb $word; done
1
0+
010
1+0
01010
0(10)+
01+
(1+0)+
(01+0)+
(010)+
1+0+1+
0+(10)+
1(0+1+)+

1

Python 3,186个字节

我正在调查除蛮行外是否还有解决此问题的方法,但是现在这是Python蛮力解决方案。

import re,itertools
def a(b):
 for z in range(10):
  for i in itertools.combinations("01()+"*4,z):
   j=''.join(i)
   try:
    if re.fullmatch(j,b)and len(j)<=len(b):return j
   except:1
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.