正则表达式(PCRE风味),66(65🐌)字节
看到两位正则表达式天才Martin Ender和jaytea都为该代码高尔夫编写了正则表达式解决方案而受到启发,我从头开始编写了自己的解决方案。著名的素数检查正则表达式未出现在我的解决方案中的任何地方。
如果您不希望破坏一元正则表达式魔术,请不要阅读此书。如果您确实想自己弄清楚该魔术,我强烈建议您先解决ECMAScript正则表达式中的一些问题:
- 匹配素数(如果您还不熟悉正则表达式)
- 匹配2的幂(如果您尚未这样做)。或者只是通过Regex Golf(包括Prime和Powers)进行工作。确保同时完成Classic和Teukon问题集。
找到最短的方法来匹配N的幂,其中N是可以复合(但不是必需)的某个常数(即,在正则表达式中指定,而不是输入中指定)。例如,匹配的幂为6。
找到一种匹配第N个幂的方法,其中N是某个常数> = 2。例如,匹配完美的正方形。(要进行热身,请匹配主要力量。)
匹配正确的乘法语句。匹配三角数。
匹配斐波那契数字(如果您像我一样疯狂),或者如果您想坚持更短一些,请匹配正确的幂运算语句(对于热身,以2为底的对数以2为底的对数返回-奖金,对任何数字进行相同的处理(根据需要将其四舍五入)或阶乘数(对于热身,匹配原始数)。
匹配大量数字(如果您像我一样疯狂)
计算要求的精度的无理数(例如,将输入除以2的平方根,将舍入的结果返回为匹配项)
(我编写的regex引擎可能会有所帮助,因为它在处理一元数学正则表达式时非常快,并且包括可以测试自然数范围的一元数值模式(但也具有可以评估非一元正则表达式或一元字符串的字符串模式)默认情况下,它与ECMAScript兼容,但是具有可选的扩展名(可以有选择地添加PCRE的子集,甚至可以添加分子前瞻性,而其他正则表达式引擎则没有)。
否则,请继续阅读并阅读此GitHub Gist(警告,许多破坏者),它记录了推动ECMAScript regex处理难度越来越大的自然数函数的旅程(从teukon的一组难题开始,并非都是数学难题,这激发了这一点)旅程)。
与该问题的其他正则表达式解决方案一样,输入以双目一元形式的两个数字形式给出,并用逗号分隔,表示一个包含范围。仅返回一个数字。可以对正则表达式进行修改,以返回所有具有相同最小最大素数的所有数字作为单独的匹配项,但是这将需要变长的后向\K
查找,或者提前查找或将结果作为捕获而不是匹配返回。
这里用最小素数重复进行隐式除法的技术与Match字符串中使用的技术相同,Match字符串的长度是我不久前发布的第四次幂次答案。
事不宜迟:
((.+).*),(?!.*(?=\1)(((?=(..+)(\5+$))\6)*)(?!\2)).*(?=\1)\K(?3)\2$
您可以在这里尝试。
以及带有注释的免费版本:
# No ^ anchor needed, because this algorithm always returns a
# match for valid input (in which the first number is less than
# or equal to the second number), and even in /g mode only one
# match can be returned. You can add an anchor to make it reject
# invalid ranges.
((.+).*), # \1 = low end of range; \2 = conjectured number that is the
# smallest number in the set of the largest prime factor of each
# number in the range; note, it is only in subsequent tests that
# this is implicitly confined to being prime.
# We shall do the rest of our work inside the "high end of range"
# number.
(?! # Assert that there is no number in the range whose largest prime
# factor is smaller than \2.
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
( # Subroutine (?3):
# Find the largest prime factor of tail, and leave it in tail.
# It will both be evaluated here as-is, and later as an atomic
# subroutine call. As used here, it is not wrapped in an atomic
# group. Thus after the return from group 3, backtracking back
# into it can increase the value of tail – but this won't mess
# with the final result, because only making tail smaller could
# change a non-match into a match.
( # Repeatedly divide tail by its smallest prime factor, leaving
# only the largest prime factor at the end.
(?=(..+)(\5+$)) # \6 = tool to make tail = \5 = largest nontrivial factor of
# current tail, which is implicitly the result of dividing it
# by its smallest prime factor.
\6 # tail = \5
)*
)
(?!\2) # matches iff tail < \ 2
)
# now, pick a number in the range whose largest prime factor is \2
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
\K # Set us up to return tail as the match.
(?3) # tail = largest prime factor of tail
\2$ # Match iff tail == \2, then return the number whose largest
# prime factor is \2 as the match.
通过将子例程调用替换为该子例程的副本,然后将匹配项作为捕获组返回而不是使用\ K,可以轻松地将该算法移植到ECMAScript。结果是80个字节的长度:
((x+)x*),(?!.*(?=\1)((?=(xx+)(\4+$))\5)*(?!\2)).*(?=\1)(((?=(xx+)(\8+$))\9)*\2$)
在线尝试!
请注意,((.+).*)
可以将其更改为((.+)+)
,将大小减小1个字节(从66 个字节减少到65个字节),而不会丢失正确的功能-但是regex呈指数级增长。
在线尝试! (79字节ECMAScript指数减速版本)