1. ホーム
  2. java

[解決済み] 正規表現で数字が素数かどうかを判断するには?

2022-06-27 06:32:19

質問

以下のようなJavaのコード例を RosettaCode :

public static boolean prime(int n) {
  return !new String(new char[n]).matches(".?|(..+?)\\1+");
}

  • 私は特にJavaを知りませんが、正規表現そのものを除いて、このスニペットのすべての側面を理解しています。
  • PHPの組み込み関数にあるようなREGEXの基礎から応用までの知識を持っている

どのように .?|(..+?)\\1+ はどのように素数に一致するのでしょうか?

どのように解決するのですか?

この部分を理解したと言いましたが、念のため強調すると、生成される文字列は指定された数と同じ長さになります。つまり、以下の場合にのみ、文字列は3文字になります。 n == 3 .

.?

正規表現の最初の部分には、"任意の文字、0回または1回"とあります。つまり、基本的には、0回または1回の文字があるか--あるいは、上に書いたように n == 0 || n == 1 . もしマッチしていれば、その否定を返します。これは、0と1が素数ではないことに対応しています。

(..+?)\\1+

正規表現の2番目の部分は、グループと後方参照に依存しているため、少しトリッキーです。グループとは括弧の中にあるもので、後で使用するために正規表現エンジンに取り込まれて保存されます。後方参照は一致したグループのことで、同じ正規表現で後で使用されます。

グループは 1 文字をキャプチャし、次に任意の文字の 1 つまたは複数をキャプチャします。(+ 文字は 1 つ以上を意味しますが、直前の文字またはグループのみです。つまり、これは "two or four or six etc. characters" ではなく、 "two or three etc." + は + と似ていますが、できるだけ少ない文字に一致させようとします。通常、+は可能であれば文字列全体を取得しようとしますが、この場合、後方参照部分が機能しなくなるため、好ましくありません)。

次の部分は後方参照です。同じ文字列(2つ以上)が、再び現れる。この後方参照は1回以上出現します。

ということです。捕捉されたグループは、捕捉された文字の自然数(2以降)に相当する。前記グループは、(同じく2以降の)自然な回数だけ現れる。もしマッチするものがあれば、それはn個の長さの文字列にマッチする2以上の数の積を見つけることが可能であることを意味します...つまり、合成nがあるということです。

一致するものが見つからない場合、2以上の2つの自然数の積が思いつかず、非一致と素数の両方があるため、再度、一致結果の否定を返します。

これでわかりましたか?信じられないほどトリッキーですが(そして計算も高い!)、一度わかってしまえば、同時にちょっと簡単でもあります :-)

さらに質問があれば、正規表現の解析が実際にどのように行われるかについて詳しく説明します。しかし、今のところ、この回答はシンプルに保とうとしています (あるいは、できる限りシンプルに保とうとしています)。