To była niesamowita zabawa. Dziękujemy za opublikowanie tego wyzwania.
Pełne ujawnienie: język (heksagonia) nie istniał w momencie opublikowania tego wyzwania. Jednak nie wymyśliłem go, a język nie został zaprojektowany do tego wyzwania (ani żadnego innego konkretnego wyzwania).
){_2"_{\"{{""}"{'2//_.\><*\"\/_><[\]/3\'\_;|#__/(\2\'3_'}(#:|{$#{>_\//(#={/;01*&"\\_|[##={|}$_#></)]$_##|){*_.>.(/?#//~-="{}<_"=#/\}.>"%<.{#{x\"<#_/=&{./1#_#>__<_'\/"#|@_|/{=/'|\"".{/>}]#]>(_<\'{\&#|>=&{{(\=/\{*'"]<$_
Rozłożony sześciokątnie:
) { _ 2 " _ { \ "
{ { " " } " { ' 2 /
/ _ . \ > < * \ " \ /
_ > < [ \ ] / 3 \ ' \ _
; | # _ _ / ( \ 2 \ ' 3 _
' } ( # : | { $ # { > _ \ /
/ ( # = { / ; 0 1 * & " \ \ _
| [ # # = { | } $ _ # > < / ) ]
$ _ # # | ) { * _ . > . ( / ? # /
/ ~ - = " { } < _ " = # / \ } .
> " % < . { # { x \ " < # _ /
= & { . / 1 # _ # > _ _ < _
' \ / " # | @ _ | / { = /
' | \ " " . { / > } ] #
] > ( _ < \ ' { \ & #
| > = & { { ( \ = /
\ { * ' " ] < $ _
Program tak naprawdę nie korzysta z #
instrukcji, więc użyłem tego znaku, aby pokazać, które komórki są rzeczywiście nieużywane.
Jak działa ten program? To zależy. Chcesz krótką wersję, czy długą?
Krótkie wyjaśnienie
Aby zilustrować, co rozumiem przez „linię” i „segment” w poniższym wyjaśnieniu, rozważ ten podział zamierzonego wyniku:
segments →
│ │ │ │ │ │x lines
─┼───┼─┼─────────┼─┼───┼─ ↓
│ │ │ │ │xxx│
─┼───┼─┼─────────┼─┼───┘
│ │ │ │x│
─┼───┼─┼─────────┼─┘
│ │ │xxxxxxxxx│
─┼───┼─┼─────────┘
│ │x│
─┼───┼─┘
│xxx│
─┼───┘
x│
Po wyjaśnieniu program odpowiada następującemu pseudokodowi:
n = get integer from stdin
# Calculate the number of lines we need to output.
line = pow(2, n+1)
while line > 0:
line = line - 1
# For all segments except the last, the character to use is spaces.
ch = ' ' (space, ASCII 32)
# The number of segments in each line is
# equal to the line number, counting down.
seg = line
while seg > 0:
seg = seg - 1
# For the last segment, use x’s.
if seg = 0:
ch = 'x' (ASCII 120)
# Calculate the actual segment number, where the leftmost is 1
n = line - seg
# Output the segment
i = pow(3, number of times n can be divided by 2)
i times: output ch
output '\n' (newline, ASCII 10)
end program
Długie wyjaśnienie
Zapoznaj się z tym schematem ścieżki kodu zakodowanym kolorem
Realizacja rozpoczyna się w lewym górnym rogu. Sekwencja instrukcji ){2'"''3''"2}?)
jest wykonywana (plus kilka zbędnych anulowań, "{
itp.) Poprzez podążanie dość skomplikowaną ścieżką. Zaczynamy od wskaźnika instrukcji nr 0, zaznaczonego szkarłatem. W połowie przełączamy się na numer 1, zaczynając od prawego górnego rogu i pomalowany na zielono. Gdy IP # 2 zaczyna się od błękitu chabrowego (środkowy prawy), układ pamięci jest następujący:
W całym programie krawędzie oznaczone 2a i 2b zawsze będą miały wartość 2
(używamy ich do obliczania odpowiednio 2ⁿ⁺¹ i dzielenia przez 2), a krawędź oznaczona 3 zawsze będzie 3
(używamy tego do obliczania 3ⁱ).
Wchodzimy do biznesu, wchodząc w naszą pierwszą pętlę, wyróżnioną kolorem chabrowym. Ta pętla wykonuje instrukcje, (}*{=&}{=
aby obliczyć wartość 2ⁿ⁺¹. Kiedy pętla wychodzi, wybierana jest brązowa ścieżka siodła, która prowadzi nas do wskaźnika instrukcji nr 3. Ten adres IP jedynie przesuwa się wzdłuż dolnej krawędzi na zachód w żółtawo-złotym kolorze i wkrótce przechodzi kontrolę nad IP # 4.
Ścieżka fuksji wskazuje, w jaki sposób IP # 4, zaczynając od lewego dolnego rogu, przechodzi szybko do linii zmniejszania , ustawia ch na 32
(znak spacji) i seg na (nowa wartość) linii . Jest to spowodowane wczesnym zmniejszeniem, że faktycznie zaczynamy od 2ⁿ⁺¹ − 1 i ostatecznie doświadczamy ostatniej iteracji z wartością 0. Następnie wchodzimy do pierwszej zagnieżdżonej pętli.
Zwracamy uwagę na rozgałęziony indygo, w którym po krótkim zmniejszeniu seg widzimy, że ch jest aktualizowane x
tylko wtedy, gdy seg wynosi teraz zero. Następnie n ustawia się na linii - seg, aby określić faktyczną liczbę segmentów, w których się znajdujemy. Natychmiast wchodzimy w kolejną pętlę, tym razem w jasnym kolorze pomidora.
W tym miejscu ustalamy, ile razy n (bieżący numer segmentu) można podzielić przez 2. Tak długo, jak moduł daje nam zero, zwiększamy i dzielimy n przez 2. Gdy jesteśmy usatysfakcjonowani, n nie jest już podzielny , rozgałęziamy się na szary łupek, który zawiera dwie pętle: najpierw podnosi 3 do potęgi obliczonego przez nas i , a następnie wyprowadza ch tyle razy. Zauważ, że pierwsza z tych pętli zawiera[
instrukcja, która przełącza sterowanie na IP # 3 - ta, która wcześniej tylko stawiała małe kroki wzdłuż dolnej krawędzi. Ciało pętli (pomnożenie przez 3 i zmniejszenie) jest wykonywane przez samotny adres IP # 3, uwięziony w nieskończonym cyklu ciemnozielonej zieleni wzdłuż dolnej krawędzi kodu. Podobnie, druga z tych łupkowych szarych pętli zawiera ]
instrukcję, która aktywuje IP # 5 do wyjścia ch i dekrementacji, pokazane tutaj w ciemno indyjskiej czerwieni. W obu przypadkach wskaźniki instrukcji uwięzione w służebności posłusznie wykonują jedną iterację naraz i poddają kontrolę z powrotem do IP # 4, tylko po to, aby poczekać chwilę na ponowne wezwanie ich usługi. Tymczasem szary łupek powraca do braci w kolorze fuksji i indygo.
Gdy seg nieuchronnie osiąga zero, pętla indygo wychodzi na zieloną ścieżkę trawnika, która jedynie wyprowadza znak nowej linii i natychmiast łączy się z powrotem w fuksję, aby kontynuować pętlę linii . Poza końcową iteracją pętli liniowej znajduje się krótka, ebonowa ścieżka ostatecznego zakończenia programu.
(,],~3^#@~.)@]
zamiast(1,[:,1,"0~3*])
oszczędzać 1 bajt. A jeśli nie masz nic przeciwko!
jako wyjściowy znak char,u:32+
zamiast' #'{~
zapisywać inny.