Retina , 66 63 45 43 36 bayt
^()(\1(?<1>.\1))+(\1(.(?(4).\4)))*$
Retina isminin başlığına rağmen, bu sadece Loeschian sayılarının sıradışı temsilini kabul eden basit bir .NET regex .
999 ve 1000 girişleri bir saniyenin altında bir sürede başarılı.
Çevrimiçi deneyin! (İlk satır, satır besleme ile ayrılmış bir test takımını etkinleştirir ve sonraki iki kolaylık sağlamak için birliğe dönüşmeye özen gösterir.)
açıklama
Çözüm, girdinin hem i*i + j*(i + j)olumlu ihem de olumsuz olmayanlar için yazılabileceği sınıflamasına dayanmaktadır j(çünkü girdiyi tutmak zorunda değiliz 0) ve bu n*nsadece ilk ntek tamsayıların toplamıdır . Golf oynamak, ileriye dönük referanslarda ilginç bir egzersizdi.
Bir "ileri referans", başvurduğu grubun içine bir geri referans yerleştirdiğiniz zamandır. Elbette, grup ilk kez kullanıldığında işe yaramaz, çünkü henüz geri dönülecek bir şey yoktur, ancak bunu bir döngüye koyarsanız, geri dönüş her seferinde önceki yinelemenin yakalanmasını sağlar. Bu da, her yineleme ile daha büyük bir yakalamanızı sağlar. Bu, üçgen sayılar, kareler ve Fibonacci sayıları gibi şeyler için çok kompakt desenler oluşturmak için kullanılabilir.
Örnek olarak, karelerin sadece ilk ngarip tam sayıların toplamı olduğu gerçeğini kullanarak şöyle bir kare girişini eşleştirebiliriz:
(^.|..\1)+$
İlk tekrarda, ..\1çalışamaz, çünkü \1henüz bir değeri yok. Böylece ^.gruba tek bir karakter çekerek başlıyoruz 1. Sonraki yinelemelerde, ^.çapa nedeniyle artık eşleşme olmaz, ancak şimdi ..\1geçerlidir. Önceki yinelemeden iki karakter daha eşleşir ve yakalamayı günceller. Bu şekilde, her bir yinelemeden sonra bir kare alarak, artan tek sayıları eşleştiriyoruz.
Şimdi ne yazık ki, bu tekniği olduğu gibi kullanamıyoruz. Eşleştirdikten sonra i*i, onu da çarpmamız için iiyi yapmamız gerekir j. Bunu yapmanın basit (ama uzun) bir yolu, eşleştirmenin yinelemeler i*ialması gerçeğini kullanmak i, böylece igruptaki şeyleri yakaladık 1. Şimdi bunu çıkarmak için dengeleme gruplarını kullanabiliriz i, ancak dediğim gibi pahalı.
Bunun yerine, isonunda bir yakalama grubunda da ortaya çıkan “ardışık tuhaf tam sayıların toplamını” yazmanın farklı bir yolunu buldum . Tabii ki itek sayı sadece 2i-1. Bu bize ileri referansı her bir yinelemede sadece 1 arttırmak için bir yol sunar. Bu kısım:
^()(\1(?<1>.\1))+
Bu ()sadece boş bir yakalamayı gruba iter 1(başlangıç iolarak 0). Bu, ^.|yukarıdaki basit çözümde hemen hemen eşdeğerdir , ancak |bu durumda kullanmak biraz zor olabilir.
O zaman ana döngümüz var (\1(?<1>.\1)). \1Bir önceki maçları i, (?<1>.\1)sonra grup günceller 1ile i+1. Açısından yeni i , sadece eşleştirdiğimizde 2i-1karakterleri. Tam olarak ihtiyacımız olan şey.
İşimiz bittiğinde, bir kareyi eşleştirdik i*ive grup 1hala ikarakter tutuyor .
İkinci kısım yukarıda gösterdiğim basit kare eşleşmesine daha yakın. Şimdilik geri tepkisini görmezden gelelim 1:
(.(?(4).\1))*
Bu temelde aynıdır (^.|..\4)*, ancak faydalanamayız ^çünkü ipin başında değiliz. Bunun yerine, .\1yalnızca grubu kullandığımız zaman ek eşleştirmek için bir koşullu kullanırız 4. Ama aslında bu tamamen aynı. Bu bize veriyor j*j.
Eksik olan tek şey j*iterimdir. Bunu j*j, j*jhesaplamanın hala jyinelemeler alması gerçeğinden yararlanarak birleştiriyoruz . Yani her yineleme için biz de imleci ilerletmek iile \1. Bunu sadece gruba yazmamaya dikkat etmemiz gerekiyor 4, çünkü bu ardışık tuhaf rakamlarla eşleşir. İşte bu şekilde:
(\1(.(?(4).\1)))*