Questa domanda ha i suoi alti e bassi


33

L'input sarà composto dai seguenti caratteri:

  • ^: Vai su uno
  • v: Scendi uno
  • oppure k: vai su due
  • oppure j: scendere due

Ad esempio, il seguente input:

^^▲^v▼▲^^v

produrrebbe il seguente output:

        ^
   ^   ^ v
  ▲ v ▲

 ^   ▼
^

Le sequenze di escape che spostano il cursore come \e[Bnon sono consentite. È necessario produrre l'output utilizzando spazi e newline.

Ecco alcuni altri casi di test.

▲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
Sono consentiti spazi finali? Linee vuote?
xnor

2
Che dire delle lingue che non supportano Unicode? È possibile utilizzare caratteri alternativi?
Maniglia della porta

1
@xnor Sono ammessi spazi finali e / o righe vuote.
assenzio

2
@Doorknob Ti permetterò jdi scendere due volte e anche kdi salire due volte.
assenzio

1
@xnor Mio cattivo: / Il commento è corretto e ho modificato le regole in modo errato. Risolverà ora.
assenzio

Risposte:


9

Pyth, 27 byte

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

Provalo online: Dimostrazione o Test Suite

Io uso ke jinvece di e . Ci sono molte linee vuote iniziali e finali. Devi cercare un po 'per trovare l'immagine. Ecco una versione di 34 byte , che rimuove tutte le righe vuote iniziali e finali.

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

Provalo online: Dimostrazione o Test Suite

Spiegazione:

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

Illeggibile , 2199 2145 2134 2104 2087 2084 byte

Supporta sia k/ jche / sintassi .

Nella buona tradizione illeggibile, ecco il programma formattato in caratteri proporzionali, per offuscare la distinzione tra apostrofi e virgolette doppie:

' '' '' ''' "" "" "" "" ' '' ' ' '''' ' ' '''' "' '' "' '' ''" ' '' '' ''' "" ' ''' "" ' ''' "" " ' '''" "" "" " ' '' '' '''" "" "" "" " ' '' ' ' '''' " ' '' '' '' ' ' '' '' '' '''' '''" "" "" "" "" " ' '' '''" "" " ' '' ''' '' ''' "" "" ' '' '' ''' "" ' ''' "" ' ''' "" ' '' ' ' '''' ''' "" "" "" ' ''' "" ' ''' "" ' '' "' '' '' '' '' "' '' '' ' ' '' '' '''' ' ' ''''"'" " ' '' ' ' '' '' '' '''' '' '' '''" " ' '''" " ' '''" "" ' '' ''' "" """" ' '''" " ' '''" " ' '''" "" ' '' '' '' '' "' '' '' '' ' ' '''' ' ' ''''" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" ' ''' "" ' ''' "" " ' '''" "' "" " ' '' '' '''" "" ' '' '' '' '' "' '' '' ''" ' '' ' ' '''' '' '' '''"" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" ' '' '' '' '' ' ' '''' '' '' ''' "" " ' '' '' '' '' ' ' '''' ' ' '''' '' "" "" ' '' ' ' '' ' ' '''' ' ' '' ' ' '''' '''' '' '' '' '''' '' '' ''' ''' "" ' ''' "" ' ''' "" " ' '' ' ' '''' ' ' '' ' ' '' '' '''' '''' '' '' "" "" ' '' '' '' "' '' "' '' '' '' '' ' ' ''''" ' '' '' ''"' '' "' '' ''" "" "" ' ''' "" ' ''' "" ' '' '' '' "' '' "' '' ' ' ''''"' '' ' ' ''''"" ' '' '' '' '' ' ' '' '' '' ' ' '''' ' ' '''' ' ' '''' '''' ' ' '''' '''" "" ' '' '' ' ' '' '' '''' ' ' '''' ' ' '''' ''' "" "" "" "" ' '' '' '' "'" " ' '''" " ' '''" "" ' '' ''' "" "" ' '' '' '' '' "' '' '' '' ' ' ''''"' ''' "" " ' '' '' '''" " ' '''" " ' '' ' ' '''' '' '' '''" " ' '''" " ' '' " ' '' ' ' '' '' '''' ' ' '''' '''" "' '' '' '' ' ' ''''" ' '' "' '' '' '' ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" " ' '' '' ' ' '' '' '''' '''"" "" "" "" ' '' '' '' "' '' ' ' '' '''' '' ' ' '' '' '''' ' ' '''' "' ''" ' '' '' '' ''' "" "" "" " ' '''" " ' '''" "" ' '' '' '' '' "' '' '' '' "'" " ' '''" "" ' '' '' ''' "" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' ""' '' "' '' ' ' '' '' '''' ' ' '' ' ' '''' '' '' '''' "' '' ' ' '' '' ''''" ' '' '' '' ' ' '' '' '' '''' ''' "" ' '' '' '' ' ' '''' ''' "" "" " ' '' '' "" "" ' '' '' ''' "" ' ''' "" ' '' ' ' '''' '' '' ''' "" ' ''' "" ' ''"' '' ''' "" "" "" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" " ' '' '' '' ' ''' "" ' '' ' ' '''' '' '' ''' "" ' ''' "" " ' '' '' ' ' '' '' '' '''' '' "" " ' '''" "" ' ''' "" "" "" " ' '''" "" ' '' ''' "" "" "" ' '' " ' '''"" "" "" " ' '' '' '' '''" "" ' '' '' ' ' '' '' '' '''' '' '' '' "' '' ''" "' '' ' ' '' '' '' '''' '' '' ''" ' '' '' '' "' '' ' ' '' '' '''' '' '' '' ' '' ' ' '''' '' '' ''' "" "" "" "' ''"' '' '' ' ' '''' " ' '' '' '''"" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" ' '' ' ' '' '''' '' "' ''" " ' '' '' '''" "' '' ' ' '''' ' ' '''' ' ' '''' '' ''" ' '' ' ' '''' "' '' ' ''' "" " ' '' '' ' ' '' '' '' '''' '' '' '' ' ' '' '' '' '''' '' '' ''" ' '' '' '' '''" "" "" " ' '' '' '' '''" "" ' '' '' '' ''' "" "" "" "" '" "" "" "" ' '' '' '' ''' "" "'"' '' '' '' '' ' ' '' '' '''' ' ' '' '' '''' "" ' ''' "" ' '' '' '' ' ' '' ' ' '' '' '' '''' '' '' '''' "' '' '' ''"' '' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' ''''"' '' ' ''' "" ' ''' "" ' ''' "" ' ''' "" "" "" " ' '''" "" ' '' '' '' "' '' ''" "" ' '' ' ' '' '' '''' '' '' '' "' '' ' ' '''' "' '' '' ''" ' ''"' "' ''"" "" " ' '''" ""

Questa è stata una sfida incredibile. Grazie per la pubblicazione!

Spiegazione

Per avere un'idea di ciò che illeggibile può e non può fare, immagina Brainfuck con un nastro infinito in entrambe le direzioni, ma invece di un puntatore di memoria che sposta una cella alla volta, puoi accedere a qualsiasi cella di memoria dereferenziando un puntatore. Questo risulta molto utile in questa soluzione, sebbene altre operazioni aritmetiche - incluso il modulo - debbano essere eseguite manualmente.

Ecco il programma come pseudocodice con il commento del regista:

// 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

Questo per quanto riguarda la logica del programma. Ora dobbiamo tradurre questo in Illeggibile e usare alcuni trucchi golfistici più interessanti.

Le variabili sono sempre riferite numericamente in Illeggibile (ad esempio a = 1diventa qualcosa di simile *(1) = 1). Alcuni letterali numerici sono più lunghi di altri; il più corto è 1, seguito da 2, ecc. Per mostrare quanto sono più lunghi i numeri negativi, ecco i numeri da -1 a 7:

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

Chiaramente, vogliamo allocare la variabile # 1 a quella che si verifica più frequentemente nel codice. Nel primo ciclo while, questo è sicuramente mod5, che arriva 10 volte. Ma non abbiamo mod5più bisogno dopo il primo ciclo while, quindi possiamo riassegnare la stessa posizione di memoria ad altre variabili che useremo in seguito. Questi sono ptr2e ptr3. Ora la variabile viene referenziata 21 volte in totale. (Se stai cercando di contare tu stesso il numero di occorrenze, ricorda di contare qualcosa come a++due volte, una volta per ottenere il valore e una volta per impostarlo.)

C'è solo un'altra variabile che possiamo riutilizzare; dopo aver calcolato i valori del modulo, chnon è più necessario. upe dnvenire lo stesso numero di volte, quindi va bene lo stesso. Uniamoci chcon up.

Questo lascia un totale di 8 variabili uniche. Potremmo allocare le variabili da 0 a 7 e quindi avviare il blocco di memoria (contenente i caratteri e i numeri di riga) da 8. Ma! Dato che 7 ha la stessa lunghezza nel codice di −1, potremmo anche usare le variabili da −1 a 6 e avviare il blocco di memoria da 7. In questo modo, ogni riferimento alla posizione iniziale del blocco di memoria è leggermente più breve nel codice! Questo ci lascia con i seguenti compiti:

-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]

Ora questo spiega l'inizializzazione in alto: è 5 perché è 7 (l'inizio del blocco di memoria) meno 2 (l'incremento obbligatorio nella prima condizione while). Lo stesso vale per le altre due occorrenze di 5 nell'ultimo ciclo.

Si noti che, poiché 0 e 4 hanno la stessa lunghezza nel codice ptre minLinepotrebbero essere allocati in entrambi i modi. ... O potrebbero?

Che dire del misterioso 2 nel penultimo ciclo while? Questo non dovrebbe essere un 6? Vogliamo solo ridurre i numeri nel blocco dati, giusto? Una volta raggiunti i 6, siamo fuori dal blocco dati e dovremmo fermarci! Sarebbe una vulnerabilità di sicurezza di errore di bug buffer overflow errore!

Bene, pensa a cosa succede se non ci fermiamo. Diminuiamo le variabili 6 e 4. La variabile 6 è mod4. Viene utilizzato solo nel primo ciclo while e non è più necessario qui, quindi nessun danno fatto. Che dire della variabile 4? Cosa pensi, dovrebbe essere la variabile 4 ptro dovrebbe essere minLine? Esatto, minLinenon è più utilizzato neanche a questo punto! Quindi, la variabile # 4 è minLinee possiamo tranquillamente diminuirla e non fare danni!

AGGIORNAMENTO 1! Giocato a golf da 2199 a 2145 byte realizzando che dnpuò anche essere unito mod5, anche se mod5è ancora usato nel calcolo del valore per dn! La nuova assegnazione delle variabili è ora:

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

AGGIORNAMENTO 2! Giocato a golf da 2145 a 2134 byte rendendosi conto che, poiché mod5ora è nella stessa variabile di dn, che viene contato su 0 in un ciclo while, mod5non è più necessario inizializzare esplicitamente su 0.

AGGIORNAMENTO 3! Giocato a golf dal 2134 al 2104 byte realizzando due cose. In primo luogo, sebbene l'idea del "modulo negativo" sia valsa la pena mod5, lo stesso ragionamento non si applica mod4perché non testiamo mai contro mod4+2ecc. Pertanto, il passaggio mod4 ? mod4+1 : -3a mod4 ? mod4-1 : 3ci porta a 2110 byte. In secondo luogo, poiché mod4è sempre 0 o 2, possiamo inizializzare mod4a 2 invece di 0 e invertire i due ternari ( mod4 ? 3 : 1anziché mod4 ? 1 : 3).

AGGIORNAMENTO 4! Giocato a golf da 2104 a 2087 byte, rendendosi conto che il ciclo while che calcola i valori del modulo viene sempre eseguito almeno una volta, e in tal caso, Illeggibile consente di riutilizzare il valore dell'ultima istruzione in un'altra espressione. Quindi, invece di while --ch: [...]; up = (mod5 ? mod5+1 ? [...]ora abbiamo up = ((while --ch: [...]) ? mod5+1 ? [...](e all'interno di quel ciclo while, calcoliamo mod4prima, quindi questa mod5è l'ultima affermazione).

AGGIORNAMENTO 5! Giocato a golf dal 2087 al 2084 byte realizzando che invece di scrivere le costanti 32e 10(spazio e newline), posso memorizzare il numero 10 nella variabile (ora non utilizzata) n. 2 (chiamiamolo ten). Invece di ptr3 = 5scrivere ten = (ptr3 = 5) + 5, 32diventa ten+22e print 10diventa print ten.


Questo è ... terribile ... +1
kirbyfan64sos

6

CJam, 37 byte

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

Stampa righe vuote prima e dopo l'output desiderato, che è stato consentito dall'OP .

Provalo online nell'interprete CJam .

Come funziona

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.

Penso che sarebbe giusto affermare esplicitamente come avvertimento che la tua soluzione produce quantità abbondanti di nuove righe extra prima e dopo l'output desiderato ...
Timwi

Aggiunto. (Non pensavo fosse necessario dal momento che il PO ha esplicitamente consentito righe vuote.)
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

Stampa riga per riga.

Scorre i caratteri nell'input e tiene traccia dell'altezza corrente. L'altezza viene aggiornata da uno dei +2, +1, -1, -2come calcolato da 'kv_^j'.find(c)-2. Probabilmente c'è una catena di mod che è più corta

Quando l'altezza corrente è uguale al numero di linea (che può essere negativo), aggiungiamo il carattere corrente alla linea e altrimenti aggiungiamo uno spazio. Quindi, stampiamo la linea. In realtà, è più breve iniziare l'altezza al numero di riga corrente e sottrarre i cambiamenti di altezza, aggiungendo il carattere quando il valore colpisce 0.

I numeri di riga comprendono un intervallo sufficientemente ampio che una sequenza di up-due o down-due rimarrà al suo interno. In realtà, c'è una buona quantità di eccesso. Se avessimo un limite superiore sulla lunghezza dell'input, sarebbe più breve scrivere, diciamo j=999.

Sorprendentemente, i and' 'or cera più corto del solito [' ',c][i==0]. Nota che ipuò essere negativo, il che elimina alcuni trucchi abituali.


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

È un inizio L' je kne fanno un dolore al collo come non riesco a trovare un modo per matematicamente mappa da j^vka [-2 -1 1 2]e con MATLAB non riconoscendo l'Unicode (a quanto pare sia su e hanno un valore di 26 in MATLAB. Go figura in basso!), Ci sono molti byte sprecati durante la mappatura.

Ispirandosi alla soluzione @xnors, il codice può essere ridotto di altri 14 caratteri mappando il carattere di controllo all'interno del ciclo for.

Ci sono anche molti byte sprecati nel tentativo di tenere conto se la stringa di input restituisce il modello sotto l'indice in cui è iniziato (forse se ci fosse un limite alla lunghezza della stringa potrei semplificare quel bit).

E nella sua forma leggibile:

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

Funzionerebbe b=[-2 -1 1 2](a==[106 107 94 118])? Funziona in Octave. O anche b=[-2 -1 1 2](a-94==[12 13 0 24])se vuoi radere via un altro byte!
wchargin,

@WChargin non funziona in MATLAB. Sfortunatamente il comportamento degli ==arresti funziona, e anche in MATLAB non puoi mettere un ()dopo a [].
Tom Carpenter,

Hmm ... potresti cambiare la lingua in Octave! :) (Anche Octave +=, prima).
wchargin,

@WChargin Questo è barare = P Ma sono d'accordo, Octave ha molte scorciatoie che Matlab non ha.
Flawr,

2

JavaScript (ES6), 140

Prova a eseguire lo snippet di seguito in un browser compatibile con EcmaScript 6 (testato su 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 byte

Questo calcola correttamente i limiti di output, quindi non viene prodotto spazio bianco in eccesso. Ecco la mia soluzione in esadecimale

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

Una piccola spiegazione è in ordine. Sullo stack abbiamo l'input dell'utente come una matrice di codici ASCII. Il programma inizia in una stringa letterale a causa di 05. Eccoci qui.

  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 byte

Ho anche una soluzione a 24 byte che non si prende molta cura nel calcolo delle dimensioni dell'output e finisce con uno spazio extra. Preferisco quello con lo spazio bianco ridotto al minimo però.

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

Crayon , 13 byte (non concorrenti)

O"^ vj"\CynIq

Provalo online! Usa le vere frecce perché perché no.

Non competitiva perché Crayon è molto più recente di questa sfida.

Come funziona

Crayon è un linguaggio basato su stack progettato per essere killer nelle sfide dell'arte ASCII. È costruito attorno alla base di una "tela" di output bidimensionale e di un "pastello", un cursore che viaggia attorno a questa tela. Tutto ciò che viene inviato all'output viene disegnato sulla tela nella posizione del pastello e nella direzione in cui è rivolto il pastello. Per impostazione predefinita, il pastello punta ad est (a destra).

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 byte

^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]^>}

Usi ke jinvece di e .

Un paio di note:

  • Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.Seguo questa regola! pb usa il concetto di "pennello" per generare caratteri. Il pennello si sposta sulla "tela" e può stampare un personaggio immediatamente sotto di essa. Tuttavia, l'implementazione effettiva stampa il personaggio usando spazi e newline.
  • Non mi sarei preoccupato di questa sfida, anche se ho pensato che sarebbe stato divertente con pb fino a quando non ho visto la sentenza You are allowed trailing spaces and/or empty lines. Questo per un paio di motivi:
    • pb non può non avere spazi finali. Produce sempre output rettangolare, imbottitura con spazi se necessario.
    • Questo programma produce molte righe vuote. Non sa quanto sarà alta l'output quando inizia a crearla, quindi per un input di lunghezza ninizia a Y=3n+1. Il -1motivo è che sta scendendo 3nda Y=-1, e a partire da Y=2n-1fallisce per un input di tutto k.

Puoi guardare questo programma in azione su YouTube! Questa versione è leggermente modificata in quanto scende solo a n-1. Funziona per questo input, ma fallirà per gli altri. Tuttavia, cattura molto meglio.

Con commenti:

^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 byte

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

O con interruzioni di riga per "leggibilità": 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);}}

Funziona sia con l'ingresso ▲ / ▼ che con l'ingresso j / k (se dovessimo supportarne solo uno, il programma sarebbe più corto di 8 byte). L'ultima riga di output è vuota quando la posizione iniziale era su di essa (ovvero il primo input era un o ^e non ci siamo mai più spostati di seguito in seguito). Gli input che non sono uno dei caratteri specificati verranno semplicemente stampati così come sono, senza cambiare riga:

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

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

Ecco una versione formattata (753 byte):

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

Questo è un programma "orientato agli oggetti" quasi diretto ... la classe (locale) L(buffer di riga) memorizza una riga di testo (in t), nonché i puntatori (nullable) al prossimo ( n) e precedente ( p) linea. Gli attributi (non nullable) u(per up) e d(per down) inizializzano quelli se necessario (con un puntatore inverso a se stesso), e in questo caso tengono traccia della prima e dell'ultima riga in generale (nelle variabili fe l).

Il ametodo (append) aggiunge un carattere a questa riga, inclusi alcuni spazi eventualmente necessari.

cè la linea corrente. Analizziamo la stringa di input (usando readLinecome input dovrebbe essere su una riga) usando un'istruzione switch che aggiorna la riga corrente e quindi chiama il metodo append.

Al termine dell'analisi, ripetiamo le righe dalla prima all'ultima, stampandone ognuna. (Questo distrugge il fpuntatore, se fosse necessario in seguito, avremmo dovuto usare una variabile separata per questo.)

Alcuni trucchi usati per giocare a golf:

  • Alcune cose che in altre lingue sarebbero parole chiave sono in realtà solo identificatori nel ceylon.languagepacchetto e possono essere rinominate con un'importazione alias: l'abbiamo usata per le annotazioni shared(usato 5 ×) e variable(usato 6 ×), così come per l'oggetto null(usato 4 ×):

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

    (Curiosità: The Formatter nell'IDE di Ceylon formatta alcune annotazioni di lingua incorporate, tra di loro variable e shared, inserendole nella stessa riga della dichiarazione annotata, in contrasto con le annotazioni personalizzate, che sono poste su una riga separata sopra la dichiarazione. rende illeggibile la versione formattata del programma golfed, quindi ho cambiato alias-imports per questa versione.)

    this, void, case, elseSono le parole chiave effettive e non può essere rinominato in questo modo, e Integer, Stringe Characterappaiono solo una volta ciascuno, quindi non c'è nulla da guadagnare importando.

  • Inizialmente avevo anche una classe ScreenBuffer separata (che teneva traccia dell'elenco collegato dei buffer di linea, dell'indice corrente e così via), ma poiché non ne esisteva mai un solo oggetto, è stato ottimizzato.

  • Anche quella classe di Screenbuffer aveva upe downmetodi, che erano chiamati dal parser (e lo avevano fatto currentLine = currentLine.uprispettivamente currentLine = currentLine.down). Ha dimostrato che farlo direttamente con il parser è più breve. Ha anche permesso di scrivere currentLine = currentLine.up.up(che in seguito divenne c = c.u.u) invece di currentLine = currentLine.up;currentLine = currentLine.up.

  • Inizialmente abbiamo passato l'indice corrente come argomento nel metodo append (e persino al parser dal loop) - avere una variabile nella funzione contenitrice è più breve.

  • Inizialmente il mio metodo printAll utilizzava il puntatore corrente e lo spostava prima verso l'alto fino a quando la riga corrente era vuota, quindi verso il basso durante la stampa di ogni riga. Ciò si interruppe quando si utilizzavano ▲ e ▼ per saltare le linee, quindi abbiamo dovuto aggiungere esplicitamente qualcosa in quelle linee saltate. Tenere traccia della prima / ultima riga si è rivelato più semplice (anche se ha reso necessario l'uso di due istruzioni di stampa, poiché non esiste un ciclo do-while in Ceylon).

  • Inizialmente avevo qualcosa del genere:

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

    process.readLineritorna nullse non ci sono righe che possono essere lette (perché l'input è stato chiuso) e il compilatore Ceylon mi richiede di verificarlo prima di accedere input. Come in questo caso non voglio fare nulla, posso usare equivalentemente l' elseoperatore che restituisce il suo primo argomento se non nullo, e in caso contrario il suo secondo argomento, salvando la variabile e l'istruzione if. (Anche questo ci permetterebbe di codificare un ingresso di default per il test: 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,'')

Bene, ecco una soluzione (piuttosto lunga) ricorsiva che supera tutti i casi di test forniti. È stata una bella sfida. Questo utilizza ke jal posto di e .

Test dello snippet

Sebbene l'invio stesso possa solo gestire k,j, il frammento seguente può gestire sia k,je ▼,▲.

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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.