Sześciokąt , 920 722 271 bajtów
Mówisz, że jest sześć różnych rodzajów pętli owocowych? To, co Hexagony została wykonana za.
){r''o{{y\p''b{{g''<.{</"&~"&~"&<_.>/{.\.....~..&.>}<.._...=.>\<=..}.|>'%<}|\.._\..>....\.}.><.|\{{*<.>,<.>/.\}/.>...\'/../==.|....|./".<_>){{<\....._>\'=.|.....>{>)<._\....<..\..=.._/}\~><.|.....>e''\.<.}\{{\|./<../e;*\.@=_.~><.>{}<><;.(~.__..>\._..>'"n{{<>{<...="<.>../
Okej, nie było. O Boże, co ja sobie zrobiłem ...
Ten kod jest teraz sześciokątem o długości boku 10 (zaczął od 19). Prawdopodobnie może być jeszcze trochę w golfa, może nawet do rozmiaru 9, ale myślę, że moja praca została wykonana tutaj ... Dla odniesienia, w źródle znajduje się 175 faktycznych poleceń, z których wiele jest potencjalnie niepotrzebnymi kopiami lustrzanymi (lub zostały dodane, aby anulować wydać polecenie ze ścieżki krzyżowej).
Pomimo pozornej liniowości kod jest w rzeczywistości dwuwymiarowy: sześciokąt przekształci go w zwykły sześciokąt (co jest również poprawnym kodem, ale wszystkie białe znaki są opcjonalne w sześciokącie). Oto rozwinięty kod w całym ... no cóż, nie chcę mówić „piękno”:
) { r ' ' o { { y \
p ' ' b { { g ' ' < .
{ < / " & ~ " & ~ " & <
_ . > / { . \ . . . . . ~
. . & . > } < . . _ . . . =
. > \ < = . . } . | > ' % < }
| \ . . _ \ . . > . . . . \ . }
. > < . | \ { { * < . > , < . > /
. \ } / . > . . . \ ' / . . / = = .
| . . . . | . / " . < _ > ) { { < \ .
. . . . _ > \ ' = . | . . . . . > {
> ) < . _ \ . . . . < . . \ . . =
. . _ / } \ ~ > < . | . . . . .
> e ' ' \ . < . } \ { { \ | .
/ < . . / e ; * \ . @ = _ .
~ > < . > { } < > < ; . (
~ . _ _ . . > \ . _ . .
> ' " n { { < > { < .
. . = " < . > . . /
Wyjaśnienie
Nie będę nawet próbował wyjaśniać wszystkich zawiłych ścieżek wykonania w tej wersji golfowej, ale algorytm i ogólny przepływ sterowania są identyczne z tą wersją bez golfa, która może być łatwiejsza do nauki dla naprawdę ciekawych po wyjaśnieniu algorytmu:
) { r ' ' o { { \ / ' ' p { . . .
. . . . . . . . y . b . . . . . . .
. . . . . . . . ' . . { . . . . . . .
. . . . . . . . \ ' g { / . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . > . . . . < . . . . . . . . .
. . . . . . . . . . . . . . > . . ) < . . . . .
. . . . . . . . . . / = { { < . . . . ( . . . . .
. . . . . . . . . . . ; . . . > . . . . . . . . . <
. . . . . . . . . . . . > < . / e ; * \ . . . . . . .
. . . . . . . . . . . . @ . } . > { } < . . | . . . . .
. . . . . / } \ . . . . . . . > < . . . > { < . . . . . .
. . . . . . > < . . . . . . . . . . . . . . . | . . . . . .
. . . . . . . . _ . . > . . \ \ " ' / . . . . . . . . . . . .
. . . . . . \ { { \ . . . > < . . > . . . . \ . . . . . . . . .
. < . . . . . . . * . . . { . > { } n = { { < . . . / { . \ . . |
. > { { ) < . . ' . . . { . \ ' < . . . . . _ . . . > } < . . .
| . . . . > , < . . . e . . . . . . . . . . . . . = . . } . .
. . . . . . . > ' % < . . . . . . . . . . . . . & . . . | .
. . . . _ . . } . . > } } = ~ & " ~ & " ~ & " < . . . . .
. . . \ . . < . . . . . . . . . . . . . . . . } . . . .
. \ . . . . . . . . . . . . . . . . . . . . . . . < .
. . . . | . . . . . . . . . . . . . . . . . . = . .
. . . . . . \ . . . . . . . . . . . . . . . . / .
. . . . . . > . . . . . . . . . . . . . . . . <
. . . . . . . . . . . . . . . . . . . . . . .
_ . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
Szczerze mówiąc, w pierwszym akapicie żartowałem tylko w połowie. Fakt, że mamy do czynienia z cyklem sześciu elementów, był naprawdę wielką pomocą. Model pamięci Hexagony jest nieskończoną heksagonalną siatką, w której każda krawędź siatki zawiera liczbę całkowitą o dowolnej dokładności, zinicjalizowaną do zera.
Oto schemat układu pamięci, której użyłem w tym programie:

Długi prosty bit po lewej stronie jest używany jako ciąg zakończony 0 ao dowolnym rozmiarze, który jest powiązany z literą r . Linie przerywane na innych literach reprezentują ten sam rodzaj struktury, każda obrócona o 60 stopni. Początkowo wskaźnik pamięci wskazuje krawędź oznaczoną 1 , zwróconą na północ.
Pierwszy, liniowy bit kodu ustawia wewnętrzną „gwiazdę” krawędzi na litery, roygbpa także ustawia początkową krawędź na 1, tak abyśmy wiedzieli, gdzie cykl się kończy / zaczyna (pomiędzy pi r):
){r''o{{y''g{{b''p{
Następnie wracamy do krawędzi oznaczonej jako 1 .
Ogólna idea algorytmu jest następująca:
- Dla każdej litery w cyklu czytaj dalej litery STDIN i, jeśli różnią się one od bieżącej litery, dołącz je do ciągu związanego z tą literą.
- Kiedy czytamy list, którego obecnie szukamy, przechowujemy
ena brzegu etykietę ? , ponieważ dopóki cykl się nie zakończy, musimy założyć, że będziemy musieli także zjeść tę postać. Następnie przejdziemy przez pierścień do następnej postaci w cyklu.
- Proces ten można przerwać na dwa sposoby:
- Albo zakończyliśmy cykl. W takim przypadku wykonujemy kolejną szybką rundę w cyklu, zastępując wszystkie te
ez pola ? krawędzie z ns, ponieważ teraz chcemy, aby ten cykl pozostał na naszyjniku. Następnie przechodzimy do drukowania kodu.
- Lub trafiamy EOF (który rozpoznajemy jako kod znaku ujemnego). W takim przypadku zapisujemy wartość ujemną w ? krawędź obecnego znaku (dzięki czemu możemy łatwo odróżnić go od obu
ei n). Następnie szukamy 1 krawędzi (aby pominąć pozostałą część potencjalnie niepełnego cyklu) przed przejściem do drukowania kodu.
- Kod drukujący przechodzi ponownie przez cykl: dla każdego znaku w cyklu usuwa zapisany ciąg podczas drukowania
edla każdego znaku. Następnie przenosi się do ? krawędź związana z postacią. Jeśli jest ujemny, po prostu kończymy program. Jeśli jest pozytywny, po prostu go drukujemy i przechodzimy do następnej postaci. Po zakończeniu cyklu wracamy do kroku 2.
Inną rzeczą, która może być interesująca, jest to, jak zaimplementowałem łańcuchy o dowolnym rozmiarze (ponieważ po raz pierwszy użyłem nieograniczonej pamięci w Hexagony).
Wyobraźmy sobie, że jesteśmy w pewnym momencie, dokąd jeszcze czyta znaki dla R (tak, możemy użyć schemat jak jest) i A [0] i 1 zostały już wypełnione znaków (wszystko na północny-zachód z nich jest nadal zerem ). Np. Może właśnie przeczytaliśmy pierwsze dwa znaki wejścia do tych krawędzi i teraz czytamy a .ogy
Nowy znak jest odczytywany w na krawędzi. Używamy ? krawędzi, aby sprawdzić, czy ten znak jest równy r. (Jest tu sprytna sztuczka: sześciokąt może łatwo rozróżniać między dodatnim i dodatnim, więc sprawdzanie równości poprzez odejmowanie jest denerwujące i wymaga co najmniej dwóch gałęzi. Ale wszystkie litery są mniejsze niż współczynnik 2, więc możemy porównać wartości, biorąc modulo, który da zero tylko wtedy, gdy będą równe.)
Ponieważ yróżni się od r, przechodzimy do (nie znakowanych) od lewej krawędzi w i skopiować ytam. Przechodzimy teraz bliższe okolice sześciokąta, kopiując znak jedną krawędź dodatkowo za każdym razem, dopóki mamy yna przeciwległej krawędzi w . Ale teraz w [0] jest już postać, której nie chcemy zastępować. Zamiast tego, „drag” THE ywokół następnego sześciokąta i sprawdzić się 1 . Ale jest tam też postać, więc idziemy o kolejny sześciokąt dalej. Teraz [2] wciąż wynosi zero, więc kopiujemyyw tym. Wskaźnik pamięci przesuwa się teraz wzdłuż sznurka w kierunku pierścienia wewnętrznego. Wiemy, kiedy osiągnęliśmy początek łańcucha, ponieważ (nieznakowane) krawędzie między a [i] są zerowe, podczas gdy ? jest pozytywny.
Prawdopodobnie będzie to przydatna technika do pisania nietrywialnego kodu w Hexagony w ogóle.