Diese Frage hat ihre Höhen und Tiefen


33

Die Eingabe besteht aus folgenden Zeichen:

  • ^: Geh eins hoch
  • v: Geh einen runter
  • oder k: Geh zwei hoch
  • oder j: 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[Bsind 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

1
Sind Leerzeichen erlaubt? Leerzeilen?
26.

2
Was ist mit Sprachen, die Unicode nicht unterstützen? Können alternative Zeichen verwendet werden?
Türklinke

1
@xnor Nachgestellte Leerzeichen und / oder Leerzeilen sind erlaubt.
Absinth

2
@Doorknob Ich erlaube jzweimal runter und kzweimal rauf zu gehen.
Absinth

1
@xnor Mein schlechtes: / Der Kommentar ist korrekt und ich habe die Regeln falsch bearbeitet. Wird jetzt reparieren.
Absinth

Antworten:


9

Pyth, 27 Bytes

jCm.<.[*5lzd\ =+Ztx"v ^k"dz

Probieren Sie es online aus: Demo oder Test Suite

Ich benutze kund janstelle 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.

j.sCm.<.[*5lzd\ =+Ztx"v ^k"dz]*lzd

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung:

jCm.<.[*5lzd\ =+Ztx"v ^k"dz  implicit: Z = 0
  m                       z  map each char d from input string z to:
                  x"v ^k"d     find d in the string "v ^k", -1 if not found
                 t             -1, that gives -2 for j, -1 for v, 1 for ^ and 2 for k
              =+Z              add this number to Z
     .[*5lzd\                  append spaces on the left and on the right of d, 
                               creating a 5*len(input_string) long string
   .<           Z              rotate this string to the left by Z chars
jC                           transpose and print on lines

16

Nicht lesbar , 2199 2145 2134 2104 2087 2084 Bytes

Unterstützt sowohl k/ jals 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:

// Initialize memory pointer. Why 5 will be explained at the very end!
ptr = 5

// FIRST PASS:
// Read all characters from stdin, store them in memory, and also keep track of the
// current line number at each character.

// We need the +1 here so that EOF, which is -1, ends the loop. We increment ptr by 2
// because we use two memory cells for each input character: one contains the actual
// character (which we store here); the other will contain the line number at which the
// character occurs (updated at the end of this loop body).
while ch = (*(ptr += 2) = read) + 1:

    // At this point, ch will be one more than the actual value.
    // However, the most code-economical way for the following loop is to
    // decrement inside the while condition. This way we get one fewer
    // iteration than the value of ch. Thus, the +1 comes in handy.

    // We are now going to calculate modulo 4 and 5. Why? Because
    // the mod 4 and 5 values of the desired input characters are:
    //
    //  ch  %5  %4
    //  ^   1
    //  v   2
    //  k   3
    //  j   4
    //  ▲   0   2
    //  ▼   0   0
    //
    // As you can see, %5 allows us to differentiate all of them except ▲/▼,
    // so we use %4 to differentiate between those two.

    mod4 = 0      // read Update 2 to find out why mod5 = 0 is missing
    while --ch:
        mod5 = mod5 ? mod5 + 1 : -4
        mod4 = mod4 ? mod4 + 1 : -3

    // At the end of this loop, the value of mod5 is ch % 5, except that it
    // uses negative numbers: -4 instead of 1, -3 instead of 2, etc. up to 0.
    // Similarly, mod4 is ch % 4 with negative numbers.

    // How many lines do we need to go up or down?
    // We deliberately store a value 1 higher here, which serves two purposes.
    // One, as already stated, while loops are shorter in code if the decrement
    // happens inside the while condition. Secondly, the number 1 ('""") is
    // much shorter than 0 ('""""""""'""").
    up = (mod5 ? mod5+1 ? mod5+3 ? 1 : 3 : 2 : mod4 ? 3 : 1)
    dn = (mod5 ? mod5+2 ? mod5+4 ? 1 : 3 : 2 : mod4 ? 1 : 3)

    // As an aside, here’s the reason I made the modulos negative. The -1 instruction
    // is much longer than the +1 instruction. In the above while loop, we only have
    // two negative numbers (-3 and -4). If they were positive, then the conditions in
    // the above ternaries, such as mod5+3, would have to be mod5-3 etc. instead. There
    // are many more of those, so the code would be longer.

    // Update the line numbers. The variables updated here are:
    // curLine = current line number (initially 0)
    // minLine = smallest linenum so far, relative to curLine (always non-positive)
    // maxLine = highest linenum so far, relative to curLine (always non-negative)
    // This way, we will know the vertical extent of our foray at the end.

    while --up:
        curLine--
        minLine ? minLine++ : no-op
        maxLine++

    while --dn:
        curLine++
        minLine--
        maxLine ? maxLine-- : no-op

    // Store the current line number in memory, but +1 (for a later while loop)
    *(ptr + 1) = curLine + 1

// At the end of this, minLine and maxLine are still relative to curLine.
// The real minimum line number is curLine + minLine.
// The real maximum line number is curLine + maxLine.
// The total number of lines to output is maxLine - minLine.

// Calculate the number of lines (into maxLine) and the real minimum
// line number (into curLine) in a single loop. Note that maxLine is
// now off by 1 because it started at 0 and thus the very line in which
// everything began was never counted.
while (++minLine) - 1:
  curLine--
  maxLine++

// Make all the row numbers in memory positive by adding curLine to all of them.
while (++curLine) - 1:
  ptr2 = ptr + 1
  while (ptr2 -= 2) - 2:    // Why -2? Read until end!
    *ptr2++

// Finally, output line by line. At each line, we go through the memory, output the
// characters whose the line number is 0, and decrement that line number. This way,
// characters “come into view” in each line by passing across the line number 0.
while (--maxLine) + 2:    // +2 because maxLine is off by 1
  ptr3 = 5
  while (ptr -= 2) - 5:
    print (*((ptr3 += 2) + 1) = *(ptr3 + 1) - 1) ? 32 : *ptr3   // 32 = space
  ptr = ptr3 + 2
  print 10  // newline

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 = 1wird 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:

-1  '""""""""'""""""""'"""  22
 0  '""""""""'"""           13
 1  '"""                     4
 2  '""'"""                  7
 3  '""'""'"""              10
 4  '""'""'""'"""           13
 5  '""'""'""'""'"""        16
 6  '""'""'""'""'""'"""     19
 7  '""'""'""'""'""'""'"""  22

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 mod5die 10-fache. Wir brauchen aber mod5nach der ersten while-Schleife nichts mehr, sodass wir den gleichen Speicherplatz anderen Variablen zuweisen können, die wir später verwenden. Das sind ptr2und ptr3. 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, chwird es nicht mehr benötigt. upund dnkommen die gleiche Anzahl von Malen, so ist entweder in Ordnung. Lassen Sie uns merge chmit up.

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:

-1    dn
 0                      ← ptr or minLine?
 1    mod5, ptr2, ptr3
 2    curLine
 3    maxLine
 4                      ← ptr or minLine?
 5    ch, up
 6    mod4
 7... [data block]

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 ptrund minLineumgekehrt 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 sein ptroder sollte es sein minLine? Das stimmt, minLinewird an dieser Stelle auch nicht mehr verwendet! Somit ist die Variable # 4 minLineund wir können sie sicher dekrementieren und keinen Schaden anrichten!

UPDATE 1! Golf von 2199 bis 2145 Bytes durch Realisierung, dndie auch mit zusammengeführt werden können mod5, obwohl mod5noch in der Berechnung des Wertes für verwendet wird dn! Neue Variablenbelegung ist jetzt:

 0    ptr
 1    mod5, dn, ptr2, ptr3
 2    curLine
 3    maxLine
 4    minLine
 5    ch, up
 6    mod4
 7... [data block]

UPDATE 2! Wurde zwischen 2145 und 2134 Byte verarbeitet, indem erkannt wurde, dass mod5die Variable dn, die jetzt in einer while-Schleife bis 0 gezählt wird, mod5nicht 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, mod4da wir nie mit mod4+2usw. testen . Daher führt die Änderung mod4 ? mod4+1 : -3von mod4 ? mod4-1 : 3zu 2110 Byte. Zweitens mod4können wir , da immer 0 oder 2 ist, mod4auf 2 anstelle von 0 initialisieren und die beiden Ternären ( mod4 ? 3 : 1anstelle von mod4 ? 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 also up = ((while --ch: [...]) ? mod5+1 ? [...](und innerhalb dieser while-Schleife berechnen wir mod4zuerst, das mod5ist also die letzte Anweisung).

UPDATE 5! Golf von 2087 bis 2084 Bytes durch die Erkenntnis, dass ich anstelle des Ausschreibens der Konstanten 32und 10(Leerzeichen und Zeilenvorschub) die Nummer 10 in der (jetzt nicht verwendeten) Variablen # 2 speichern kann (nennen wir es ten). Anstatt zu ptr3 = 5schreiben ten = (ptr3 = 5) + 5, 32wird ten+22und print 10wird print ten.


Dies ist ... schrecklich ... +1
kirbyfan64sos

6

CJam, 37 Bytes

r_,2*:L3*S*f{\_iImd8-g\8>)*L+:L\t}zN*

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

r_     e# Read a token from STDIN and push a copy.
,2*:L  e# Compute its length, double it and save it in L.
3*S*   e# Push a string of 6L spaces.
f{     e# For each character C in the input, push C and the string of spaces; then
  \    e#   Swap C with the string of spaces.
  _i   e#   Push a copy of C and cast it to integer.
  Imd  e#   Push quotient and remainder of its division by 18.
  8-g  e#   Push the sign((C%18) - 8). Gives -1 for ^ and ▲, 1 for v and ▼.
  \    e#   Swap the result with the quotient.
  8>)  e#   Push ((C/18) > 1) + 1. Gives 2 for ▲ and ▼, 1 for ^ and v.
  *    e#   Multiply both results. This pushes the correct step value.
  L+:L e#   Add the product to L, updating L.
  \t   e#   Replace the space at index L with C.
}      e# We've built the columns of the output.
z      e# Zip; transpose rows with columns.
N*     e# Join the rows, separating by linefeeds.

Ich denke, es wäre nur fair, ausdrücklich als Einschränkung zu erwähnen, dass Ihre Lösung vor und nach der gewünschten Ausgabe reichlich zusätzliche Zeilenumbrüche erzeugt ...
Timwi

Hinzugefügt. (Ich hielt es nicht für notwendig, da das OP ausdrücklich Leerzeilen erlaubte.)
Dennis

3

Python 2, 102

s=input()
j=3*len(s)
exec"w='';i=j=j-1\nfor c in s:i-='kv_^j'.find(c)-2;w+=i and' 'or c\nprint w;"*2*j

Druckt zeilenweise.

Durchläuft Zeichen in der Eingabe und verfolgt die aktuelle Höhe. Die Höhe wird von einem der +2, +1, -1, -2berechneten Werte aktualisiert 'kv_^j'.find(c)-2. Es gibt wahrscheinlich eine Mod-Kette, die kürzer ist

Wenn 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 cwar kürzer als üblich [' ',c][i==0]. Beachten Sie, dass idies negativ sein kann, wodurch einige übliche Tricks vermieden werden.


2

MATLAB, 116

function o=u(a)
x=0;y=1;o='';for c=a b=find(c=='j^ vk')-3;y=y+b;if y<1 o=[zeros(1-y,x);o];y=1;end
x=x+1;o(y,x)=c;end

Es ist ein Anfang. Die jund kmachen es einem im Nacken weh, da ich keinen Weg finde, mathematisch von j^vkzu 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:

function o=u(a)
%We start in the top left corner.
x=0; %Although the x coordinate is 1 less than it should be as we add one before storing the character
y=1;
o=''; %Start with a blank array
for c=a
    %Map the current character to [-2 -1 1 2] for 'j^vk' respectively.
    b=find(c=='j^ vk')-3;
    y=y+b; %Offset y by our character
    if y<1 %If it goes out of range of the array
        o=[zeros(1-y,x); o]; %Add enough extra lines to the array. This is a bit of a hack as 0 prints as a space in MATLAB.
        y=1; %Reset the y index as we have now rearranged the array
    end
    x=x+1; %Move to the next x coordinate (this is why we start at x=0
    o(y,x)=c; %Store the control character in the x'th position at the correct height.
end

Würde 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!
wchargin

@WChargin funktioniert nicht in MATLAB. Leider ==funktioniert das Verhalten der nicht mehr, und auch in MATLAB kann man kein ()nach dem anderen setzen [].
Tom Carpenter

Hmm ... du könntest die Sprache in Octave ändern! :) (Octave hat auch +=, fwiw.)
wchargin

@WChargin Das ist Betrug = P Aber ich stimme zu, Octave hat viele Verknüpfungen, die Matlab nicht hat.
Fehler

2

JavaScript (ES6), 140

Testen Sie das folgende Snippet in einem EcmaScript 6-kompatiblen Browser (getestet in Firefox).

f=s=>[...s].map(c=>{for(t=r[y+=c>'▲'?2:c>'v'?-2:c>'^'?1:-1]||x;y<0;y++)r=[,...r];r[y]=t+x.slice(t.length)+c,x+=' '},y=0,r=[x=''])&&r.join`
`

// Less golfed

f=s=>(
  y=0,
  x='',
  r=[],
  [...s].forEach( c =>
    {
      y += c > '▲' ? 2 : c > 'v' ? -2 : c > '^' ? 1 : -1;
      t = r[y] || x;
      while (y < 0)
      {
        y++;
        r = [,...r]
      }  
      r[y] = t + x.slice(t.length) + c;
      x += ' '
    }
  ),
  r.join`\n`
)  


//Test

;[
  '^^▲^v▼▲^^v'
, '▲v^v^v^v^v^v^v^v▲'
, '^^^^^^^▲▲▲▼▼▼vvvvvv'
, 'v^^vv^^vvv^v^v^^^vvvv^^v^^vv'  
].forEach(t=>document.write(`${t}<pre>${f(t)}</pre>`))
pre { border:1px solid #777 }


1

GS2, 34 Bytes

Dieser berechnet die Ausgabegrenzen korrekt, sodass kein übermäßiger Leerraum erzeugt wird. Hier ist meine Lösung in hex

5e 20 76 6a 05 3e 26 ea 30 e0 6d 40 28 26 cf d3
31 e9 d0 4d 42 5e e2 b1 40 2e e8 29 cf d3 5c e9
9a 54

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.

  5e 20 76 6a      # ascii for "^ vj"
  05               # finish string literal and push to stack
  3e               # index - find index in array or -1 if not found
  26               # decrement
ea                 # map array using block of 3 instructions (indented)

  30               # add 
e0                 # create a block of 1 instruction
6d                 # scan (create running total array of array using block)
40                 # duplicate top of stack
28                 # get minimum of array
26                 # decrement
cf                 # pop from stack into register D (this is the "highest" the path goes)

  d3               # push onto stack from register D
  31               # subtract
e9                 # map array using block of 2 instructions

d0                 # push onto stack from register A (unitialized, so it contains stdin)

  4d               # itemize - make singleton array (also is single char string)
  42               # swap top two elements in stack
  5e               # rjust - right justify string
e2                 # make block from 3 instructions
b1                 # zipwith - evaluate block using parallel inputs from two arrays
40                 # duplicate top of stack

  2e               # get length of array/string
e8                 # map array using block of 1 instruction
29                 # get maximum of array
cf                 # pop from stack into register D (this is the "lowest" the path goes)

  d3               # push from register D onto stack
  5c               # ljust - left justify string
e9                 # map array using block of two instructions
9a                 # transpose array of arrays
54                 # show-lines - add a newline to end of each element in array

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.

5e 20 76 6a 05 3e 26 ea 30 e0 6d d0 08 4d 42 d1
30 5e d1 5c 09 b1 9a 54

1

Wachsmalstift , 13 Bytes (nicht konkurrierend)

O"^ vj"\CynIq

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).

O"^ v▼"\CynIq   Implicit: input string is on top of the stack
O               For each char I in the input string:
 "^ v▼"          Push this string.
       \         Swap the top two items (so I is on top).
        C        Take the index of I in the string.
                 This returns 3 for ▼, 2 for v, 0 for ^, and -1 for ▲.
         y       Move the crayon by this number of spaces on the Y-axis (south).
          n      Move the crayon one position north.
                 The crayon has now been translated 2 positions south for ▼,
                 1 south for v, 1 north for ^, and 2 north for ▲.
           Iq    Draw I at the crayon. This automatically moves the crayon forward
                 by the length of I, which is 1 in this case.

0

pb - 136 Bytes

^w[B!0]{>}v[3*X]<[X]<b[1]^[Y]^>w[B!0]{t[B]<vw[B=0]{v}>w[T=107]{^^b[T]t[0]}w[T=94]{^b[T]t[0]}w[T=118]{vb[T]t[0]}w[T!0]{vvb[T]t[0]}^[Y]^>}

Verwendet kund janstelle 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.
  • Ich würde mich nicht mit dieser Herausforderung beschäftigen, obwohl ich dachte, dass es mit pb Spaß machen würde, bis ich das Urteil sah You are allowed trailing spaces and/or empty lines. Dies hat mehrere Gründe:
    • pb kann nicht nicht haben Leerzeichen. Es wird immer eine rechteckige Ausgabe erzeugt, die bei Bedarf mit Leerzeichen aufgefüllt wird.
    • Dieses Programm erzeugt viele Leerzeilen. Es ist nicht bekannt, wie hoch die Ausgabe sein wird, wenn sie anfängt, sie zu erstellen. Bei einer Eingabe von Länge nbeginnt sie also bei Y=3n+1. Das -1ist , weil es geht nach unten 3naus Y=-1, und ab Y=2n-1für eine Eingabe aller ausfällt k.

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:

^w[B!0]{>}             # Go to the end of the input
v[3*X]                 # Go down 3 times the current X value
<[X]<                  # Go to X=-1 (off screen, won't be printed)
b[1]                   # Leave a non-zero value to find later
^[Y]^>                 # Back to the beginning of the input
w[B!0]{                # For every byte of input:
    t[B]                 # Copy it to T
    <vw[B=0]{v}>         # Go 1 to the right of the character to the left
                         # (either the last one printed or the value at X=-1)
                         # Move the correct amount for each character and print it:
    w[T=107]{^^b[T]t[0]} # k
    w[T=94]{^b[T]t[0]}   # ^
    w[T=118]{vb[T]t[0]}  # v
    w[T!0]{vvb[T]t[0]}   # j (Every other possibility sets T to 0, so if T is not 0
                         #    it must be j. T!0 is shorter than T=106)
    ^[Y]^>               # To the next byte of input to restart the loop
}

0

Ceylon, 447 Bytes

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);}}

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:

v^^vv^^vvv^v^v^^^Hellovvvv^^v^^vv

  ^   ^         ^Hello
 ^ v ^ v       ^      v       ^
v   v   v ^ ^ ^        v   ^ ^ v
         v v v          v ^ v   v
                         v

Hier ist eine formatierte Version (753 Bytes):

shared void y() {
    variable L c;
    variable L f;
    variable L l;
    variable Integer i = 0;
    class L(variable L? p, variable L? n) {
        shared variable String t = "";
        shared L u => p else (f = p = L(null, this));
        shared L d => n else (l = n = L(this, null));
        shared void a(Character c) => t = t + " ".repeat(i - t.size) + c.string;
    }
    f = l = c = L(null, null);
    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 ist ein fast unkompliziertes "objektorientiertes" Programm ... die (lokale) Klasse L(Zeilenpuffer) speichert eine Textzeile (in t) sowie (nullbare) Zeiger auf das nächste ( n) und vorherige ( p) Linie. Die (nicht nullbaren) Attribute u(für oben) und d(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 (in fund)l Variablen ).

Das a (append) -Methode hängt ein Zeichen an diese Zeile an, einschließlich einiger eventuell erforderlicher Leerzeichen.

cist 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 dief 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.languagePaket und können mit einem Alias-Import umbenannt werden - wir haben dies für die Annotationen shared(verwendet 5 ×) und variable(verwendet 6 ×) sowie für das Objekt verwendet null(verwendet 4 ×):

    import ceylon.language{o=null,v=variable,s=shared}
    

    (Trivia: Der Formatierer in der Ceylon-IDE formatiert einige integrierte Sprachanmerkungen zwischen ihnen variableund sharedstellt 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, elseSind tatsächlich verwendeten Keywords und auf diese Weise nicht umbenannt werden kann, und Integer, Stringund Charactererscheinen 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 upund downMethoden, die von dem Parser genannt wurden (und gerade taten currentLine = currentLine.upjeweils currentLine = currentLine.down). Es zeigte sich, dass die direkte Ausführung im Parser-Schalter kürzer ist. Es durfte auch schreiben currentLine = currentLine.up.up(was später wurde c = c.u.u) statt currentLine = 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:

      String? input = process.readLine();
      if(exists input) {
         for(x in input) {
             ...
         }
      }
    

    process.readLinenullGibt 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 zugreife input. Da ich in diesem Fall nichts tun möchte, kann ich äquivalent den elseOperator 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") {)


0

JavaScript (ES6), 228 Byte

E=(r,p=(' '[M='repeat'](Z=r.length)+',')[M](Z*4),i=Z*2,k=0)=>Z>k?E(r,(p.split(',').map((o,q)=>q==i?o.slice(0,k)+r[k]+o.slice(k++):o)).join`,`,i+(H={'^':-1,k:-2,j:2,v:1})[r[k]],k):p.split(',').join`
`.replace(/\s+\n$|^\s+\n/g,'')

Nun, hier ist eine (ziemlich lange) rekursive Lösung, die alle angegebenen Testfälle besteht. Es war eine schöne Herausforderung. Dies verwendet kund janstelle von und .

Testschnipsel

Obwohl die Übermittlung selbst nur verarbeiten kann k,j, kann das folgende Snippet sowohl k,jals auch verarbeiten ▼,▲.

E=(r,p=(' '[M='repeat'](Z=r.length)+',')[M](Z*4),i=Z*2,k=0)=>Z>k?E(r,(p.split(',').map((o,q)=>q==i?o.slice(0,k)+r[k]+o.slice(k++):o)).join`,`,i+(H={'^':-1,k:-2,j:2,v:1})[r[k]],k):p.split(',').join`
`.replace(/\s+\n$|^\s+\n/g,'')
Input: <input type="text" oninput=o.textContent=E(this.value.replace(/▲/g,'k').replace(//g,'j'))></input>
<pre id='o'></pre>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.