9 katları için normal ifade


14

9'un katlarını tanıyan sonlu durum makinesini tanımlamak kolaydır: rakam toplamını (mod 9) takip edin ve daha sonra kabul edilen rakamı ekleyin. Böyle bir FSM'nin sadece 9 durumu vardır, çok basit! FSM tarafından tanınabilirlik ve normal diller arasındaki denklikle, 9'un katları için düzenli bir ifade vardır. Ancak, bu tür düzenli ifadeler muhtemelen ... çok ... uzun. İçinde olduğu gibi, muhtemelen bir gigabayt civarında.

Https://www.quaxio.com/triple/ adresinde 3'ün katları için çalışılmış bir örnek var. Normal ifade için FSM.

Meydan okuma:

9'un katlarını tespit etmek için bir normal ifade yapmanız gerekir. Böyle bir normal ifadenin çok uzun olması beklendiğinden, normal ifadenizi yazdırabilecek bir program sağlamanızı rica ediyorum. (Eğer gerçekten bütün bir normal ifade vermek istiyorsanız, belki de başka bir yerde barındırın ve buraya bağlayın!)

Bize programınızın çıktısının tam karakter sayısını söyleyebilmeniz gerekir - bu nedenle, yeterince hızlı çalışmadıkça, tüm regex'leri belirli bir uzunluğa kadar çalıştıran bir programa sahip olmak, mümkün olduğunca hızlı çalışmadıkça kabul edilemez. tamamlamak için çalıştırın ve bize sonuçta normal regex uzunluğu verin!

Puanlar, elbette program uzunluğuna bağlı olarak değil, en kısa çıktı normaline sahip olmak içindir. Normal ifade istediğim "program" olduğundan ve burada rahatça iletmek için çok uzun olduğu için hala bu kod golfünü etiketliyorum.

Kurallar:

  • Giriş yalnızca eşleşen karakterleri içerecektir [0-9]*.
  • Normal ifadeniz 9'un katlarıyla eşleşmelidir , ancak başka hiçbir şeyle eşleşmemelidir . Tamamen 0-9 arasındaki rakamlardan yapılmayan ve geçersiz giriş olan durumlar, istediğiniz şekilde eşleşebilir veya başarısız olabilir.
  • Bir DFA tarafından kolayca tanınması motivasyonu göz önüne alındığında, ortaya çıkan normal ifade , daha teorik terminolojide, yani sadece normal dillerin kapalı olduğu operatörlerde düzenli ifade olmalıdır . Kesin olmak gerekirse, izin verilen tek şey:
    • Değişmez, karakter aralıkları ( [ab], [a-f], [^k]), Kleene yıldızlı ( *), tespit ( ^ve $), parantez ile, sırayla değişen (gruplama |), isteğe bağlı şartlar ( ?), bir ya da daha fazla terim ( +), lookaheads ( (?=)), negatif lookaheads ( (?!)), lookbehinds ( (?<=)), negatif lookbehinds ( (?<!)), koşullu ( https://www.regular-expressions.info/conditional.html - gibi (?(?=test)then|else)) ve sınırlı uzunlukta arka referanslar (aşağıya bakın).
  • Şeylerin örnekleri değil izin:
    • Keyfi uzunluk, ileri referanslar, Özyineleme, alt yordamlar, döngü yapıları, yürütülebilir kod, herhangi bir 'eval' varyasyonu veya dizeyi aritmetik bir değere dökmek için yerleşik yapıların arka referansları.
  • Sınırlı uzunlukta bir bağlama dizesine sahip olduğu gösterilebilen geri bildirimler, sonlu halde saklanabildikleri ve dilin düzenliliğini değiştirmedikleri için kabul edilebilir. Örneğin (..2.[3-5])4\1.\1, yakalama grubunda bağlı uzunluk olduğu için normal ifade kabul edilebilir \1. Bu düzenli bir yapıdır. (2*)0\1Yakalanan grup sonlu halde saklanamayacağı için böyle bir yapı kabul edilemez.
  • Normal ifadeniz, istediğiniz gibi sıfırdan büyük sıfırlarla tamsayıları kabul veya reddetmekte özgürdür. Ancak, dize "0"kabul edilmelidir.

2
İlgili , bunun bir kopya olarak kabul edilip edilmeyeceğinden emin değilim
ASCII-sadece

Ah, hmm! Ben "regex çoklu" için arama vardı ama "regex bölünebilir" değil. Sanırım bu çok benzer, evet.
Alex Meiburg

11
Henüz söylenmedi, bu yüzden PPCG ve ilginç ilk meydan okuma hoş geldiniz! Başka bir kullanıcı tarafından belirtildiği gibi, genellikle yayınlamadan önce geri bildirim alabilmeleri için Sandbox'ta meydan okuma önerileri göndermeleri önerilir, ancak zorunlu değildir . Ancak, bu iyi düşünülmüş ve açık bir meydan okumadır, bu yüzden bunu Sandbox'a taşımak için bir neden yoktur. Topluluğumuzun tadını çıkarmanızı umuyoruz!
caird coinheringaahing

200'den az kibibitten daha az çözüm mümkündür, bu yüzden çok büyük olmayacak
Ton Hospel

3
.NET'in uzantılarını kullanarak çözüm:^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)
Neil

Yanıtlar:


3

Haskell , 207.535 202.073 bayt

5462 bayt kullanarak kaydedilen 0|9yerine [09]mümkünse.

digits n
  | x == 0    = "0|9"
  | otherwise = show x
  where x = mod n 9

regex 0 = "[09]*"
regex n = (regex' n (-1) (-1)) ++ "*"

regex' 0 start end = digits (end - start)
regex' n start end = '(':(regex' 0 start end) ++ (concat ['|':(regex' (n-x) (start-x) (-1)) ++ (regex (n-x))
                                                  ++ (regex' (n-x) (-1) (end-x)) | x <- [1..n]]) ++ ")"

main = do
  putStr ("^" ++ (regex 8) ++ "$")

Çevrimiçi deneyin!

İşleri başlatmak için bağlantılı makalenin dipnotlarında verilen normal ifadenin hızlı bir uyarlaması.

Herman Lauenstein'ın izniyle çıktı regex'in pastebin .

Tam regex'i test edemesem de, bölünebilirliği 3 ile kontrol etmek için programı değiştirmek, bunun üzerine dayalı regex'e tam olarak eşdeğer bir şey verir. Ayrıca, rakamın bölünebilirliğini 4 veya 5 ile kontrol etmek için programı değiştirmek de test ettiğim sayılar üzerinde çalışıyor gibi görünüyor.


Ayrıca yönteminizin bölünebilirlik için ne verdiğini 2 ile (benzer bir şey olmalı /even$/) ve bölünebilirlik 5 ile (benzer bir şey olmalıdır) test edebilirsiniz /[05]$/. Not: Kodunuzun dilini
belirtin

İşte çıktı ile bir macun ( binlerce bayt kurtarmak için tüm oluşumları ile ([09]|değiştirilir (0|9|)
Herman L
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.