Das hat unglaublich viel Spaß gemacht. Vielen Dank, dass Sie diese Challenge gepostet haben.
Vollständige Offenlegung: Die Sprache (Hexagony) war zum Zeitpunkt der Veröffentlichung dieser Challenge noch nicht vorhanden. Ich habe es jedoch nicht erfunden und die Sprache wurde nicht für diese Herausforderung (oder irgendeine andere spezielle Herausforderung) entwickelt.
){_2"_{\"{{""}"{'2//_.\><*\"\/_><[\]/3\'\_;|#__/(\2\'3_'}(#:|{$#{>_\//(#={/;01*&"\\_|[##={|}$_#></)]$_##|){*_.>.(/?#//~-="{}<_"=#/\}.>"%<.{#{x\"<#_/=&{./1#_#>__<_'\/"#|@_|/{=/'|\"".{/>}]#]>(_<\'{\&#|>=&{{(\=/\{*'"]<$_
Sechseckig angeordnet:
) { _ 2 " _ { \ "
{ { " " } " { ' 2 /
/ _ . \ > < * \ " \ /
_ > < [ \ ] / 3 \ ' \ _
; | # _ _ / ( \ 2 \ ' 3 _
' } ( # : | { $ # { > _ \ /
/ ( # = { / ; 0 1 * & " \ \ _
| [ # # = { | } $ _ # > < / ) ]
$ _ # # | ) { * _ . > . ( / ? # /
/ ~ - = " { } < _ " = # / \ } .
> " % < . { # { x \ " < # _ /
= & { . / 1 # _ # > _ _ < _
' \ / " # | @ _ | / { = /
' | \ " " . { / > } ] #
] > ( _ < \ ' { \ & #
| > = & { { ( \ = /
\ { * ' " ] < $ _
Das Programm verwendet die #
Anweisung nicht wirklich , also habe ich dieses Zeichen verwendet, um zu zeigen, welche Zellen wirklich nicht verwendet werden.
Wie funktioniert dieses Programm? Das hängt davon ab. Willst du die kurze oder die lange Version?
Kurze Erklärung
Um zu veranschaulichen, was ich in der folgenden Erläuterung mit "Linie" und "Segment" meine, betrachten Sie diese Aufteilung der beabsichtigten Ausgabe:
segments →
│ │ │ │ │ │x lines
─┼───┼─┼─────────┼─┼───┼─ ↓
│ │ │ │ │xxx│
─┼───┼─┼─────────┼─┼───┘
│ │ │ │x│
─┼───┼─┼─────────┼─┘
│ │ │xxxxxxxxx│
─┼───┼─┼─────────┘
│ │x│
─┼───┼─┘
│xxx│
─┼───┘
x│
Damit entspricht das Programm dem folgenden Pseudocode:
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
Lange Erklärung
Bitte beziehen Sie sich auf dieses farbcodierte Codepfaddiagramm.
Die Ausführung beginnt in der oberen linken Ecke. Die ){2'"''3''"2}?)
Befehlsfolge wird ausgeführt (plus einige redundante Löschvorgänge "{
usw.), indem ein ziemlich verschlungener Pfad verfolgt wird. Wir beginnen mit dem Anweisungszeiger # 0, der hochrot hervorgehoben ist. Auf halbem Weg wechseln wir zu Nummer 1, beginnend in der oberen rechten Ecke und in Waldgrün. Wenn IP Nr. 2 in Kornblumenblau (Mitte rechts) beginnt, sieht das Speicherlayout folgendermaßen aus:
Während des gesamten Programms haben die mit 2a und 2b bezeichneten Kanten immer den Wert 2
(wir verwenden sie, um 2ⁿ⁺¹ zu berechnen und durch 2 zu teilen), und die mit 3 bezeichnete Kante ist immer 3
(wir verwenden sie, um 3ⁱ zu berechnen).
Wir machen uns an die Arbeit, als wir unsere erste Schleife betreten, die in Kornblumenblau hervorgehoben ist. Diese Schleife führt die Anweisungen (}*{=&}{=
zur Berechnung des Wertes 2ⁿ⁺¹ aus. Wenn die Schleife endet, wird der sattelbraune Pfad genommen, der uns zum Anweisungszeiger Nr. 3 führt. Diese IP plantscht lediglich in Goldrutengelb am unteren Rand nach Westen und übergibt die Kontrolle bald an IP # 4.
Der pinkfarbene Pfad gibt an, wie IP # 4, beginnend links unten, schnell zur Dekrementierung der Zeile voranschreitet , ch auf 32
(das Leerzeichen) und seg auf (den neuen Wert von) Zeile setzt . Aufgrund des frühen Dekrements beginnen wir tatsächlich mit 2ⁿ⁺¹ − 1 und erleben schließlich eine letzte Iteration mit dem Wert 0. Dann geben wir die erste verschachtelte Schleife ein.
Wir wenden unsere Aufmerksamkeit auf die Verzweigung Indigo, wo nach einer kurzen Abnahme der seg , sehen wir ch aktualisiert x
nur , wenn seg ist jetzt Null. Danach wird n auf line - seg gesetzt , um die tatsächliche Nummer des Segments zu bestimmen, in dem wir uns befinden. Sofort treten wir in eine weitere Schleife ein, diesmal in der hellen Farbe von Tomate.
Hier stellen wir fest, wie oft n (die aktuelle Segmentnummer) durch 2 dividiert werden kann. Solange das Modulo Null ergibt, inkrementieren wir i und dividieren n durch 2. Wenn wir zufrieden sind, ist n nicht mehr so teilbar , verzweigen wir uns in das Schiefergrau, das zwei Schleifen enthält: Zuerst erhöht es 3 zur Potenz des von uns berechneten i , und dann gibt es ch so oft aus. Beachten Sie, dass die erste dieser Schleifen a enthält[
Befehl, der die Steuerung auf IP # 3 umschaltet - diejenige, die zuvor nur kleine Schritte entlang der unteren Kante unternommen hat. Der Körper der Schleife (multipliziert mit 3 und dekrementiert) wird von einer einsamen IP # 3 ausgeführt, die in einem endlosen dunkelolivgrünen Zyklus am unteren Rand des Codes eingeschlossen ist. In ähnlicher Weise enthält die zweite dieser schiefergrauen Schleifen eine ]
Anweisung, die IP # 5 aktiviert, um Kanal und Dekrement auszugeben , die hier in dunklem Indischrot dargestellt sind. In beiden Fällen führen die in der Knechtschaft gefangenen Anweisungszeiger gehorsam eine Iteration nach der anderen aus und geben die Kontrolle an IP # 4 zurück, nur um den Zeitpunkt abzuwarten, an dem ihr Dienst erneut aufgerufen werden soll. Das Schiefergrau verbindet sich unterdessen wieder mit seinen Fuchsia- und Indigo-Brüdern.
Wenn seg zwangsläufig Null erreicht, tritt die Indigoschleife in den grünen Rasenpfad ein, der lediglich das Zeilenumbruchzeichen ausgibt und sofort wieder in die Fuchsie übergeht, um die Linienschleife fortzusetzen . Jenseits der letzten Iteration der Leitungsschleife liegt der kurze schwarze Pfad der endgültigen Programmbeendigung.
(,],~3^#@~.)@]
statt(1,[:,1,"0~3*])
spart 1 Byte. Und wenn Sie mit!
als Ausgabezeichen in Ordnung sind,u:32+
anstatt ein' #'{~
anderes zu speichern.