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).
- Değişmez, karakter aralıkları (
- Ş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\1
Yakalanan 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.
^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)