Asallık testinin dışındaki regex kısmını açıklayacağım: aşağıdaki düzenli ifade verilen String s, yinelemeden oluşan a String t, bulur t.
System.out.println(
"MamamiaMamamiaMamamia".replaceAll("^(.*)\\1+$", "$1")
); // prints "Mamamia"
Çalışma şekli, normal ifadenin (.*)içine girmesi \1ve ardından \1+onu takip edip etmediğini görmesidir . kullanılması ^ve$ sağlayan bir maç bütün dize olması gerektiğini.
Yani, bir bakıma, String s"çarpanı" olan bize verilir String tve normal ifade bunu bulacaktır t( \1açgözlü olduğundan mümkün olan en uzun olanı ).
Bu normal ifadenin neden çalıştığını anladıktan sonra (şimdilik OP'nin normal ifadesindeki ilk alternatifi görmezden gelerek), asallık testi için nasıl kullanıldığını açıklamak basittir.
- Asallığını test etmek için
n, önce bir Stringuzunluk oluşturun n(aynısıyla doldurulmuş char)
- Normal
Stringifade , kiçine bir miktar (örneğin ) yakalar \1ve diğeriyle eşleştirmeye çalışır \1+.String
- Bir eşleşme varsa, o zaman
ntam katıdır kve bu nedenle nasal değildir.
kEşleşme yoksa bölen böyle bir şey yoktur nve nbu nedenle asal
.?|(..+?)\1+Asal sayılarla nasıl eşleşir?
Aslında öyle değil! Bu maçları String uzunluğu DEĞİL asal!
.?: Değişimli Stringuzunluk eşleşmelerinin ilk bölümü 0veya 1(tanım gereği asal DEĞİL)
(..+?)\1+: Sırayla değişen ikinci kısmı, düzenli ifade bir varyasyonu, yukarıda açıklandığı gibi, stoktaki Stringuzunluğunun niçinde bir "çoklu" olduğu Stringuzunluğunun k >= 2(diğer bir deyişlen bileşik, değil bir asal).
- İsteksiz değiştiricinin
?aslında doğruluk için gerekli olmadığını, ancak könce daha küçük deneyerek süreci hızlandırmaya yardımcı olabileceğini unutmayın.
Not ! booleaniçinde tamamlayıcı operatörü returnaçıklamada: değilleme matches. Regex zaman var ETMEZ maç, nasal! Bu ikili negatif bir mantık, bu yüzden kafa karıştırıcı olmasına şaşmamalı !!
sadeleştirme
İşte kodu daha okunaklı hale getirmek için basit bir yeniden yazma:
public static boolean isPrime(int n) {
String lengthN = new String(new char[n]);
boolean isNotPrimeN = lengthN.matches(".?|(..+?)\\1+");
return !isNotPrimeN;
}
Yukarıdakiler esasen orijinal Java koduyla aynıdır, ancak mantığın anlaşılmasını kolaylaştırmak için yerel değişkenlere atamalarla birden çok ifadeye bölünmüştür.
Ayrıca, aşağıdaki gibi, sonlu tekrar kullanarak normal ifadeyi basitleştirebiliriz:
boolean isNotPrimeN = lengthN.matches(".{0,1}|(.{2,})\\1+");
Yine, bir Stringuzunluk verildiğinde n, aynısı ile dolu char,
.{0,1}kontrol eder n = 0,1, asal DEĞİL
(.{2,})\1+asal DEĞİL, ndoğru bir katı olup olmadığını kontrol ederk >= 2
İsteksiz değiştiricinin ?açık olması dışında \1(açıklık amacıyla atlanmıştır), yukarıdaki normal ifade orijinal ile aynıdır.
Daha eğlenceli normal ifade
Aşağıdaki normal ifade benzer bir teknik kullanır; eğitici olmalı:
System.out.println(
"OhMyGod=MyMyMyOhGodOhGodOhGod"
.replaceAll("^(.+)(.+)(.+)=(\\1|\\2|\\3)+$", "$1! $2! $3!")
); // prints "Oh! My! God!"
Ayrıca bakınız
!new String(new char[n]).matches(".?|(..+?)\\1+")eşdeğerdir!((new String(new char[n])).matches(".?|(..+?)\\1+")).