Düzenli ifadeler kullanan bir dizenin bir palindrom olup olmadığı nasıl kontrol edilir?


94

Bu cevaplayamadığım bir röportaj sorusuydu:

Düzenli ifadeler kullanan bir dizenin bir palindrom olup olmadığı nasıl kontrol edilir?

ps " Verilen dizenin palindrome olup olmadığı nasıl kontrol edilir? " sorusu zaten var ve farklı dillerde birçok yanıt veriyor, ancak normal ifadeleri kullanan bir yanıt yok.



2
Bugünlerde (2018) ve "palindrom regex" i arayanlar için , Prakhar'ın bağlantısında PCRE'nin özyinelemeli kalıpları destekleyen tartışmasına ve karşılaştırmalarla birlikte aşağıdaki özyinelemeli regex'ime bakın .
Peter Krauss

Yanıtlar:


155

Bu sorunun cevabı "imkansız" dır. Daha spesifik olarak, görüşmeci hesaplama teorisi dersinize dikkat edip etmediğinizi merak ediyor.

Hesaplama teorisi sınıfınızda sonlu durum makinelerini öğrendiniz. Sonlu durum makinesi, düğümlerden ve kenarlardan oluşur. Her kenar, sonlu bir alfabeden bir harfle notlandırılmıştır. Bir veya daha fazla düğüm özel "kabul eden" düğümlerdir ve bir düğüm "başlangıç" düğümüdür. Her harf belirli bir kelimeden okundukça, makinede verilen kenarı geçiyoruz. Kabul etme durumuna gelirsek, makinenin bu kelimeyi "kabul ettiğini" söyleriz.

Normal bir ifade her zaman eşdeğer bir sonlu durum makinesine çevrilebilir. Yani, normal ifadeyle aynı kelimeleri kabul eden ve reddeden bir kelime (gerçek dünyada, bazı normal ifade dilleri rastgele işlevlere izin verir, bunlar sayılmaz).

Tüm palindromları kabul eden bir sonlu durum makinesi inşa etmek imkansızdır. Kanıt, keyfi olarak çok sayıda düğüm gerektiren bir dizeyi kolayca oluşturabileceğimiz gerçeklerine, yani dizeye dayanır.

a ^ xba ^ x (ör., aba, aabaa, aaabaaa, aaaabaaaa, ....)

burada a ^ x, x kez tekrarlanan bir sayıdır. Bu, en az x düğüm gerektirir, çünkü 'b'yi gördükten sonra, onun bir palindrom olduğundan emin olmak için x kez geri saymamız gerekir.

Son olarak, orijinal soruya geri dönersek, görüşmeciye bazı sabit uzunluklardan daha küçük olan tüm palindromları kabul eden normal bir ifade yazabileceğinizi söyleyebilirsiniz. Palindromların tanımlanmasını gerektiren bir gerçek dünya uygulaması varsa, o zaman neredeyse kesinlikle keyfi olarak uzun olanları içermeyecektir, bu nedenle bu cevap, teorik imkansızlıkları gerçek dünya uygulamalarından ayırt edebileceğinizi gösterecektir. Yine de, gerçek normal ifade, eşdeğer 4 satırlık programdan çok daha uzun olacaktır (okuyucu için kolay alıştırma: palindromları tanımlayan bir program yazın).


7
@SteveMoser Ruby 1.9.x'te, düzenli ifadeler artık Normal (Otomata Teorisi anlamında) değildir ve bu nedenle palindromları kontrol etmek gibi şeyler mümkündür. Bununla birlikte, amaç ve amaçlar için, palindromlar bir Normal regex ile kontrol edilemez (mantıklı mı?).

1
@SteveMoser iyi Ruby'nin düzenli ifade motoru writeup (Orada >=1.9) burada

@John haklı, bu yüzden soru bağlamında Jose haklı ve hqt yanlış.
Steve Moser

2
Akademik terimlerle, normal bir ifadenin belirli sınırları vardır (bir DFA'yı tanımlar). Gerçekte, birçok regexp motoru (öncelikle Perl ve onun akrabaları), akademik tanımı ihlal eden (NFA veya daha geniş hale gelen) geri referansları destekler. Dolayısıyla bu sorunun, sorucunun referans çerçevesinin ne olduğuna bağlı olarak farklı yanıtları vardır.
jiggy

Sözlü bir testte "formalz imkansızdır" ile gitmelisiniz, ancak bazı normal ifade motorlarının buna izin verdiğini belirtmelisiniz.
Oliver A.

46

İken PCRE motor desteği özyinelemeli düzenli ifadeler yapar (bkz Peter Krauss tarafından cevap üzerinde bir normal ifadeler kullanabilirsiniz edemez) YBÜ (Apple tarafından örneğin kullanıldığı gibi) ekstra kod olmadan bunu başarmak için motor. Bunun gibi bir şey yapmanız gerekecek:

Bu, herhangi bir palindromu algılar, ancak bir döngü gerektirir (normal ifadeler sayılamayacağı için gerekli olacaktır).

$a = "teststring";
while(length $a > 1)
{
   $a =~ /(.)(.*)(.)/;
   die "Not a palindrome: $a" unless $1 eq $3;
   $a = $2;
}
print "Palindrome";

4
İyi cevap. Soru, bir palindromu kutudan çıkarır çıkarmaz algılayan tek bir normal ifade istemiyordu - basitçe, normal ifadeleri kullanan palindromları tespit etmek için bir yöntem istedi. Bu şekilde baktığınız için anlayışınız için tebrikler.
Stewart

1
Yalnızca tek bir normal ifade kullanan en basit eşleştirmeye de bakın (dize manipülasyonu olmadan), stackoverflow.com/a/48608623/287948
Peter Krauss

Teşekkürler @PeterKrauss. PCRE'nin özyinelemeye sahip olduğunu bilmiyordum. Cevabınıza başvurdu.
Airsource Ltd

33

Bu mümkün değil. Palindromlar normal bir dille tanımlanmaz. (Bakın, hesaplama teorisinde bir şeyler öğrenmiştim)


2
Çoğu normal ifade motoru, normal dillerden daha fazlasını yakalar (örneğin net, eşleşen parantezleri yakalayabilir). Yalnızca standart normal ifadeler normal dillerle sınırlıdır.
Santiago Palladino

Soru "düzenli ifade" terimini kullanıyordu ... bu yüzden ZCHudson'ın cevabı doğru.
paxos1977

2
@austirg: ZCHudson'ın cevabı doğru ama eksik. Modern programlama dillerinde kullanılan düzenli ifadeler ve teorik bilgisayar bilimleri sınıflarında kullanılan normal ifadeler farklı canavarlardır. Terim sadece tarihi bir mirastır. Stackoverflow.com/questions/233243#235199 ve cevabıma bakın .
jfs

2
@JF Sebastian - Bu konuda austirg ile aynı fikirde olmalıyım. Normal ifade terimi, comp sci tanımında belirtilen belirli bir programlama dili olmadan kullanıldığında geçerlidir. Normal ifadeleri destekleyen tüm diller bunu yapamaz, bu nedenle burada kullanılanın yaptığını varsaymamalıyız.
Rontologist

@Rontologist: Soruda programlama dili seçiminde herhangi bir kısıtlama görmüyorum, dolayısıyla herhangi bir dile izin veriliyor. Sağa bakın: İlgili sorulardaki "düzenli ifade" nin anlamı nedir? Bunlardan herhangi birinde belirli bir programlama dilinden bahsediliyor mu?
jfs

28

Perl regex ile:

/^((.)(?1)\2|.?)$/

Yine de, birçok kişinin de belirttiği gibi, katı olmak istiyorsanız, bu normal bir ifade olarak kabul edilemez. Normal ifadeler özyinelemeyi desteklemez.


bu
PCRE'de

Haklısın. PCRE, özyinelemeyi atomik bir grup olarak ele alırken, Perl bunun içinde geri dönüşe izin veriyor. Bu kontrolü PCRE'de yapmanın mümkün olduğunu sanmıyorum.
Markus Jarderot

1
Şaşırtıcı bir şekilde, Latin olmayan diller, örneğin Ermenice için çalışmıyor.
Temujin

4
@Temujin Bunun nedeni, unicode karakterlerin kodlanmış baytlar olarak eşleştirilmesidir ( /udeğiştirici ekleyin ) veya birleştirici karakterler nedeniyle. ( kaçış dizisi. ile değiştirin ). \X
Markus Jarderot

1
Desenim PCRE'de çalışmıyor. Perl'de çalışıyor. Alt dizeler tekrarlandığında deseniniz başarısız oluyor. Örneğin abababa. PCRE tabanlı regex motorlarını kullanırken her girdi için özyineleme ile çalışması mümkün değildir. Casimirs regex, yineleme ve değişken durumu kullanarak farklı bir yaklaşım kullanır ve oldukça etkileyicidir.
Markus Jarderot

15

İşte karakterin her tür için: (senet örn) 4 harfli palindrom algılamak için: biri

\(.\)\(.\)\2\1

İşte 5 harfli palindromları (örneğin: radar) algılayarak yalnızca harfleri kontrol etmek için:

\([a-z]\)\([a-z]\)[a-z]\2\1

Bu nedenle, her olası kelime uzunluğu için farklı bir normal ifadeye ihtiyacımız var gibi görünüyor. Bir Python posta listesindeki bu gönderi , nedeniyle ilgili bazı ayrıntılar içerir (Sonlu Durum Otomatı ve pompalama lemması).


14

Kendine ne kadar güvendiğine bağlı olarak şu cevabı verirdim:

Bunu düzenli bir ifade ile yapmazdım. Normal ifadelerin uygun bir kullanımı değildir.


3
Normal ifadenin sınırlamalarını gerçekten anladığınızı göstermek için biraz daha açıklama yapacağınızı umuyorum. Basit cevabınız "şaşkına döndüm" olarak alınabilir.
Scott Wegner

Dolayısıyla verdiği bağımlı cümle.
Will Bickford

13

Evet , bunu .Net'te yapabilirsiniz!

(?<N>.)+.?(?<-N>\k<N>)+(?(N)(?!))

Buradan kontrol edebilirsiniz ! Harika bir gönderi!


1
.NET aromalı Regex'in tüm noktası, sonlu durumlu bir otomata olmadıkları için düzenli olmadıklarıdır; teorik anlamda gerçekten regex değiller.
kedi

12

StackOverflow gibi cevaplar doludur "hayır, bunu desteklemez? Düzenli ifadeleri. Onlar olamaz destekliyorum.".

Gerçek şu ki, normal ifadelerin artık normal gramerlerle ilgisi yok. Modern düzenli ifadeler, özyineleme ve dengeleme grupları gibi işlevler içerir ve uygulamalarının kullanılabilirliği giderek artmaktadır (örneğin, buradaki Ruby örneklerine bakın). Benim fikrime göre, alanımızdaki düzenli ifadelerin bir programlama kavramından başka bir şey olmadığı şeklindeki eski inanca bağlı kalmak, sadece ters etki yapar. Artık en uygun olmayan seçim kelimesi için onlardan nefret etmek yerine, bir şeyleri kabul etme ve devam etme zamanı.

İşte Perl'in yaratıcısı Larry Wall'dan bir alıntı :

(…) Genel olarak, gerçek düzenli ifadelerle yalnızca marjinal olarak ilişkili olan "düzenli ifadeler" dediğimiz şeylerle ilgili olmak zorunda. Yine de terim, kalıp eşleştirme motorlarımızın yetenekleriyle büyüdü, bu yüzden burada dilsel gereklilikle savaşmaya çalışmayacağım. Ancak ben bunlara genellikle "normal ifadeler" (veya Anglo-Sakson modundayken "regexen") diyeceğim.

Ve burada bir var blog yazısı ile PHP'nin çekirdek geliştiricilerinden biri :

Makale oldukça uzun olduğu için, işte ana noktaların bir özeti:

  • Programcılar tarafından kullanılan "düzenli ifadeler", biçimsel dil teorisi bağlamında orijinal düzenlilik kavramıyla çok az ortak noktaya sahiptir.
  • Normal ifadeler (en azından PCRE) bağlamdan bağımsız tüm dillerle eşleşebilir. Bu nedenle, iyi biçimlendirilmiş HTML ve hemen hemen tüm diğer programlama dilleriyle eşleşebilirler.
  • Normal ifadeler, en azından bazı bağlama duyarlı dillerle eşleşebilir.
  • Normal ifadelerin eşleştirilmesi NP tamamlandı. Bu nedenle, normal ifadeleri kullanarak diğer herhangi bir NP problemini çözebilirsiniz.

Bununla birlikte, palindromları bunu kullanarak normal ifadelerle eşleştirebilirsiniz:

^(?'letter'[a-z])+[a-z]?(?:\k'letter'(?'-letter'))+(?(letter)(?!))$

... belli ki normal gramerlerle ilgisi yok.
Daha fazla bilgi burada: http://www.regular-expressions.info/balancing.html


9

Birkaçının daha önce söylediği gibi, kutudan çıkan genel bir palindromu algılayacak tek bir normal ifade yoktur, ancak belirli bir uzunluğa kadar palindromları tespit etmek istiyorsanız, aşağıdaki gibi bir şey kullanabilirsiniz:

(.?)(.?)(.?)(.?)(.?).?\5\4\3\2\1


6

Ruby'de adlandırılmış yakalama gruplarını kullanabilirsiniz. yani böyle bir şey işe yarayacak -

def palindrome?(string)
  $1 if string =~ /\A(?<p>| \w | (?: (?<l>\w) \g<p> \k<l+0> ))\z/x
end

deneyin, işe yarıyor ...

1.9.2p290 :017 > palindrome?("racecar")
 => "racecar" 
1.9.2p290 :018 > palindrome?("kayak")
 => "kayak" 
1.9.2p290 :019 > palindrome?("woahitworks!")
 => nil 

1
Adlandırılmış yakalama grupları kesinlikle normal ifade değildir. willamette.edu/~fruehr/LLC/lab5.html
Steve Moser

2
Haklısın. Bu özellikle bu yüzden adlandırılmış yakalama grupları kullanmanız gerektiğini söyledim.
Taylor

Birisi şans eseri bu RE karakterini bir acemi için karakter karakter açıklayabilir mi? Aşağıdakilerin hepsini anlıyorum (virgül 'atomları' ayırır) /, \ A, (, |, \ w, |, (, (, \ w,),),), \ z, /, x ama bilmiyorum Bunlardan hiçbirini anlamadım mı? <p>,?:,? <l>, \ g <p>, \ k <l + 0> ve yardım için rubular.com kullanıyorum ve görünüşe göre RE'yi ( doğal olarak), ancak bu onu görmeme yardımcı olmuyor ve hatta "Tam bir Ruby düzenli ifade kılavuzu için, Kazmaya bakın." yardımcı olmuyor, çünkü 'Kazma' ile bağlantılı site anlayamadığım atomları açıklamıyor. Biliyorum ? Sıfır veya a ile bir eşleşmeyi TAKİP ETMEK, ama? bir karakterin önünde mi?
Kevin Ford denizaltı

Ah, adlandırılmış yakalama grupları ! Güzel. @SteveMoser artık kırık bir bağlantı, ancak başka bir bağlantı buldum . Onlardan bahsettiği için teşekkürler Taylor, aksi halde, neyin kastedildiği hakkında hiçbir fikrim olmazdı? <p> ve? <l> ve?: (Yakalama olmayan yakalama grubu) ve \ g <p> ve \ k <l + 0>. Hala neyi göremiyorum <p> | gerçi. Yapmaz | yani "veya"? RE'lerde boru için bu kullanımın belgelerini bulamıyorum. Bu çok güzel RE için ayrıntılı bir açıklama görmekten yine de mutluluk duyarım.
Denizaltı Kevin Ford

6

Bunu özyineleme kullanmadan da yapabilirsiniz:

\A(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2\z

tek bir karaktere izin vermek için:

\A(?:(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2|.)\z

Perl, PCRE ile çalışır

demo

Java için:

\A(?:(.)(?=.*?(\1\2\z|(?<!(?=\2\z).{0,1000})\1\z)))*?.?\2\z

demo


1
Bu bir normal ifade sorusuna çok ilginç bir cevaptır. Aslında bazı testlerimi geçen tek model . Bunun için teşekkürler Casimir :)
bobble bubble

1
@bobblebubble: Desteğiniz için teşekkürler. Gördüğünüz gibi, geçenlerde bu cevabı düzenledim çünkü önceki versiyon yanlıştı (üç yıldır ne yazık).
Casimir et Hippolyte

5

Normal ifadeler yerine dize manipülasyonu ile yapmak aslında daha kolaydır:

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

Bunun röportaj sorusuna gerçekten cevap vermediğini anlıyorum, ancak bunu bir görevi yerine getirmenin daha iyi bir yolunu nasıl bildiğinizi göstermek için kullanabilirsiniz ve her sorunu bir çivi olarak gören tipik "çekiçli" bir kişi değilsiniz . "


Bu yanıta oldukça düşkün olsam da, dizeyi görsel karakterlere düzgün bir şekilde ayırmak için BreakIterator'ı kullanarak ekstra puan kazanacağınızı düşünüyorum.
Trejkaz

5

İşte Regex Golf'ün 5. seviyesi (Bir adam, bir plan) için cevabım . Tarayıcının Normal İfadesi ile 7 karaktere kadar çalışır (Chrome 36.0.1985.143 kullanıyorum).

^(.)(.)(?:(.).?\3?)?\2\1$

İşte 9 karaktere kadar bir tane

^(.)(.)(?:(.)(?:(.).?\4?)?\3?)?\2\1$

Çalışacağı maksimum karakter sayısını artırmak için, tekrar tekrar değiştirirsiniz . ile (?: (.).? \ n?)? .


1
Bunu biraz daha az karakterle başardım, ^ (.) (.) (.)?.? \ 3 \ 2 \ 1 $
Ben Ellis

Beni
bozduğun

İnsanların geri kalanı neden 13'e sahipken bu 19
U11-İleri

5

Yinelemeli Normal İfadeler bunu yapabilir!

Palindrom içeren bir dizeyi tespit etmek için çok basit ve apaçık bir algoritma:

   (\w)(?:(?R)|\w?)\1

At rexegg.com/regex-recursion öğretici nasıl çalıştığını açıklar.


Herhangi bir dilde iyi çalışır, burada kavram kanıtı olarak aynı kaynaktan (bağlantı) uyarlanmış bir örnek, PHP kullanılarak:

$subjects=['dont','o','oo','kook','book','paper','kayak','okonoko','aaaaa','bbbb'];
$pattern='/(\w)(?:(?R)|\w?)\1/';
foreach ($subjects as $sub) {
  echo $sub." ".str_repeat('-',15-strlen($sub))."-> ";
  if (preg_match($pattern,$sub,$m)) 
      echo $m[0].(($m[0]==$sub)? "! a palindrome!\n": "\n");
  else 
      echo "sorry, no match\n";
}

çıktılar

dont ------------> sorry, no match
o ---------------> sorry, no match
oo --------------> oo! a palindrome!
kook ------------> kook! a palindrome!
book ------------> oo
paper -----------> pap
kayak -----------> kayak! a palindrome!
okonoko ---------> okonoko! a palindrome!
aaaaa -----------> aaaaa! a palindrome!
bbbb ------------> bbb

Karşılaştırma

Normal ifade ^((\w)(?:(?1)|\w?)\2)$ aynı işi yapar, ancak evet / değil yerine "içerir" olarak.
Not: "o" nun bir palimbrom olmadığı, "mümkün-elba" tireli biçimin bir palindrom olmadığı, ancak "mümkünelba" nın olduğu bir tanım kullanıyor. Tanımın adlandırılması 1 .
"O" ve "olası-elba" palindron olduğunda, adlandırma tanımı2 .

Başka bir "palindrom normal ifadeleri" ile karşılaştırıldığında,

  • ^((.)(?:(?1)|.?)\2)$yukarıdaki temel normal ifade, \wkısıtlama olmaksızın , "mümkün-elba" yı kabul eder.

  • ^((.)(?1)?\2|.)$( @LilDevil ) kullanımı definition2 ( "o" ve bu yüzden "aaaaa" ve "BBB" şeritlerinin tanınmasında da farklı "güçlü-elba" kabul eder).

  • ^((.)(?1)\2|.?)$( @Markus ) "kook" veya "bbbb" algılanmadı

  • ^((.)(?1)*\2|.?)$( @Csaba ) Tanım 2'yi kullan .


NOT: karşılaştırmak $subjectsiçin, karşılaştırılan her normal ifade için için daha fazla kelime ve bir satır ekleyebilirsiniz.

  if (preg_match('/^((.)(?:(?1)|.?)\2)$/',$sub)) echo " ...reg_base($sub)!\n";
  if (preg_match('/^((.)(?1)?\2|.)$/',$sub)) echo " ...reg2($sub)!\n";
  if (preg_match('/^((.)(?1)\2|.?)$/',$sub)) echo " ...reg3($sub)!\n";
  if (preg_match('/^((.)(?1)*\2|.?)$/',$sub)) echo " ...reg4($sub)!\n";

Bunu denedim ve görünüşe göre tüm palindromlarla eşleşti:^((.)(?:(?1)|.?)\2|(.)\3*)$
Hao Wu

4

PCRE ifadesi ile ilgili olarak (MizardX'ten):

/ ^((.)(?1)\2|.?)$/

Test ettin mi? Win XP Pro altında PHP 5.3'ümde şu hata veriyor: aaaba Aslında, ifade ifadesini okumak için biraz değiştirdim:

/ ^((.)(?1)*\2|.?)$/

Bence dışarıdaki karakter çifti tutturulmuşken, kalan iç karakterlerin değil. Bu tam bir cevap değildir çünkü "aaaba" ve "aabaacaa" 'dan yanlış bir şekilde geçerken, "aabaaca" da doğru şekilde başarısız olur.

Bunun için bir düzeltme olup olmadığını merak ediyorum ve ayrıca Perl örneği (JF Sebastian / Zsolt tarafından) testlerimi doğru bir şekilde geçiyor mu?

Viyana'dan Csaba Gabor



3

Perl'de (ayrıca Zsolt Botykai'nin cevabına bakınız ):

$re = qr/
  .                 # single letter is a palindrome
  |
  (.)               # first letter
  (??{ $re })??     # apply recursivly (not interpolated yet)
  \1                # last letter
/x;

while(<>) {
    chomp;
    say if /^$re$/; # print palindromes
}

3

Bu normal ifade, boşlukları, sekmeleri, virgülleri ve tırnakları yok sayarak 22 karaktere kadar palindromları algılar.

\b(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*\11?[ \t,'"]*\10|\10?)[ \t,'"]*\9|\9?)[ \t,'"]*\8|\8?)[ \t,'"]*\7|\7?)[ \t,'"]*\6|\6?)[ \t,'"]*\5|\5?)[ \t,'"]*\4|\4?)[ \t,'"]*\3|\3?)[ \t,'"]*\2|\2?))?[ \t,'"]*\1\b

Onunla burada oynayın: https://regexr.com/4tmui


2

ZCHudson'un belirttiği gibi, palindrom kümesi normal bir dil olmadığından, bir şeyin palindrom olup olmadığını belirlemek, normal bir regexp ile yapılamaz.

Airsource Ltd'ye , görüşmecinin aradığı türden bir cevap "bu mümkün değil" olduğunu söylediğinde kesinlikle katılmıyorum . Görüşmem sırasında, iyi bir adayla karşılaştığımda, ona yanlış bir şey yapmasını önerdiğimizde doğru argümanı bulup bulamayacağını kontrol etmek için bu tür bir soruya geliyorum. Daha iyisini biliyorsa, bir şeyi yanlış şekilde yapmaya çalışacak birini işe almak istemiyorum.



2

Görüşmeciye, palindromlardan oluşan dilin normal bir dil olmadığını, bunun yerine bağlamdan bağımsız olduğunu açıklardım.

Tüm palindromlarla eşleşen normal ifade sonsuz olacaktır . Bunun yerine, kendisini kabul etmek için maksimum boyutta palindromla sınırlamasını öneririm; veya tüm palindromlara ihtiyaç duyuluyorsa, minimum bir tür NDPA kullanın veya sadece basit dizi ters çevirme / eşittir tekniğini kullanın.


2

Yakalama grupları tükenmeden önce normal ifadelerle yapabileceğiniz en iyi şey:

/(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1/

Bu, uzunluğu 19 karaktere kadar olan tüm palindromlarla eşleşecektir.

Tüm uzunluklar için programlı çözümleme önemsizdir:

str == str.reverse ? true : false

Normal ifadeniz çalışmıyor. Örneğin, "abac" ın bir eşleşme olduğunu gösterecektir ...
Darwin Airola

2

Henüz satır içi yorum yapacak temsilcim yok, ancak MizardX tarafından sağlanan ve Csaba tarafından değiştirilen normal ifade, PCRE'de çalışması için daha fazla değiştirilebilir. Bulduğum tek hata, tek karakterli dizedir, ancak bunu ayrı ayrı test edebilirim.

/^((.)(?1)?\2|.)$/

Başka dizelerde başarısız olmasını sağlayabilirseniz, lütfen yorum yapın.


2
#!/usr/bin/perl

use strict;
use warnings;

print "Enter your string: ";
chop(my $a = scalar(<STDIN>));    
my $m = (length($a)+1)/2;
if( (length($a) % 2 != 0 ) or length($a) > 1 ) { 
  my $r; 
  foreach (0 ..($m - 2)){
    $r .= "(.)";
  }
  $r .= ".?";
  foreach ( my $i = ($m-1); $i > 0; $i-- ) { 
    $r .= "\\$i";
  } 
  if ( $a =~ /(.)(.).\2\1/ ){
    print "$a is a palindrome\n";
  }
  else {
    print "$a not a palindrome\n";
 }
exit(1);
}
print "$a not a palindrome\n";

2

Otomata teorisine göre, herhangi bir uzunluktaki bir paliandromu eşleştirmek imkansızdır (çünkü bu sonsuz miktarda bellek gerektirir). Ancak, Sabit Uzunluktaki Paliandromes ile eşleşmesi MÜMKÜN. <= 5 veya <= 6 vb. Uzunluktaki tüm paliandromlarla eşleşen ancak üst sınırın net olmadığı> = 5 vb. İle eşleşmeyen bir normal ifade yazmanın mümkün olduğunu söyleyin


2

Ruby'de, \b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\bpalindrome sözcüklerini eşleştirmek için kullanabilirsiniz a, dad, radar, racecar, and redivider. ps: bu normal ifade yalnızca tek sayıda harf uzunluğunda olan palindrome kelimeleriyle eşleşir.

Bu normal ifadenin radarla nasıl eşleştiğini görelim. Kelime sınırı \ b dizenin başında eşleşir. Normal ifade motoru, yakalama grubu "word" e girer. [az], daha sonra yakalama grubu "harf" için yığında sıfır özyineleme seviyesinde saklanan r ile eşleşir. Şimdi normal ifade motoru "kelime" grubunun ilk özyinelemesine girer. (? 'mektup' [az]), birinci özyineleme düzeyinde a ile eşleşir ve yakalar. Normal ifade, "kelime" grubunun ikinci yinelemesine girer. (? 'mektup' [az]) ikinci özyineleme düzeyinde d'yi yakalar. Sonraki iki özyineleme sırasında, grup üçüncü ve dördüncü seviyelerde a ve r yakalar. Beşinci özyineleme başarısız olur çünkü dizede [az] ile eşleşecek karakter kalmamıştır. Normal ifade motoru geri dönmelidir.

Normal ifade motoru şimdi "kelime" grubu içindeki ikinci alternatifi denemelidir. Normal ifadedeki ikinci [az], dizedeki son r ile eşleşir. Motor şimdi başarılı bir özyinelemeden çıkar ve bir seviye geri üçüncü özyinelemeye gider.

Eşleştirmeden (& word) sonra motor \ k'letter + 0'a ulaşır. Normal ifade motoru zaten konu dizesinin sonuna ulaştığı için geri başvuru başarısız olur. Böylece bir kez daha geri adım atıyor. İkinci alternatif artık a ile eşleşiyor. Normal ifade motoru üçüncü özyinelemeden çıkar.

Normal ifade motoru tekrar eşleşti (& word) ve geri başvuruyu tekrar denemesi gerekiyor. Geri referans +0 veya mevcut özyineleme seviyesini belirtir, bu 2'dir. Bu seviyede, yakalama grubu d ile eşleşti. Dizedeki sonraki karakter r olduğundan geri referans başarısız olur. Tekrar geri dönüş, ikinci alternatif eşleşir d.

Şimdi \ k'letter + 0 'dizedeki ikinci a ile eşleşiyor. Bunun nedeni, normal ifade motorunun, yakalama grubunun ilk a ile eşleştiği ilk özyinelemeye geri dönmesidir. Normal ifade motoru ilk özyinelemeden çıkar.

Normal ifade motoru artık tüm özyinelemenin dışında kaldı. Bu seviyede, yakalama grubu r depolanır. Geri referans artık dizedeki son r ile eşleşebilir. Motor artık herhangi bir özyineleme içinde olmadığından, gruptan sonra normal ifadenin geri kalanıyla devam eder. \ b dizenin sonunda eşleşir. Normal ifadenin sonuna ulaşılır ve genel eşleşme olarak radar döndürülür.


2

burada verilen dizenin palindrome olup olmadığını normal ifadeler kullanıp kullanmadığını söyleyen PL / SQL kodu:

create or replace procedure palin_test(palin in varchar2) is
 tmp varchar2(100);
 i number := 0;
 BEGIN
 tmp := palin;
 for i in 1 .. length(palin)/2 loop
  if length(tmp) > 1 then  
    if regexp_like(tmp,'^(^.).*(\1)$') = true then 
      tmp := substr(palin,i+1,length(tmp)-2);
    else 
      dbms_output.put_line('not a palindrome');
      exit;
    end if;
  end if;  
  if i >= length(palin)/2 then 
   dbms_output.put_line('Yes ! it is a palindrome');
  end if;
 end loop;  
end palin_test;

2
my $pal='malayalam';

while($pal=~/((.)(.*)\2)/){                                 #checking palindrome word
    $pal=$3;
}
if ($pal=~/^.?$/i){                                         #matches single letter or no letter
    print"palindrome\n";
}
else{
    print"not palindrome\n";
}

3
Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek bağlam sağlamak, yanıtlayanın uzun vadeli değerini artıracaktır.
Donald Duck

0

Sözde kodda Airsource Ltd'nin yönteminde ufak bir iyileştirme:

WHILE string.length > 1
    IF /(.)(.*)\1/ matches string
        string = \2
    ELSE
        REJECT
ACCEPT
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.