Solusi Lain
Menurut saya ini adalah salah satu masalah paling menarik di situs ini. Saya perlu berterima kasih pada deadcode karena menabraknya kembali ke atas.
^((^|xx)(^|\3\4\4)(^|\4x{12})(^x|\1))*$
39 byte , tanpa persyaratan atau pernyataan ... semacam. Alternatifnya, seperti yang sedang digunakan ( ^|), adalah jenis kondisional dalam suatu cara, untuk memilih antara "iterasi pertama," dan "bukan iterasi pertama."
Regex ini dapat dilihat berfungsi di sini: http://regex101.com/r/qA5pK3/1
Baik PCRE dan Python menginterpretasikan regex dengan benar, dan itu juga telah diuji dalam Perl hingga n = 128 , termasuk n 4 -1 , dan n 4 +1 .
Definisi
Teknik umum adalah sama seperti pada solusi lain sudah diposting: menentukan ekspresi diri-referensi yang pada setiap iterasi berikutnya sesuai panjang yang sama dengan istilah berikutnya fungsi perbedaan maju, D f , dengan quantifier terbatas ( *). Definisi formal fungsi perbedaan maju:

Selain itu, fungsi perbedaan urutan yang lebih tinggi juga dapat didefinisikan:

Atau, lebih umum:

Fungsi perbedaan maju memiliki banyak sifat menarik; itu adalah urutan apa turunannya untuk fungsi kontinu. Misalnya, D f dari n th rangka polinomial akan selalu menjadi n-1 th rangka polinomial, dan untuk setiap i , jika D f i = D f i + 1 , maka fungsi f adalah eksponensial, dalam banyak cara yang sama bahwa turunan dari e x sama dengan dirinya sendiri. Fungsi diskrit paling sederhana di mana f = D f adalah 2 n .
f (n) = n 2
Sebelum kita memeriksa solusi di atas, mari kita mulai dengan sesuatu yang sedikit lebih mudah: regex yang cocok dengan string yang panjangnya adalah kuadrat sempurna. Meneliti fungsi perbedaan maju:

Artinya, iterasi pertama harus cocok dengan string dengan panjang 1 , yang kedua string dengan panjang 3 , yang ketiga string dengan panjang 5 , dll., Dan secara umum, setiap iterasi harus cocok dengan string yang dua lebih panjang dari sebelumnya. Regex yang sesuai mengikuti hampir secara langsung dari pernyataan ini:
^(^x|\1xx)*$
Dapat dilihat bahwa iterasi pertama hanya akan cocok dengan satu x, dan setiap iterasi berikutnya akan cocok dengan string dua lebih lama dari sebelumnya, persis seperti yang ditentukan. Ini juga menyiratkan tes kuadrat sempurna pendek luar biasa di perl:
(1x$_)=~/^(^1|11\1)*$/
Regex ini dapat digeneralisasikan lebih lanjut untuk mencocokkan dengan panjang n- gonal:
Angka segitiga:
^(^x|\1x{1})*$
Angka kuadrat:
^(^x|\1x{2})*$
Angka pentagonal:
^(^x|\1x{3})*$
Angka heksagonal:
^(^x|\1x{4})*$
dll.
f (n) = n 3
Pindah ke n 3 , sekali lagi memeriksa fungsi perbedaan maju:

Mungkin tidak segera jelas cara mengimplementasikan ini, jadi kami memeriksa fungsi perbedaan kedua juga:

Jadi, fungsi perbedaan ke depan tidak meningkat dengan nilai konstan, melainkan nilai linier. Itu bagus bahwa ( 'awal -1 th') nilai D f 2 adalah nol, yang menyimpan sebuah inisialisasi pada iterasi kedua. Regex yang dihasilkan adalah sebagai berikut:
^((^|\2x{6})(^x|\1))*$
Iterasi pertama akan cocok dengan 1 , seperti sebelumnya, yang kedua akan cocok dengan string 6 lebih panjang ( 7 ), yang ketiga akan cocok dengan string 12 lebih lama ( 19 ), dll.
f (n) = n 4
Fungsi perbedaan maju untuk n 4 :

Fungsi perbedaan maju kedua:

Fungsi perbedaan maju ketiga:

Nah, itu jelek. Nilai awal untuk D f 2 dan D f 3 keduanya bukan nol, 2 dan 12 masing-masing, yang perlu dipertanggungjawabkan. Anda mungkin sudah tahu sekarang bahwa regex akan mengikuti pola ini:
^((^|\2\3{b})(^|\3x{a})(^x|\1))*$
Karena D f 3 harus sesuai panjang 12 pada iterasi kedua, sebuah niscaya 12 . Tetapi karena ia bertambah 24 setiap istilah, sarang yang lebih dalam berikutnya harus menggunakan nilai sebelumnya dua kali, menyiratkan b = 2 . Hal terakhir yang perlu dilakukan adalah menginisialisasi D f 2 . Karena D f 2 pengaruh D f langsung, yang pada akhirnya apa yang kita ingin mencocokkan, nilainya dapat diinisialisasi dengan menyisipkan atom yang tepat langsung ke regex, dalam hal ini (^|xx). Regex terakhir kemudian menjadi:
^((^|xx)(^|\3\4{2})(^|\4x{12})(^x|\1))*$
Pesanan Tinggi
Polinomial urutan kelima dapat dicocokkan dengan regex berikut:
^((^|\2\3{c})(^|\3\4{b})(^|\4x{a})(^x|\1))*$
f (n) = n 5 adalah latihan yang cukup mudah, karena nilai awal untuk fungsi perbedaan maju kedua dan keempat adalah nol:
^((^|\2\3)(^|\3\4{4})(^|\4x{30})(^x|\1))*$
Untuk enam polinomial pesanan:
^((^|\2\3{d})(^|\3\4{c})(^|\4\5{b})(^|\5x{a})(^x|\1))*$
Untuk polinomial urutan ketujuh:
^((^|\2\3{e})(^|\3\4{d})(^|\4\5{c})(^|\5\6{b})(^|\6x{a})(^x|\1))*$
dll.
Perhatikan bahwa tidak semua polinomial dapat dicocokkan dengan cara ini, jika salah satu koefisien yang diperlukan adalah non-integer. Sebagai contoh, n 6 mensyaratkan bahwa a = 60 , b = 8 , dan c = 3/2 . Ini dapat diatasi, dalam hal ini:
^((^|xx)(^|\3\6\7{2})(^|\4\5)(^|\5\6{2})(^|\6\7{6})(^|\7x{60})(^x|\1))*$
Di sini saya telah mengubah b menjadi 6 , dan c menjadi 2 , yang memiliki produk yang sama dengan nilai yang dinyatakan di atas. Sangat penting bahwa produk tidak berubah, karena a · b · c · ... mengontrol fungsi perbedaan konstan, yang untuk polinomial urutan keenam adalah D f 6 . Ada dua atom inisialisasi hadir: satu untuk menginisialisasi D f ke 2 , seperti dengan n 4 , dan yang lainnya untuk menginisialisasi fungsi perbedaan kelima menjadi 360 , sementara pada saat yang sama menambahkan dua yang hilang dari b .