Javaの次のコード例を見つけました。ロゼッタコード:
public static boolean prime(int n) {
return !new String(new char[n]).matches(".?|(..+?)\\1+");
}
- 私は特にJavaを知りませんが、正規表現自体を除いてこのスニペットのすべての側面を理解しています
- 私は組み込みのPHP関数にあるような正規表現の基礎から上級レベルの知識を持っています。
.?|(..+?)\\1+
素数はどうやって一致しますか?
ベストアンサー1
この部分は理解しているとのことですが、念のため強調しておきますが、生成された文字列の長さは、指定された数値と同じです。したがって、文字列が 3 文字になるのは、 の場合のみですn == 3
。
.?
正規表現の最初の部分は、「任意の文字、0 回または 1 回」です。つまり、基本的には、文字が 0 個か 1 個か、または、上で述べたように、 ですn == 0 || n == 1
。一致した場合は、その否定を返します。これは、0 と 1 が素数ではないという事実に対応しています。
(..+?)\\1+
正規表現の 2 番目の部分は少し複雑で、グループとバックリファレンスに依存しています。グループとは括弧で囲まれたもので、正規表現エンジンによってキャプチャされ、後で使用するために保存されます。バックリファレンスとは、同じ正規表現で後で使用される一致したグループです。
グループは 1 文字をキャプチャし、次に任意の文字を 1 つ以上キャプチャします。(+ 文字は、前の文字またはグループの 1 つ以上の文字のみを意味します。したがって、これは「2 文字、4 文字、6 文字など」ではなく、「2 文字、3 文字など」です。+? は + に似ていますが、できるだけ少ない文字に一致しようとします。+ は通常、可能であれば文字列全体を取り込もうとしますが、この場合はバックリファレンス部分が機能しなくなるため、これは良くありません。)
次の部分はバック参照です。同じ文字セット (2 つ以上) が再び現れます。このバック参照は 1 回以上現れます。
つまり、キャプチャされたグループは、キャプチャされた文字の自然数 (2 以降) に対応します。その後、このグループは自然数 (これも 2 以降) で出現します。一致がある場合、これは、長さ n の文字列に一致する 2 以上の 2 つの数値の積を見つけることが可能であることを意味します。つまり、合成 n があるということです。したがって、再び、成功した一致の否定を返します。n は素数ではありません。
一致するものが見つからない場合は、2 以上の 2 つの自然数の積を導き出すことはできません... 不一致と素数の両方が存在するため、一致結果の否定が返されます。
分かりましたか? 信じられないほど難しい (そして計算コストが高い!) ですが、一度理解してしまえば、同時にとても簡単なことでもあります。:-)
正規表現の解析が実際にどのように機能するかなど、さらに質問がある場合は詳しく説明できます。ただし、現時点では、この回答をシンプルに(または可能な限りシンプルに)しようとしています。