Regex Golf网址:https://alf.nu/RegexGolf
Regex Golf通关解答:Regex Golf通关解答-优快云博客
顾名思义,本篇的题目都是让我们去匹配一些合法的等式的。与数字篇不同,等式篇的题目想出一个合法的答案并不算太难,但如何才能把答案优化到最少字符,才是本篇的关键。
Subtraction–Quantify with care.
利用反向引用,很容易就可以得到答案:^(.+)(.+) - \1 = \2$,使用20个字符。但是观察排行榜可以知道,存在一个18字符的答案。这会就需要我们稍微打破一下惯性思维了,减数后面的那个空格和被减数后面那个空格用同样的模式进行匹配的,且不影响等式成立,所以最少字符的答案为:^(.+)(.+)- \2= \1$。
Addition–Beauty in symmetry.
减法下来就是加法,真是一点毛病都没有。有了上一题的经验,既然空格可以进分组,那么加号也可以啊,再加上题目中“Beauty in symmetry”的提示,我很快写出了第一版答案:^(.*)(.*)(.*) = \3\2\1$,共23个字符。然而如果继续观察的话,就会发现后两个分组是可以合并的,完全没有必要分开,于是得到最终答案:^(.*)(.*) = \2\1$。
Modulus–Lookahead smithwork.
加减法完成之后又是求模,没问题。a % b = c,意味着a = bx + c,于是我先按照(bx + c) % b = c的思路进行匹配,得到了第一版答案:^(x+)\1*(x+) % \1 = \2$,但是这个答案是错误的,它不能匹配a长度小于b长度的情况(例如:x % xxxx = x)。
那如果可以先捕获b,然后在第a的位置引用呢:^\2*(x+) % (x+) = \1$,但是很遗憾,这个写法也是不行。反向引用,要求先捕获,然后“反向”引用,我们是无法提前使用一个尚未捕获的分组的。那怎么才能做到在捕获b时,a中的字符还没被匹配消掉呢?使用零宽断言呀!于是我第二版的答案如下:^(?=(x+) % (x+) = (x+)$)\2*\3 。
这个答案满足(bx + c) % b = c,但是它并没有约束c的长度必须小于b,这就导致xxxxx % xxxxx = xxxxx这样的等式被错误的匹配了。加上c长度小于b这个约束,我终于得到了一个正确答案:^(?=(x+) % (x+)(x+) = \3$)(\2\3)*\3 ,共36个字符。接下来就是优化时间了。
首先,虽然我们捕获了三个分组,但实际我们只使用了两个,也就是说,第一个分组捕获是没有意义的。所以第一次优化结果为:^(?=.+ (x+)(x+) = \2$)(\1\2)*\2 ,32个字符。然后我们把(\1\2)合并成一个分组:^(?=.+ ((x+)(x+)) = \3$)\1*\3 ,30个字符。我们再次发现所捕获的分组二并没有被使用,也就是说它并不需要被捕获,所以我都最终答案为:^(?=.+ (x+(x+)) = \2$)\1*\2 ,28个字符(注意正则表达式结尾有一个空格)。看网站排名,字符最少的答案为25字符,我暂时还没有思路。
Euclid–Greed is good.
最后是一道匹配最大公约数等式的题目,形如gcd(a, b) = c。首先我按照a = cx,b = cy的思路进行匹配:
^gcd\((x+)\1*, \1+\) = \1$
遗憾的是,这个表达式匹配出来的c是a和b的合法公约数,但不是最大公约数。最大公约数要求a = cx,b = cy的前提下,不能存在a = cnx, b = cny,n > 1。加上上述约束,结合反向引用,零宽断言,我目前能写出的最佳答案为:
^(?=.* (x+)$)(?!.*\((\1\1+)\2*, \2+\)).*\(\1+, \1+\)
52个字符。看网站排名,字符最少的答案只使用25个字符,我暂时还没有思路。