APL (158 znaków, wynik = 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
Używam tutaj Dyalog APL. Liczbę cykli można zwiększyć o jeden, dodając 0
(0, a następnie spację) na końcu wyrażenia i na końcu łańcucha (przed '''
). Długość cyklu wynosi (# 0's) + 1
, a długość wyrażenia wynosi 150 + 4*(cycle length))
. Zakładając, że nadal dodajemy zera na zawsze, wynikiem jest Limit[(150 + 4*n)/(n - 1), n -> Infinity] = 4
, gdzie n
jest długość cyklu.
Oto przykład z długością cyklu = 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 znaki, wynik = 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
W zależności od implementacji jednym punktem awarii może być zbyt duża liczba przedrostkowa łańcucha. Teoretycznie możemy dodać cykl, dodając dwa znaki - a 1
na końcu ciągu (przed '''
) i a 1
na końcu całej linii.
200 znaków, wynik = 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
Moja implementacja APL nie ma domyślnie liczb całkowitych o nieograniczonej precyzji, więc liczba całkowita jest konwertowana na liczbę zmiennoprzecinkową, gdy staje się zbyt duża, co powoduje, że dane wyjściowe są nieprawidłowe. Więc ten jest najbardziej wybredny, ale teoretycznie (albo ręcznie, albo z innym interpreterem APL), powinien mieć wynik 1. Po prostu dodaj a 1
na końcu wyrażenia, a otrzymasz kolejny cykl.
Przegląd (z krótszym okiem)
Przedstawię przegląd pierwszej wersji, ponieważ myślę, że jest to prawdopodobnie najłatwiejszy do zrozumienia. Zanim jednak zajmiemy się tą wersją, rozważymy prosty quine w APL :
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
Odkryłem, że jednym z najlepszych sposobów na zrozumienie niektórych wyrażeń APL jest spojrzenie na dane wyjściowe w kaskadzie operatorów / funkcji. Wszystkie operatory i funkcje w APL są skojarzone z prawą i mają taki sam priorytet, więc oto od prawej do lewej:
'''1⌽22⍴11⍴'''
: To tylko literał łańcuchowy (lista znaków). ''
jest sposobem APL na unikanie pojedynczych cudzysłowów. Wyjście: '1⌽22⍴11⍴'
.
11⍴'''1⌽22⍴11⍴'''
: Tutaj przekształcamy ( ⍴
) ciąg znaków na długość 11
. Ponieważ długość łańcucha jest mniejsza niż 11, jest on powtarzany (tzn. 5⍴'abc'
Dałby wynik 'abcab'
). Wyjście: '1⌽22⍴11⍴''
. Mamy więc na końcu dwa znaki cudzysłowu - gdzieś się udajemy!
22⍴11⍴'''1⌽22⍴11⍴'''
: Podobnie teraz przekształcamy nasze poprzednie dane wyjściowe na długość 22
. Wyjście: '1⌽22⍴11⍴'''1⌽22⍴11⍴''
. Jesteśmy prawie na miejscu - wystarczy przesunąć pierwszy pojedynczy cytat na koniec.
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
: Tutaj obracamy ( ⌽
) listę znaków o 1
. To przesuwa pierwszy znak ciągu na koniec. Jako kolejny przykład 2⌽'abcdef'
zwraca 'cdefab'
. Wyjście: 1⌽22⍴11⍴'''1⌽22⍴11⍴'''
.
Obracający się quine
Ten krótki quine jest główną podstawą naszego obrotowego quine. Mając to na uwadze, spójrzmy na nasz quine:
'''{(((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
{ ... }
definiuje nienazwaną funkcję, w której będziemy wykonywać pracę. Zauważ, że funkcje w APL pobierają prawy argument oznaczony przez ⍵
i opcjonalny lewy argument oznaczony przez ⍺
(think infix). Chcemy zasilić tę funkcję zarówno naszym ciągiem znaków quine, jak i czymś, co pomoże nam w tworzeniu dowolnej liczby cykli. Aby ułatwić sobie (i każdemu, kto chce dodać cykle), ciąg quine jest lewym argumentem. Właściwy argument dotyczy zatem naszej listy cykli. 2 lub więcej elementów oddzielonych spacją tworzy listę, więc w tym przykładzie mamy 2-elementową listę składającą się z a 1
i a 0
.
Widzimy, że funkcja wygląda podobnie do poprzedniej. Mamy taką samą ...⌽...⍴...⍴...
formę jak wcześniej. To dobrze - przynajmniej tyle rozumiemy! Spójrzmy prawdzie wniknąć głębiej elips, zaczynając wszystko od wyprodukowania ostatniego ⍴
: ⊃,/(~^/¨⍺=0)/⍺
.
- Jak widać, patrząc na powyższy przykład, poprzedzamy ciąg zerami z prawej strony, dodając jeden z każdą iteracją; ale nie dbamy o to teraz. Chcemy tylko sznurka!
- Najpierw zastanów się, co jest w nawiasach. (Nawiasem mówiąc, grupują się jak w większości innych języków).
⍺=0
zwraca listę, w tym przypadku, o takim samym kształcie jak ⍺
, gdzie każdy element ⍺
jest zastępowany przez a, 1
jeśli jest on równy 0
, i w 0
przeciwnym razie. Odbywa się to rekurencyjnie; więc jeśli mamy listę z listą znaków, poszczególne znaki zostaną przetestowane pod kątem 0, a otrzymasz listę list wartości binarnych.
- Więc jeśli
⍺
składa się tylko z naszego ciągu, otrzymujemy listę zer. W przeciwnym razie nasz lewy argument ma przedrostek 0 (np. 0 0 0 'quinestring'
), Więc jest to lista składająca się z zer i innej listy, naszego łańcucha. Tak wygląda nasza produkcja 1 1 1 <sub-list of zeros>
.
^/¨⍺=0
: Stosujemy funkcję pochodną ^/
, która redukuje ( /
) za pomocą logicznej funkcji AND ( ^
), do każdego ¨
elementu ( ) ⍺=0
. Ma to na celu spłaszczenie podlisty zer, abyśmy mogli traktować ciąg quine jako jedną wartość binarną. Biorąc pod uwagę poprzedni przykład, wynik byłby 1 1 1 0
.
~
: Binarnie NIE każdą z wcześniejszych wartości (np. Zwracamy 0 0 0 1
).
(~^/¨⍺=0)/⍺
: Dla każdego elementu ⍺
replikujemy ( /
) liczbę razy podaną przez odpowiedni element w lewym argumencie. To eliminuje wszystkie zera, pozostawiając nas tylko z naszym ciągiem znaków quine.
⊃,/
jest niezbędną formalnością, aby upewnić się, że otrzymamy spłaszczoną listę znaków, zmniejszając wynik za pomocą funkcji konkatenacji ( ,
). Jeśli wejście jest już spłaszczoną listą (tzn. Lewym argumentem naszej funkcji głównej jest tylko ciąg znaków), otrzymujemy 1-elementową listę zawierającą tę listę. W innym przypadku, gdy mamy listę składającą się z podlisty ciągu, otrzymujemy tę samą rzecz z powrotem (listę z podlistą). Następnie rozpakowujemy to ( ⊃
), dając nam tylko pierwszy element listy (tj. Podlistę znaków). Może się to wydawać niepotrzebne, ale w przeciwnym razie próbowalibyśmy przekształcić listę 1-elementową!
Następnie patrzymy na długość podaną dla pierwszego przekształcenia w nawiasach:
⍺,⍵
: Łączymy właściwy argument z pierwszym argumentem
⊃,/⍺,⍵
: Tak jak poprzednio - spłaszcz listę.
+/0=⊃,/⍺,⍵
: Dodaj liczbę zer na liście, zmniejszając ( /
) za pomocą funkcji add ( +
).
2×+/0=⊃,/⍺,⍵
: Pomnóż tę liczbę przez dwa.
z←2×+/0=⊃,/⍺,⍵
: Rola ( ←
) wynik do zmiennej z
. Reasumując, z
jest teraz dwa razy większa niż zero znalezione zarówno w lewym, jak i prawym argumencie.
77+z←2×+/0=⊃,/⍺,⍵
: Następnie dodajemy 77
dla znaków w ciągu znaków quine ignorowanie wszystkiego po następującym po nim spacji 1
. Podobnie jak w pierwszym przykładzie quine, dodajemy 1 do długości ciągu, aby uzyskać kolejny pojedynczy cytat.
- Dane wyjściowe tego przekształcenia w tym przykładzie są następujące:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Argument dotyczący następującego przekształcenia jest prosty i odzwierciedla krótki quine (2-krotność długości pierwszego przekształcenia). Nasza produkcja jest teraz:
'{(((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 ''
Teraz ostatni krok, w którym obliczamy, ile obrócić ciąg wyjściowy:
- Jak widać patrząc na poprzedni wynik, chcemy go obrócić z powrotem (kwota ujemna), aby doprowadzić 2 końcowe cytaty na początek. Ponieważ chcemy, aby
0
(i inna spacja) również przesunęła się na początek, chcemy obrócić ją o dodatkowe 3 znaki z powrotem.
+/+/¨⍺=0
: Dodaj liczbę zer w lewym argumencie. Pierwszy (od prawej) +/¨
sumuje liczbę każdego elementu (tj. Podlistę lub tylko liczbę całkowitą), a drugi +/
daje nam sumę wynikowej listy.
5+2×+/+/¨⍺=0
: Pomnóż przez dwa (aby również obrócić spacje) i dodaj 5 (wynik, który wymyśliliśmy wcześniej).
- Teraz odejmujemy poprzednią wartość od lewego argumentu,
-
aby obsłużyć sprawę po osiągnięciu końca naszego cyklu:
(3+z)×^/⍵
: ORAZ wszystkie elementy we właściwym argumencie, aby sprawdzić, czy osiągnęliśmy koniec ( 1
), i pomnóż to przez 3+z
.
I skończone!