APL (158 karakter, skor = 4)
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
Saya menggunakan Dyalog APL di sini. Jumlah siklus dapat ditingkatkan satu dengan menambahkan 0
(0 diikuti oleh spasi) ke akhir ekspresi dan ke akhir string (sebelum '''
). Panjang siklusnya (# 0's) + 1
, dan panjang ekspresi itu 150 + 4*(cycle length))
. Dengan asumsi kami terus menambahkan nol selamanya, nilainya adalah Limit[(150 + 4*n)/(n - 1), n -> Infinity] = 4
, di mana n
panjang siklusnya.
Berikut ini contoh dengan panjang siklus = 6:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
192 karakter, skor = 2
'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺ ⋄ a←⊃2⌷⍺ ⋄ ⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺⋄a←⊃2⌷⍺⋄⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01
Bergantung pada implementasinya, satu titik kegagalan bisa terjadi ketika bilangan bulat diawali ke string terlalu besar. Secara teoritis, kita dapat menambahkan siklus dengan menambahkan dua karakter - a 1
di akhir string (sebelum '''
) dan a 1
di akhir seluruh baris.
200 karakter, skor = 1
'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}91
Implementasi APL saya tidak memiliki integer presisi tak terbatas secara default, jadi integer dikonversi menjadi float ketika menjadi terlalu besar, menyebabkan output salah. Jadi yang ini adalah yang paling rewel, tetapi secara teoritis (baik dengan tangan atau dengan penerjemah APL yang berbeda), harus memiliki skor 1. Cukup tambahkan a 1
ke akhir ekspresi, dan Anda mendapatkan siklus lain.
Ikhtisar (dengan quine yang lebih pendek)
Saya akan memberikan gambaran tentang versi pertama, karena saya pikir itu mungkin yang paling mudah untuk dipahami. Namun, sebelum menangani versi itu, kami akan mempertimbangkan quine sederhana di APL :
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
Saya telah menemukan bahwa salah satu cara terbaik untuk memahami beberapa ekspresi APL adalah dengan melihat output di seluruh kaskade operator / fungsi. Semua operator dan fungsi dalam APL bersifat asosiatif-kanan dan memiliki prioritas yang sama, jadi inilah, dari kanan ke kiri:
'''1⌽22⍴11⍴'''
: Ini hanya string literal (daftar karakter). ''
adalah cara APL untuk keluar dari tanda kutip tunggal. Output: '1⌽22⍴11⍴'
.
11⍴'''1⌽22⍴11⍴'''
: Di sini, kami membentuk kembali ( ⍴
) string menjadi panjang 11
. Karena panjang string di bawah 11, maka string diulangi (yaitu, 5⍴'abc'
akan menghasilkan 'abcab'
). Output: '1⌽22⍴11⍴''
. Jadi kita sekarang memiliki dua tanda kutip di akhir - kita mendapatkan suatu tempat!
22⍴11⍴'''1⌽22⍴11⍴'''
: Demikian pula, kami sekarang membentuk ulang output kami sebelumnya menjadi panjang 22
. Output: '1⌽22⍴11⍴'''1⌽22⍴11⍴''
. Kita hampir sampai - kita hanya perlu memindahkan kutipan tunggal ke akhir.
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
: Di sini, kami memutar ( ⌽
) daftar karakter berdasarkan 1
. Ini memindahkan karakter pertama dari string ke akhir. Sebagai contoh lain, 2⌽'abcdef'
kembali 'cdefab'
. Output: 1⌽22⍴11⍴'''1⌽22⍴11⍴'''
.
Rotating quine
Quine pendek itu adalah dasar utama quine berputar kami. Sekarang, dengan itu dalam pikiran, mari kita lihat quine kami:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
{ ... }
mendefinisikan fungsi yang tidak disebutkan namanya, di mana kita akan melakukan pekerjaan. Perhatikan bahwa fungsi dalam APL mengambil argumen kanan, dilambangkan dengan ⍵
, dan argumen kiri opsional, dilambangkan dengan ⍺
(think infix). Kami ingin memberi makan fungsi ini baik string quine kami dan sesuatu untuk membantu kami dalam menciptakan jumlah siklus yang sewenang-wenang. Untuk membuat segalanya lebih mudah pada diri kita sendiri (dan siapa pun yang ingin menambahkan siklus), kita menjadikan string quine argumen kiri. Maka argumen yang benar adalah di mana kita menempatkan daftar siklus kita. 2 atau lebih item yang dipisahkan oleh spasi membuat daftar, jadi dalam contoh ini, kami memiliki daftar 2 elemen yang terdiri dari a 1
dan a 0
.
Kita dapat melihat bahwa fungsinya mirip dengan quine dari sebelumnya. Kami memiliki ...⌽...⍴...⍴...
bentuk yang sama dari sebelumnya. Jadi itu bagus - kita setidaknya mengerti itu! Mari kita mempelajari lebih dalam elips, dimulai dengan semuanya setelah yang terakhir ⍴
: ⊃,/(~^/¨⍺=0)/⍺
.
- Seperti yang dapat Anda lihat dengan melihat contoh di atas, kami mengawali string dengan angka 0 dari sisi kanan, menambahkan satu dengan setiap iterasi; tapi kami tidak peduli dengan itu sekarang. Kami hanya ingin senarnya!
- Pertama, pertimbangkan apa yang ada di dalam tanda kurung. (Ngomong-ngomong, mereka dikelompokkan seperti kebanyakan bahasa lain.)
⍺=0
mengembalikan daftar, dalam hal ini, dengan bentuk yang sama dengan ⍺
, di mana setiap elemen ⍺
digantikan oleh 1
jika sama dengan 0
, dan 0
sebaliknya. Ini dilakukan secara rekursif; jadi jika kita memiliki daftar daftar daftar karakter, masing-masing karakter akan diuji terhadap 0, dan Anda akan mendapatkan kembali daftar daftar daftar nilai-nilai biner.
- Jadi jika
⍺
hanya terdiri dari string kami, kami mendapatkan kembali daftar 0. Kalau tidak, argumen kiri kami memiliki beberapa 0 yang diawali untuk itu (misalnya, 0 0 0 'quinestring'
), jadi itu adalah daftar yang terdiri dari 0 dan daftar lain, string kami. Maka output kami terlihat seperti 1 1 1 <sub-list of zeros>
.
^/¨⍺=0
: Kami menerapkan fungsi turunan ^/
, yang mengurangi ( /
) menggunakan fungsi logis AND ( ^
), untuk setiap ¨
elemen ( ) dari ⍺=0
. Ini untuk meratakan sub-daftar nol sehingga kita dapat menganggap string quine sebagai satu nilai biner. Mempertimbangkan contoh sebelumnya, hasilnya adalah 1 1 1 0
.
~
: Kami biner TIDAK masing-masing nilai dari sebelumnya (misalnya, kembali 0 0 0 1
).
(~^/¨⍺=0)/⍺
: Untuk setiap elemen dalam ⍺
, kami mereplikasi ( /
) jumlah kali yang diberikan oleh elemen yang sesuai dalam argumen kiri. Ini menghilangkan semua 0, meninggalkan kita hanya dengan string quine kita.
⊃,/
adalah beberapa dokumen yang diperlukan untuk memastikan bahwa kami mendapatkan kembali daftar karakter yang rata, dengan mengurangi hasilnya dengan fungsi gabungan ( ,
). Jika input sudah daftar rata (yaitu, argumen kiri ke fungsi utama kami hanya string), kami mendapatkan daftar 1-elemen yang berisi daftar itu. Dalam kasus lain, ketika kita memiliki daftar yang terdiri dari sub-daftar untuk string, kita mendapatkan hal yang sama kembali (daftar dengan sub-daftar). Kami kemudian membongkar ini ( ⊃
), memberi kami hanya elemen pertama dari daftar (yaitu, sub-daftar karakter). Ini mungkin tampak tidak perlu, tetapi jika tidak kita akan mencoba untuk membentuk kembali daftar 1-elemen!
Selanjutnya, kita melihat panjang yang diberikan untuk membentuk kembali pertama, dalam tanda kurung:
⍺,⍵
: Kami menggabungkan argumen yang benar dengan argumen pertama
⊃,/⍺,⍵
: Sama seperti sebelumnya - ratakan daftar.
+/0=⊃,/⍺,⍵
: Tambahkan jumlah nol dalam daftar dengan mengurangi ( /
) menggunakan fungsi penambahan ( +
).
2×+/0=⊃,/⍺,⍵
: Kalikan angka itu dengan dua.
z←2×+/0=⊃,/⍺,⍵
: Tetapkan ( ←
) hasilnya ke variabel z
,. Untuk rekap, z
sekarang dua kali jumlah nol yang ditemukan di argumen kiri dan kanan.
77+z←2×+/0=⊃,/⍺,⍵
: Kami kemudian menambahkan 77
, untuk karakter dalam string quine, mengabaikan semuanya setelah spasi berikut 1
. Seperti pada contoh quine awal, kami menambahkan 1 pada panjang string untuk mendapatkan satu kutipan lagi.
- Output dari pembentukan kembali ini, dalam contoh ini, adalah:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Argumen untuk membentuk kembali yang berikut adalah sederhana dan mencerminkan quine pendek (2 kali panjang untuk membentuk kembali pertama). Output kami sekarang adalah:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Sekarang untuk langkah terakhir, di mana kami menghitung berapa banyak untuk memutar string output:
- Seperti yang Anda lihat dengan melihat output sebelumnya, kami ingin memutarnya kembali (jumlah negatif) untuk membawa 2 kutipan terakhir ke awal. Karena kami ingin
0
(dan ruang lain) untuk pindah ke awal juga, kami ingin memutar kembali 3 karakter tambahan.
+/+/¨⍺=0
: Jumlahkan angka nol di argumen kiri . Yang pertama (dari kanan) +/¨
menjumlahkan jumlah setiap elemen (yaitu, sublist atau hanya integer), dan yang kedua +/
memberi kita jumlah dari daftar yang dihasilkan.
5+2×+/+/¨⍺=0
: Kalikan dua (untuk memutar spasi juga), dan tambahkan 5 (hasil yang kami buat sebelumnya).
- Sekarang, kita kurangi nilai sebelumnya dari argumen kiri ke
-
untuk menangani kasus ketika kita mencapai akhir siklus kita:
(3+z)×^/⍵
: DAN semua elemen dalam argumen yang tepat bersama untuk melihat apakah kita telah mencapai tujuan kita ( 1
), dan kalikan dengan 3+z
.
Dan kita selesai!