Je vais vous expliquer les regex en dehors de test de primalité: la regex suivante, compte tenu d'un String s
qui consiste à répéter String t
, conclut t
.
System.out.println(
"MamamiaMamamiaMamamia".replaceAll("^(.*)\\1+$", "$1")
); // prints "Mamamia"
La façon dont cela fonctionne est que la regex capture (.*)
en \1
, et voit si il y a \1+
suivant. À l'aide de l' ^
et $
assure qu'un match doit être de l'ensemble de la chaîne.
Donc dans un sens, nous sommes donnée, String s
, ce qui est un "multiple" de String t
, et la regex trouverez par exemple t
(la plus longue possible, depuis \1
est gourmand).
Une fois que vous comprenez pourquoi cette regex fonctionne, alors (en ignorant le premier suppléant dans l'OP de la regex pour l'instant) en expliquant comment il est utilisé pour les tests de primalité est simple.
- Pour tester la primalité d'
n
, d'abord générer un String
de la longueur n
(rempli avec le même char
)
- La regex de capture d'un
String
d'une certaine longueur (disons k
) en \1
, et tente de faire correspondre \1+
pour le reste de l' String
- Si il y a un match, alors
n
est un multiple de k
, et, par conséquent, n
n'est pas premier.
- Si il n'y a pas de match, cette
k
existe qui divise n
, et n
est donc un premier
Comment est - .?|(..+?)\1+
correspondent à des nombres premiers?
En fait, il n'est pas! Il correspond String
dont la longueur n'est PAS premier!
-
.?
: La première partie de l'alternance correspond String
de la longueur 0
ou 1
(PAS le premier, par définition)
-
(..+?)\1+
: La deuxième partie de l'alternance, une variation de l'expression rationnelle expliqué ci-dessus, correspond à, String
de la longueur n
qui est "multiple" de String
de la longueur k >= 2
(c - n
est un composite, PAS premier).
- Notez que les réticents modificateur
?
est en fait pas nécessaire pour la correction, mais il peut aider à accélérer le processus en essayant de petits k
premier
Remarque l' !
boolean
opérateur de complément dans l' return
déclaration: il nie l' matches
. C'est quand la regex N'a PAS de match, n
est le premier! C'est un double négatif de la logique, donc pas étonnant que c'est un peu déroutant!!
La Simplification
Voici une simple réécriture du code pour le rendre plus lisible:
public static boolean isPrime(int n) {
String lengthN = new String(new char[n]);
boolean isNotPrimeN = lengthN.matches(".?|(..+?)\\1+");
return !isNotPrimeN;
}
Le ci-dessus est essentiellement le même que l'original du code Java, mais divisée en plusieurs états avec des affectations de variables locales à faire de la logique plus facile à comprendre.
On peut aussi simplifier l'expression régulière, à l'aide de fini la répétition, comme suit:
boolean isNotPrimeN = lengthN.matches(".{0,1}|(.{2,})\\1+");
Encore une fois, donné un String
de la longueur n
, rempli avec le même char
,
-
.{0,1}
vérifie si n = 0,1
, PAS premier
-
(.{2,})\1+
vérifie si n
est un multiple de k >= 2
, PAS premier
À l'exception de l'réticents modificateur ?
sur \1
(omis pour plus de clarté), la regex est identique à l'original.
Plus de plaisir regex
La regex suivante utilise le même genre de technique; il doit être éducatif:
System.out.println(
"OhMyGod=MyMyMyOhGodOhGodOhGod"
.replaceAll("^(.+)(.+)(.+)=(\\1|\\2|\\3)+$", "$1! $2! $3!")
); // prints "Oh! My! God!"
Voir aussi