Die Eingabe besteht aus folgenden Zeichen:
^
: Geh eins hochv
: Geh einen runter▲
oderk
: Geh zwei hoch▼
oderj
: Geh zwei runter
Zum Beispiel die folgende Eingabe:
^^▲^v▼▲^^v
würde die folgende Ausgabe erzeugen:
^
^ ^ v
▲ v ▲
^ ▼
^
Escape-Sequenzen, die den Cursor bewegen, \e[B
sind nicht zulässig. Sie müssen die Ausgabe mit Leerzeichen und Zeilenumbrüchen erstellen.
Hier noch ein paar Testfälle.
▲v^v^v^v^v^v^v^v▲
▲
▲ ^ ^ ^ ^ ^ ^ ^
v v v v v v v v
^^^^^^^▲▲▲▼▼▼vvvvvv
▲
▲ ▼
▲ ▼
^ ▼
^ v
^ v
^ v
^ v
^ v
^ v
v^^vv^^vvv^v^v^^^vvvv^^v^^vv
^ ^ ^
^ v ^ v ^ v ^
v v v ^ ^ ^ v ^ ^ v
v v v v ^ v v
v
j
zweimal runter undk
zweimal rauf zu gehen.Antworten:
Pyth, 27 Bytes
Probieren Sie es online aus: Demo oder Test Suite
Ich benutze
k
undj
anstelle von▲
und▼
. Es gibt viele führende und nachfolgende Leerzeilen. Sie müssen ziemlich viel suchen, um das Bild zu finden. Hier ist eine 34-Byte- Version, die alle führenden und nachfolgenden Leerzeilen entfernt.Probieren Sie es online aus: Demo oder Test Suite
Erläuterung:
quelle
Nicht lesbar ,
219921452134210420872084 BytesUnterstützt sowohl
k
/j
als auch▲
/▼
Syntax.In guter unleserlicher Tradition ist hier das Programm in proportionaler Schrift formatiert, um die Unterscheidung zwischen Apostrophen und doppelten Anführungszeichen zu verschleiern:
Dies war eine erstaunliche Herausforderung. Vielen Dank für die Veröffentlichung!
Erläuterung
Um ein Gefühl dafür zu bekommen, was Unreadable kann und was nicht, stellen Sie sich Brainfuck mit einem unendlichen Band in beide Richtungen vor. Statt eines Speicherzeigers, der jeweils eine Zelle bewegt, können Sie auf eine beliebige Speicherzelle zugreifen, indem Sie einen Zeiger dereferenzieren. Dies ist in dieser Lösung sehr praktisch, obwohl andere arithmetische Operationen - einschließlich Modulo - von Hand ausgeführt werden müssen.
Hier ist das Programm als Pseudocode mit Regiekommentar:
Soviel zur Programmlogik. Jetzt müssen wir dies in Unreadable übersetzen und ein paar weitere interessante Golf-Tricks anwenden .
Variablen werden in Unreadable immer dereferenziert (zB
a = 1
wird so etwas*(1) = 1
). Einige numerische Literale sind länger als andere; die kürzeste ist 1, gefolgt von 2 usw. Um zu zeigen, wie viel länger negative Zahlen sind, sind hier die Zahlen von -1 bis 7:Natürlich möchten wir die Variable # 1 derjenigen zuordnen, die im Code am häufigsten vorkommt . In der ersten while-Schleife ist dies definitiv
mod5
die 10-fache. Wir brauchen abermod5
nach der ersten while-Schleife nichts mehr, sodass wir den gleichen Speicherplatz anderen Variablen zuweisen können, die wir später verwenden. Das sindptr2
undptr3
. Jetzt wird die Variable insgesamt 21 Mal referenziert. (Wenn Sie versuchen, die Anzahl der Vorkommen selbst zu zählen, denken Sie daran,a++
zweimal zu zählen , einmal, um den Wert abzurufen, und einmal, um ihn festzulegen.)Es gibt nur eine andere Variable, die wir wiederverwenden können. nachdem wir die Modulo-Werte berechnet haben,
ch
wird es nicht mehr benötigt.up
unddn
kommen die gleiche Anzahl von Malen, so ist entweder in Ordnung. Lassen Sie uns mergech
mitup
.Somit bleiben insgesamt 8 eindeutige Variablen übrig. Wir könnten die Variablen 0 bis 7 zuweisen und dann den Speicherblock (der die Zeichen und Zeilennummern enthält) bei 8 starten. Aber! Da 7 im Code die gleiche Länge hat wie −1, können wir auch die Variablen −1 bis 6 verwenden und den Speicherblock bei 7 starten. Auf diese Weise ist jeder Verweis auf die Startposition des Speicherblocks im Code etwas kürzer! Dies lässt uns mit folgenden Aufgaben:
Nun dies erklärt die Initialisierung an der Spitze: es 5 ist , weil es 7 (der Anfang des Speicherblockes) minus 2 (der obligatorische Schritt in dem ersten , während Bedingung). Gleiches gilt für die beiden anderen Vorkommen von 5 in der letzten Schleife.
Beachten Sie, dass 0 und 4 im Code dieselbe Länge haben
ptr
undminLine
umgekehrt zugewiesen werden können. ... Oder könnten sie?Was ist mit der mysteriösen 2 in der vorletzten while-Schleife? Sollte das nicht eine 6 sein? Wir wollen nur die Zahlen im Datenblock dekrementieren, oder? Sobald wir 6 erreichen, sind wir außerhalb des Datenblocks und wir sollten aufhören! Es wäre eine Sicherheitslücke, die durch einen Pufferüberlauffehler ausgelöst werden könnte!
Denken Sie darüber nach, was passiert, wenn wir nicht aufhören. Wir dekrementieren die Variablen 6 und 4. Die Variable 6 ist
mod4
. Das wird nur in der ersten while-Schleife verwendet und hier nicht mehr benötigt, also kein Schaden angerichtet. Was ist mit Variable 4? Was denkst du, sollte Variable 4 seinptr
oder sollte es seinminLine
? Das stimmt,minLine
wird an dieser Stelle auch nicht mehr verwendet! Somit ist die Variable # 4minLine
und wir können sie sicher dekrementieren und keinen Schaden anrichten!UPDATE 1! Golf von 2199 bis 2145 Bytes durch Realisierung,
dn
die auch mit zusammengeführt werden könnenmod5
, obwohlmod5
noch in der Berechnung des Wertes für verwendet wirddn
! Neue Variablenbelegung ist jetzt:UPDATE 2! Wurde zwischen 2145 und 2134 Byte verarbeitet, indem erkannt wurde, dass
mod5
die Variabledn
, die jetzt in einer while-Schleife bis 0 gezählt wird,mod5
nicht mehr explizit auf 0 initialisiert werden muss.UPDATE 3! Golf von 2134 bis 2104 Bytes durch die Realisierung von zwei Dingen. Erstens, obwohl sich die Idee des „negativen Moduls“ gelohnt hat
mod5
, gilt die gleiche Argumentation nicht,mod4
da wir nie mitmod4+2
usw. testen . Daher führt die Änderungmod4 ? mod4+1 : -3
vonmod4 ? mod4-1 : 3
zu 2110 Byte. Zweitensmod4
können wir , da immer 0 oder 2 ist,mod4
auf 2 anstelle von 0 initialisieren und die beiden Ternären (mod4 ? 3 : 1
anstelle vonmod4 ? 1 : 3
) umkehren .UPDATE 4! Wird zwischen 2104 und 2087 Byte verarbeitet, indem erkannt wird, dass die while-Schleife, die die Modulo-Werte berechnet, immer mindestens einmal ausgeführt wird. In diesem Fall können Sie mit Unreadable den Wert der letzten Anweisung in einem anderen Ausdruck wiederverwenden. Anstelle von
while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
jetzt haben wir alsoup = ((while --ch: [...]) ? mod5+1 ? [...]
(und innerhalb dieser while-Schleife berechnen wirmod4
zuerst, dasmod5
ist also die letzte Anweisung).UPDATE 5! Golf von 2087 bis 2084 Bytes durch die Erkenntnis, dass ich anstelle des Ausschreibens der Konstanten
32
und10
(Leerzeichen und Zeilenvorschub) die Nummer 10 in der (jetzt nicht verwendeten) Variablen # 2 speichern kann (nennen wir esten
). Anstatt zuptr3 = 5
schreibenten = (ptr3 = 5) + 5
,32
wirdten+22
undprint 10
wirdprint ten
.quelle
CJam, 37 Bytes
Dies druckt leere Zeilen vor und nach der gewünschten Ausgabe, die vom OP zugelassen wurde .
Probieren Sie es online im CJam-Interpreter aus .
Wie es funktioniert
quelle
Python 2, 102
Druckt zeilenweise.
Durchläuft Zeichen in der Eingabe und verfolgt die aktuelle Höhe. Die Höhe wird von einem der
+2, +1, -1, -2
berechneten Werte aktualisiert'kv_^j'.find(c)-2
. Es gibt wahrscheinlich eine Mod-Kette, die kürzer istWenn die aktuelle Höhe der Zeilennummer entspricht (was negativ sein kann), fügen wir das aktuelle Zeichen an die Zeile und ansonsten ein Leerzeichen an. Dann drucken wir die Zeile. Tatsächlich ist es kürzer, die Höhe an der aktuellen Zeilennummer zu beginnen und die Höhenänderungen zu subtrahieren, wobei das Zeichen angehängt wird, wenn der Wert trifft
0
.Die Zeilennummern umfassen einen Bereich, der groß genug ist, dass eine Folge von zwei aufwärts oder zwei abwärts darin verbleibt. Tatsächlich gibt es eine Menge Überfluss. Wenn wir eine Obergrenze für die Eingabelänge hätten, wäre es beispielsweise kürzer zu schreiben
j=999
.Überraschenderweise
i and' 'or c
war kürzer als üblich[' ',c][i==0]
. Beachten Sie, dassi
dies negativ sein kann, wodurch einige übliche Tricks vermieden werden.quelle
MATLAB, 116
Es ist ein Anfang. Die
j
undk
machen es einem im Nacken weh, da ich keinen Weg finde, mathematisch vonj^vk
zu zuzuordnen[-2 -1 1 2]
und mit MATLAB den Unicode nicht zu erkennen (anscheinend haben beide einen Wert von 26 in MATLAB. Go figure!), Gibt es Beim Mapping wurden viele Bytes verschwendet.Indem Sie sich von der @ xnors-Lösung inspirieren lassen, können Sie den Code um weitere 14 Zeichen reduzieren, indem Sie das Steuerzeichen in der for-Schleife zuordnen.
Es werden auch viele Bytes verschwendet, um zu versuchen, zu berücksichtigen, ob die Eingabezeichenfolge das Muster wieder unter den Index zurückschickt, bei dem es begonnen hat (möglicherweise könnte ich dieses Bit vereinfachen, wenn die Zeichenfolgenlänge begrenzt wäre).
Und in lesbarer Form:
quelle
b=[-2 -1 1 2](a==[106 107 94 118])
funktionieren Es funktioniert in Octave. Oder auch,b=[-2 -1 1 2](a-94==[12 13 0 24])
wenn Sie noch ein Byte abschneiden wollen!==
funktioniert das Verhalten der nicht mehr, und auch in MATLAB kann man kein()
nach dem anderen setzen[]
.+=
, fwiw.)JavaScript (ES6), 140
Testen Sie das folgende Snippet in einem EcmaScript 6-kompatiblen Browser (getestet in Firefox).
quelle
GS2, 34 Bytes
Dieser berechnet die Ausgabegrenzen korrekt, sodass kein übermäßiger Leerraum erzeugt wird. Hier ist meine Lösung in hex
Eine kleine Erklärung ist angebracht. Auf dem Stapel haben wir Benutzereingaben als Array von ASCII-Codes. Das Programm startet in einem String-Literal wegen des
05
. Auf geht's.GS2, 24 Bytes
Ich habe auch eine 24-Byte-Lösung, bei der die Berechnung der Ausgabegröße weniger wichtig ist und die am Ende zusätzliche Leerzeichen enthält. Ich bevorzuge jedoch die mit einem auf ein Minimum beschränkten Leerzeichen.
quelle
Wachsmalstift , 13 Bytes (nicht konkurrierend)
Probieren Sie es online! Verwendet die echten Pfeile, weil warum nicht.
Nicht konkurrierend, weil Crayon viel neuer ist als diese Herausforderung.
Wie es funktioniert
Crayon ist eine stapelbasierte Sprache, die entwickelt wurde, um ASCII-Herausforderungen zu meistern. Es basiert auf einer zweidimensionalen Ausgabe "canvas" und einem "crayon", einem Cursor, der sich auf dieser Zeichenfläche bewegt. Alles, was zur Ausgabe gesendet wird, wird an der Position des Stiftes und in der Richtung, in die der Stift zeigt, auf die Leinwand gezeichnet. Standardmäßig zeigt der Stift nach Osten (nach rechts).
quelle
pb - 136 Bytes
Verwendet
k
undj
anstelle von▲
und▼
.Ein paar Notizen:
Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.
Ich folge dieser Regel! pb verwendet das Konzept eines "Pinsels", um Zeichen auszugeben. Der Pinsel bewegt sich um die "Leinwand" und kann ein Zeichen direkt darunter drucken. Die eigentliche Implementierung druckt das Zeichen jedoch mit Leerzeichen und Zeilenumbrüchen.You are allowed trailing spaces and/or empty lines
. Dies hat mehrere Gründe:n
beginnt sie also beiY=3n+1
. Das-1
ist , weil es geht nach unten3n
ausY=-1
, und abY=2n-1
für eine Eingabe aller ausfälltk
.Sie können dieses Programm auf YouTube in Aktion sehen!Diese Version ist insofern leicht modifiziert, als es nur noch geht
n-1
. Dies funktioniert für diese Eingabe, schlägt jedoch für andere fehl. Es macht jedoch viel schöner zu erfassen.Mit Kommentaren:
quelle
Ceylon, 447 Bytes
Oder mit Zeilenumbrüchen für "Lesbarkeit":
import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}
Dies funktioniert sowohl mit der Eingabe ▲ / ▼ als auch mit der Eingabe j / k (Wenn wir nur eine davon unterstützen müssten, wäre das Programm 8 Byte kürzer). Die letzte Ausgabezeile ist leer, als sich die Startposition darauf befand (dh die erste Eingabe war ein
▲
oder^
und wir sind später nie wieder darunter gekommen). Eingaben, bei denen es sich nicht um eines der angegebenen Zeichen handelt, werden einfach so gedruckt, wie sie sind, ohne die Zeile zu wechseln:→
Hier ist eine formatierte Version (753 Bytes):
Dies ist ein fast unkompliziertes "objektorientiertes" Programm ... die (lokale) Klasse
L
(Zeilenpuffer) speichert eine Textzeile (int
) sowie (nullbare) Zeiger auf das nächste (n
) und vorherige (p
) Linie. Die (nicht nullbaren) Attributeu
(für oben) undd
(für unten) initialisieren diese bei Bedarf (mit einem Rückwärtszeiger auf sich selbst) und verfolgen in diesem Fall auch die erste und letzte Zeile insgesamt (inf
und)l
Variablen ).Das
a
(append) -Methode hängt ein Zeichen an diese Zeile an, einschließlich einiger eventuell erforderlicher Leerzeichen.c
ist die aktuelle Zeile. Wir analysieren die Eingabezeichenfolge (mitreadLine
als Eingabe eine Zeile verwendet werden sollte) mit einer switch-Anweisung, die die aktuelle Zeile aktualisiert, und rufen dann die append-Methode auf.Nachdem das Parsen abgeschlossen ist, werden die Zeilen von der ersten bis zur letzten durchlaufen und jeweils gedruckt. (Dies zerstört die
f
Zeiger, wenn er später benötigt würde, hätten wir dafür eine separate Variable verwenden müssen.)Einige Tricks zum Golfen:
Einige Dinge, die in anderen Sprachen Schlüsselwörter wären, sind eigentlich nur Bezeichner im
ceylon.language
Paket und können mit einem Alias-Import umbenannt werden - wir haben dies für die Annotationenshared
(verwendet 5 ×) undvariable
(verwendet 6 ×) sowie für das Objekt verwendetnull
(verwendet 4 ×):(Trivia: Der Formatierer in der Ceylon-IDE formatiert einige integrierte Sprachanmerkungen zwischen ihnen
variable
undshared
stellt sie in die gleiche Zeile wie die mit Anmerkungen versehene Deklaration, im Gegensatz zu benutzerdefinierten Anmerkungen, die in einer separaten Zeile über der Deklaration stehen.) macht die formatierte Version des Golf-Programms unlesbar, daher habe ich die Alias-Importe für diese Version zurückgesetzt.)this
,void
,case
,else
Sind tatsächlich verwendeten Keywords und auf diese Weise nicht umbenannt werden kann, undInteger
,String
undCharacter
erscheinen nur je einmal, so gibt es nichts durch den Import gewonnen werden soll.Ursprünglich hatte ich auch eine separate ScreenBuffer-Klasse (die die verknüpfte Liste der Zeilenpuffer, den aktuellen Index usw. verfolgte), aber da es immer nur ein Objekt davon gab, wurde es entfernt optimiert.
Die Screenbuffer Klasse auch hatte
up
unddown
Methoden, die von dem Parser genannt wurden (und gerade tatencurrentLine = currentLine.up
jeweilscurrentLine = currentLine.down
). Es zeigte sich, dass die direkte Ausführung im Parser-Schalter kürzer ist. Es durfte auch schreibencurrentLine = currentLine.up.up
(was später wurdec = c.u.u
) stattcurrentLine = currentLine.up;currentLine = currentLine.up
.Ursprünglich haben wir den aktuellen Index als Argument an die Append-Methode übergeben (und sogar an den Parser aus der Schleife) - eine Variable in der enthaltenden Funktion ist kürzer.
Ursprünglich verwendete meine printAll-Methode den aktuellen Zeiger und bewegte ihn zuerst nach oben, bis die aktuelle Zeile leer war, und dann nach unten, während jede Zeile gedruckt wurde. Dies brach ab, wenn ▲ und ▼ zum Überspringen von Zeilen verwendet wurden, sodass wir stattdessen explizit etwas an diese übersprungenen Zeilen anhängen mussten. Das Verfolgen der ersten / letzten Zeile erwies sich als einfacher (obwohl es erforderlich war, zwei print-Anweisungen zu verwenden, da es in Ceylon keine do-while-Schleife gibt).
Ursprünglich hatte ich so etwas:
process.readLine
null
Gibt zurück, wenn keine Zeile vorhanden ist, die gelesen werden kann (da die Eingabe geschlossen wurde), und der Ceylon-Compiler fordert mich auf, dies zu überprüfen, bevor ich darauf zugreifeinput
. Da ich in diesem Fall nichts tun möchte, kann ich äquivalent denelse
Operator verwenden, der sein erstes Argument zurückgibt, wenn er nicht null ist, und ansonsten sein zweites Argument, wobei die Variable und die if-Anweisung gespeichert werden. (Dies würde auch ermöglichen es uns , eine Standard - Eingabe zu kodieren für die Prüfung:for (x in process.readLine() else "^^▲^v▼▲^^v") {
)quelle
JavaScript (ES6), 228 Byte
Nun, hier ist eine (ziemlich lange) rekursive Lösung, die alle angegebenen Testfälle besteht. Es war eine schöne Herausforderung. Dies verwendet
k
undj
anstelle von▼
und▲
.Testschnipsel
Obwohl die Übermittlung selbst nur verarbeiten kann
k,j
, kann das folgende Snippet sowohlk,j
als auch verarbeiten▼,▲
.quelle