Naviga il testo con i tasti freccia


11

sfondo

La maggior parte degli editor di testo (a metà decente) consentono di navigare nel testo utilizzando i tasti freccia. Su e giù ti consentono di navigare tra le linee, mentre sinistra e destra si spostano su una linea ma anche di spostarti. Inoltre, se la linea è più corta della posizione X del cursore, il cursore appare alla fine della linea ma ritorna nella stessa posizione X se si continua a spostarsi verso l'alto o verso il basso. Forse la seguente spiegazione visiva aiuterà:

Esempi di movimento

Un semplice esempio di testo potrebbe apparire così. Il cursore verrà inserito tra due caratteri in questo testo o alla fine.

-----
---
------

let's put the cursor here:

X-----
---
------

move down (v):

-----
X---
------

move left (<):

-----X
---
------

v

-----
---X
------

v (notice how the X position of the cursor has been maintained)

-----
---
-----X-

^

-----
---X
------

>  (more line wrapping)

-----
---
X------

<

-----
---X
------

^ (the X-position from earlier is no longer maintained due to the left-right motion)

---X--
---
------

La sfida

Date diverse linee di test ASCII, trova il percorso più breve dalla posizione iniziale alla posizione finale. La posizione iniziale è rappresentata da ^e la posizione finale è rappresentata da $, e ce ne sarà solo una. Questi non sono considerati parte del testo e non contribuiscono alla "lunghezza" di quella riga.

L'input consisterà in diverse righe di testo non vuote. L'output sarà una serie di ^v<>caratteri che mostrano uno dei percorsi più brevi. Opzionalmente puoi assumere una nuova riga aggiuntiva alla fine di ciascuna, ma che non è inclusa come parte del testo navigabile.

È possibile scrivere un programma o una funzione denominata. Il vincitore sarà l'invio più breve, misurato in byte.

Esempio di I / O

^Squares
are
fun$ny

vv<v  (which is better than the naive vv>>>)

Squares
^are
funny$

<vv

Alp$habet^
Song

v<^

Mary had a little lamb,
His fleece was white as snow,
And$ everywhere that ^Mary went,
The lamb was sure to go.

^^>>>>v>>>

$^degenerate case

(no output)

"Il cursore verrà inserito tra due caratteri in questo testo, o alla fine" - procede a posizionare il cursore all'inizio nel primo esempio
aditsu si chiude perché SE è EVIL

Ci sono due estremità di ogni riga. A cura di "una fine".
PhiNotPi

Vim consente le frecce. Ho un vero vi nella mia scatola AIX che non lo ha (ho aggiunto le istruzioni della mappa al mio file di avvio). "A metà strada decente" ... sì
Jerry Jeremiah,

L'output del primo esempio potrebbe anche essere v<vv, giusto? O sarebbe finita dopo l'ultimo personaggio su quella linea?
mbomb007,

@ mbomb007 Sarebbe terminato dopo l'ultimo carattere della riga.
PhiNotPi l'

Risposte:


7

CJam, 139 byte

Bene, ci sono volute molte ore per arrivare a qualcosa che sembra fatto. Sembra che il tempo necessario per ottimizzare in modo aggressivo il codice CJam sia qualcosa di più grande di O (n) rispetto alla dimensione del codice ...

Puoi provarlo online , ma per qualsiasi input per il quale il percorso migliore è almeno 6 operazioni o giù di lì, dovresti probabilmente provarlo offline con un interprete più veloce.

schiacciata:

q_'$-_'^-:T;'^#\'^-'$#W{)2$5Y$5b+{:D[L"_T<W%_N#)_@>N+N#X-Ue>+-"_"W%-U"--2'<t2'>t'++'(')]=~0e>T,e<D3/1$T<N\+W%N#X?:X;}/2$-}g5b{" ^v<>"=}%]W=

Ampliato e commentato:

q               "Read the input";
_'$-            "Remove the end marker";
_'^-:T;         "Remove the start marker and save the text";
'^#             "With only the end marker removed, locate the start marker";
\'^-'$#         "With only the start marker removed, locate the end marker";
W               "Initialize the path number to -1";
{               "Do...";
  )               "Increment the path number";
  2$              "Initialize the cursor position to that of the start marker";
  5Y$5b+          "Convert the path number to base 5, then add a leading 5
                   (the leading 5 will act to initialize the column memory)";
  {:D             "For each digit in the path digit string:";
    [               "Begin cases:";
      L               "0: Do nothing";
      "_T<W%_N#)_@>N+N#X-Ue>+-"
"REFS: [   1   ][  2  ][ 3 ]45
                       1: [1] Calculate the distance to the end of the previous
                              line (0 if no such line)
                          [2] Calculate the length of the previous line (0 if
                              no such line)
                          [3] Calculate the distance to move backwards in the
                              previous line as the maximum of the length of the
                              previous line minus the column memory and 0
                          [4] Calculate the total distance to move as the sum 
                              of [1] and [3]
                          [5] Subtract [4] from the cursor position";
      _"W%-U"-        "2: Start with a base of the logic of case 1, but with a
                          few operations adjusted.";
      -2'<t2'>t       "   [1] Calculate the distance to the *start* of the
                              *next* line (0 if no such line)
                          [2] Calculate the length of the *next* line (0 if no
                              such line)
                          [3] Calculate the distance to move *forwards* in the
                              *next* line as the *minimum* of the length of the
                              *next line* and *the column memory*
                          [4] Calculate the total distance to move as the sum 
                              of [1] and [3]";
      '++             "   [5] *Add* [4] *to* the cursor position";
      '(              "3: Decrement the cursor position";
      ')              "4: Increment the cursor position";
    ]=~             "Execute the case corresponding to the path digit mod 5";
    0e>T,e<         "Clamp the cursor position to [0, text length]";
    D3/             "Check if the path digit is not 0, 1, or 2...";
    1$T<N\+W%N#     "Calculate the current column";
    X?:X;           "If the above check succeeded, update the column memory";
  }/              "End for each";
  2$-             "Subtract the end marker position from the cursor position";
}g              "... While the above subtraction is nonzero";
5b              "Convert the path number to base 5";
{" ^v<>"=}%     "Map each digit in the path string to its operation symbol";
]W=             "Clean up";

Nel complesso, questa è una soluzione piuttosto semplice. "Esegue" le cifre della rappresentazione base-5 di un numero di percorso che viene incrementato ogni iterazione, iniziando con 0, fino a quando un percorso funziona. Le cifre 1: 4mappano le operazioni su, giù, sinistra e destra e 0non fanno nulla. La prima iterazione che utilizza un percorso 0cattura solo il caso degenerato. Tutti gli altri percorsi che contengono un 0non vengono mai selezionati perché sono solo versioni di percorsi già testati con aggiunte non operative.

Lo stato è modellato nel modo più minimalista possibile: il testo con i marcatori di inizio e fine rimossi, la posizione del cursore nel testo e la "memoria di colonna". Le newline sono per lo più trattate come qualsiasi altro personaggio, quindi non esiste un concetto di riga e la posizione del cursore è solo un indice. Ciò semplifica lo spostamento dei morti sinistro e destro, che sono solo implementati come decremento e incremento (con il bloccaggio sulla dimensione del testo). Muoversi su e giù è un po 'più complicato, ma comunque gestibile.

Il riutilizzo del codice era una tattica di ottimizzazione piuttosto vitale. Esempi di questo includono:

  • Scrivere il codice per spostarsi verso l'alto in modo tale che sia più piccolo generare il codice per spostarsi verso il basso in fase di esecuzione piuttosto che scrivere il proprio codice. Questo viene fatto copiando il codice per spostarsi verso l'alto e rimuovere / sostituire alcuni caratteri.
  • L'aggiornamento della "memoria di colonna" viene eseguito in modo condizionale in base alla cifra del percorso divisa per 3 anziché essere codificata nella logica dell'operazione. Ciò consente anche l'inizializzazione della memoria della colonna aggiungendo un'operazione fittizia 5all'inizio della stringa del percorso, che in tal caso utilizza anche la 0logica no-op a causa dell'indicizzazione dell'array circolare e ci sono solo 5 operazioni definite.

Nel complesso, sono molto contento di come è venuto fuori. Questa è sicuramente la maggior parte del lavoro che ho messo in una risposta di code golf ad oggi (per qualcosa che si adatta a un tweet !?). Il tempo di esecuzione è piuttosto spaventoso, però. CJam non è esattamente il linguaggio più veloce per cominciare e questo algoritmo ha una complessità simile a O (m * 5 n ) , dove m è la dimensione dell'input e n è la dimensione dell'output. Per fortuna la velocità non conta!


Bello :) Mi sento un po 'in colpa per averti indirettamente speso così tanto tempo su questo: p
aditsu smettila perché SE è MALE

2

Python 2: 446

Q=input().split('\n');
def g(c):l=[l for l in Q if c in l][0];return Q.index(l),l.index(c)
a,b=g('^');c,d=g('$');Q=map(len,Q);Q[a]-=1;Q[c]-=1
if a==c:d-=b<d;b-=d<b
t=-1
while Q:
 l=[];T=t=t+1;x,y,z=a,b,b
 while T:l+=[T%5]*(T%5>0);T/=5
 for T in l:A=":x+=T+T-3;y=min(Q[x],z)";B="x<len(Q)-1";exec"if "+["","x"+A,B+A,"y:y=z=y-1\nelif x:x-=1;y=z=Q[x]","y<Q[x]:y=z=y+1\nelif "+B+":x+=1;y=z=0"][T]
 if(x,y)==(c,d):print''.join(' ^v<>'[x]for x in l);Q=0

Soluzione semplice. Sto eseguendo una prima ricerca. tscorre su tutti i diversi percorsi. Converto tin base 5, ma uso solo le voci, che sono diverse da zero. 1è su, 2è giù, 3è a sinistra ed 4è a destra.

Continuo la posizione corrente del cursore 3 variabili x, ye z. xè la linea, yla posizione della colonna e zla posizione della colonna "nascosta", se si sale o si scende e la linea è troppo corta. Molti if decidono come cambiare la variabile durante una mossa.

La preelaborazione è molto lunga, le prime 4 righe eseguono solo questa attività.

Il lungo testcase richiede molto tempo. L'algoritmo ha una complessità di O (N * 5 ^ N), dove N è la lunghezza della soluzione più breve.

Uso: inserisci le linee come una singola stringa (linee separate da \n) come"Alp$habet^\nSong"


1

CJam - 274

Ancora nessuna risposta? Ok, eccone uno :)

qN/_{0:V;{_'^={[UVV]:B;;}{'$={[UV]:E;}{V):V;}?}?}/U):U;}/"^$"f-:,:A;{:X0=[X0=(_A=X2=_@e<\]X?}:U;{:X0=A,(=X[X0=)_A=X2=_@e<\]?}:D;{:X1=[X~;(_]{X0=[X0=(_A=_]X?}?}:L;{:X1=X0=A=={X0=A,(=X[X0=)0_]?}[X~;)_]?}:R;[[BM]]{_{0=2<E=},_{0=1=o0}{;[{"U^DvL<R>"2/\f{[~@1/~@\+@@~\]}~}/]1}?}g;

Provalo su http://cjam.aditsu.net/ ... eccetto l'esempio di Mary o qualcosa di quelle dimensioni, probabilmente vorrai l' interprete java .


1
WTF? 274 !!!!!!
Ottimizzatore,

@Optimizer hahaha, beh, ci ho perso abbastanza tempo, vai avanti e
gioca a
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.