正規表現(PCREフレーバー)、66(65🐌)バイト
正規表現の天才であるMartin Enderとjayteaの両方がこのコードゴルフの正規表現ソリューションを書いたことに触発されて、私はゼロから自分自身を書きました。有名な素数チェック正規表現は、私のソリューションのどこにも現れません。
単項正規表現の魔法を台無しにしたくない場合は、これを読んではいけません。この魔法を自分で理解するためにショットを撮りたい場合は、ECMAScript正規表現のいくつかの問題を解決することから始めることを強くお勧めします。
- 素数に一致します(正規表現でこれを行うことに慣れていない場合)
- 2のべき乗を一致させます(まだ一致していない場合)。または、PrimeおよびPowersを含むRegex Golfを使用してください。ClassicとTeukonの両方の問題セットを必ず実行してください。
Nの累乗に一致する最短の方法を見つけます。ここで、Nは合成可能な(ただし、入力でなく正規表現で指定された)定数です(ただし、必須ではありません)。たとえば、6のべき乗に一致します。
Nの累乗を一致させる方法を見つけます。ここで、Nは2以上の定数です。たとえば、完全な正方形に一致します。(ウォームアップのために、プライムパワーと一致します。)
正しい乗算ステートメントに一致します。三角数字に一致します。
フィボナッチ数と一致する場合(あなたが私と同じくらいクレイジーな場合)、またはより短いものに固執したい場合は、べき乗の正しいステートメントに一致します(ウォームアップの場合、2の底の2の対数に一致するように戻ります)ボーナス、好きなように丸めて任意の数で同じことを行います)、または階乗数(ウォームアップの場合は、原数に一致します)。
豊富な数字に一致する(あなたが私と同じくらいクレイジーな場合)
要求された精度まで無理数を計算します(たとえば、入力を2の平方根で除算し、丸めた結果を一致として返します)
(私が書いた正規表現エンジンは、単項数学正規表現で非常に高速で、自然数の範囲をテストできる単項数値モードが含まれていますが、非単項正規表現または単項を評価できる文字列モードもありますので、役立つかもしれませんデフォルトではECMAScriptと互換性がありますが、オプションの拡張機能があります(PCREのサブセット、または他の正規表現エンジンにはない分子先読みを選択的に追加できます)。
それ以外の場合は、このGitHub Gist(警告、多くのネタバレ)を読んでください旅)。
この問題に対する他の正規表現ソリューションと同様に、入力は、全範囲を表すコンマで区切られた全単射の2つの数値として与えられます。1つの数値のみが返されます。正規表現は、同じ最小の最大素数を共有するすべての数値を個別の一致として返すように変更できますが、可変長の後読みが必要\K
であり、先読みを行うか、一致ではなくキャプチャとして結果を返す必要があります。
ここで使用されている最小の素因数による暗黙の除算の繰り返しの手法は、長さの4乗の答えである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バイト)落としますが、正規表現は指数関数的にスローダウンします。
オンラインでお試しください! (79バイトECMAScript指数関数的スローダウンバージョン)