Movimento efficiente del robot


24

Disclaimer: la storia raccontata all'interno di questa domanda è del tutto inventata e inventata esclusivamente allo scopo di fornire un'introduzione.

Il mio capo ha ottenuto un nuovo robot giocattolo e vuole che lo aiuti a programmarlo. Vuole essere in grado di inserire semplici istruzioni a freccia per farlo muovere. Queste istruzioni sono: ^ (per andare avanti) <(per girare a sinistra) e> (per girare a destra). Tuttavia, ora che ho programmato il robot, desidera funzionalità aggiuntive. Vuole che trasformi qualsiasi sequenza di frecce che inserisce, in modo che, anziché fare in modo che il robot prenda il percorso indicato, si sposta nella posizione desiderata, indicata dal punto in cui sarebbe finita se avesse preso il percorso immesso, in modo efficiente come possibile. Mi rivolgo a voi, membri di PP&CG, per aiutarmi in questo compito.

Il tuo compito:

Scrivi un programma o una funzione per convertire una stringa composta da frecce in una stringa che raggiungerà la posizione indicata dall'input il più rapidamente possibile. La rotazione richiede esattamente il tempo di muoversi avanti o indietro.

Ingresso:

Una serie di frecce, come indicato sopra. Se lo desideri, i caratteri diversi possono essere sostituiti con le frecce, ma assicurati di includere il fatto che lo fai nella tua risposta. Tutti i casi di test usano normalmente le frecce.

Produzione:

Una serie di frecce (o caratteri equivalenti) che portano il robot alla destinazione desiderata nel modo più efficiente possibile.

Casi test:

Si noti che le soluzioni offerte sono solo possibilità e che altre soluzioni potrebbero essere valide.

>^<<^^>^^    -> ^^<^
^^^^>^^^^    -> ^^^^>^^^^
>>>^^^^^^    -> <^^^^^^
>^>^>^>^     -> (empty string)
^<^^<^^<^^^^ -> >^^>^

punteggio:

La memoria del robot è limitata, quindi il programma deve avere il conteggio di byte più basso possibile.


Perché nell'input il robot finisce esattamente dove è iniziato, quindi non sono necessari comandi per spostarlo lì nel modo più efficiente possibile.
Gryphon - Ripristina Monica il

Oh, ho letto male la stringa. Colpa mia.
JungHwan Min

Richiesta del test case ^<^^<^^<^^^^-> >^^>^?
JungHwan Min

1
@pizzakingme, scusa, ma il mio capo è molto pigro e vuole solo digitare un personaggio per movimento.
Gryphon - Ripristina Monica il

1
Programmo robot competitivi e posso confermare che funziona esattamente.
Joe,

Risposte:


9

Retina , 103 74 71 byte

<
>>>
+`(>(\^*>){3})\^
^$1
+`\^(>\^*>)\^
$1
>>(\^*)>(\^+)
<$2<$1
<?>*$

Provalo online! Il link include casi di test. Spiegazione:

<
>>>

Girare a sinistra si trasforma in triple a destra.

+`(>(\^*>){3})\^
^$1

Ridurre tutti i giri modulo 4.

+`\^(>\^*>)\^
$1

Annullare i movimenti in direzioni opposte.

>>(\^*)>(\^+)
<$2<$1

Girare una tripla svolta a destra in una svolta a sinistra. Questo gestisce anche il caso di >>^>^cui deve diventare <^<^.

<?>*$

Elimina le svolte finali non necessarie.


Impressionante. Sapevo che doveva esserci un modo per ottenere questo sotto 100 byte in qualche lingua, e la tua risposta era così vicina prima. +1
Gryphon - Ripristina Monica il

6

Mathematica, 135 byte

{a="^"~Table~Ramp@#&;a@#,s=If[#2>0,">","<"],a@Abs@#2,If[#<0,s,""],a@-#}<>""&@@ReIm[j=0;i=1;Switch[#,">",i*=I,"<",i/=I,"^",j+=i]&/@#;j]&

Accetta una Liststringa come input.

Spiegazione

j=0;i=1

Impostare jsu 0 e impostare isu 1.

/@#

Per ogni personaggio in input ...

Switch[#,">",i*=I,"<",i/=I,"^",j+=i]

Se il personaggio è >, moltiplica iper l'unità immaginaria. Se il personaggio è >, dividi iper l'unità immaginaria. Se il personaggio è ^, aggiungi ia j.

ReIm[ ... ;j]

Prendi le parti reali e immaginarie di j. Ciò fornisce le coordinate cartesiane del robot.

... &@@

Applicare quanto segue a questo risultato:


a="^"~Table~Ramp@#&;

Impostato asu una funzione che genera una stringa con (input)o 0carattere ^s, a seconda di quale sia maggiore.

{ ... }

Un Listcomposto da ...

a@#

aapplicato al primo input (parte reale di j)

s=If[#2>0,">","<"]

Se il secondo ingresso (parte immaginaria j) è maggiore di 0, >. In caso contrario, <. Impostare ssul carattere risultante.

a@Abs@#2

a applicato al valore assoluto del secondo input.

If[#<0,s,""]

Se il primo input è inferiore a 0 s,. Altrimenti, stringa vuota.

a@-#

Applicare aai tempi di input negativi.

... <>""

Unisciti alle corde.


2

Mathematica 119 byte

La posizione finale di JungHwan rispetto al codice di percorso era più breve della mia, quindi usandola. Penso che ci sia probabilmente un modo ancora più breve per farlo ...

Uso la AnglePathfunzione integrata per decidere la posizione finale. Definisco anche i simboli L, F e R per "<", "^" e ">", per salvare alcuni caratteri di citazione.

L={0,Pi/2};R=-L;F={1,0};{a="F"~Table~Ramp@#&;a@#,s=If[#2>0,"L","R"],a@Abs@#2,If[#<0,s,""],a@-#}<>""&@@Last@AnglePath@#&

Uso:

%@{R,F,L,L,F,F,R,F,F}

Produzione:

FFLF

2

Rubino , 130 byte

->s{w,d=0,1;s.bytes{|b|b>93?w+=d:d*=1i*(b<=>61)};r,c=w.rect;[w=(d=">><"[c<=>0])+?^*c.abs,?^*r.abs+w,w+d+?^*r.abs][r<=>0].chomp ?>}

Come funziona

->s{
    # We start from (0,0i), direction is +1
    w,d=0,1

    s.bytes{|b|
        # If it's ASCII 94, go one step forward,
        # else multiply direction by +i or -i
        b>93?w+=d:d*=1i*(b<=>61)
    }

    # Get the rectangular representation of the result
    r,c=w.rect

    # Now, create 2 strings of "^" (call them x and y) for horizontal and vertical moves
    # And a single ">" or "<" (call it d) for the direction change
    # If x>0, output x+d+y
    # If x==0, output d+y
    # If x>0, output d+y+d+x
    [w=(d=">><"[c<=>0])+?^*c.abs,?^*r.abs+w,w+d+?^*r.abs][r<=>0]

    #If y==0 we get an extra ">" sometimes
    .chomp ?>
}

Provalo online!


2

J, 90 byte

soluzione

t=.{&' ><'@*
g=.'^'#~|
(t,g@{.,t@-@(*/),g@{:`g@{:,t@{.,g@|@{.@.(0<:{:))@+.@(+/)@(=&1*j.**/\)

spiegazione

c'è un trucco accurato usando numeri complessi (moltiplicando per i è una rotazione a sinistra di 90 gradi e -i ti dà uno a destra).

quindi prendiamo il nostro input come numeri complessi: un 1 rappresenta "cammina avanti" e i / -i rappresentano le svolte a destra e a sinistra.

la posizione finale viene calcolata senza sforzo con questa rappresentazione. Nota che questa è la prima parte (più a destra) della mia espressione finale sopra:

(+/)@(=&1*j.**/\)

Quella breve riga sopra è ciò che risolve il problema. Tutto il resto sta solo cercando di capire come formattare la risposta e potrebbe sicuramente essere risolto molto di più.

Per comprendere la breve riga sopra, nota che */\(la scansione di prodotti parziali) ti fornisce un elenco delle posizioni che stai affrontando in ciascun indice nell'input: i è nord, 1 e -1 sono est e ovest e -i è sud . Ma da quando iniziamo a nord, dobbiamo moltiplicare tutti quelli per i che, in J, è rappresentato da j.(masticare quella frase per un momento).

Abbiamo solo effettivamente "spostare" quando l'ingresso originale è 1, quindi abbiamo poi moltiplicare tale risultato elementwise dalla matrice booleana che è 1 in cui l'ingresso originale è 1 e 0 altrimenti: =&1*. Il risultato di tale moltiplicazione è una matrice di "passi direzionali". La nostra posizione finale è semplicemente la somma di questi passaggi:+/

analisi

Sfortunatamente non riesco a farlo funzionare in TIO per qualche motivo, ma incollare quanto segue nella console J verificherà che funzioni:

t=.{&' ><'@*
g=.'^'#~|
f=.(t,g@{.,t@-@(*/),g@{:`g@{:,t@{.,g@|@{.@.(0<:{:))@+.@(+/)@(=&1*j.**/\)

NB. test cases
NB. format input as complex numbers
convert=. {&0j1 0j_1 1@:('<>^'&i.)

s=. '^<^^<^^<^^^^'  NB. >^^>^
echo f convert s
s=. '>^<<^^>^^'     NB. ^^<^
echo f convert s
s=. '^^^^>^^^^'     NB. ^^^^>^^^^
echo f convert s
s=. '>>>^^^^^^'     NB. <^^^^^^
echo f convert s
s=. '>^>^>^>^'      NB. empty string
echo f convert s

1

C # (.NET Core) , 349 byte

n=>{int a=0,b=0,x=0,y=1,t=0,j=0,k=0,w,e,r;var p="";foreach(var c in n){if(c==62){t=x;x=y;y=-t;}if(c<61){t=x;x=-y;y=t;}if(c>63){a+=x;b+=y;}}while(a!=j|b!=k){w=0;e=a-j;r=b-k;if(r>=e&r>=-e){w=b-k;k+=w;}else if(r<=e&r<=-e){p+=">>";w=k-b;k-=w;}else if(r>=e&r<=-e){p+="<";w=j-a;j-=w;}else if(r<=e&r>=-e){p+=">";w=a-j;j+=w;}p+=new string('^',w);}return p;}

Provalo online!

Prende una stringa come input e genera il percorso più breve che l'input prenderebbe.


Non registrato e commentato

n =>
{
    // First, calculate the route that the robot is going to take, represented by xy
    int a = 0, b = 0; // The current coordinates (a=x, b=y)
    int x = 0, y = 1; // The movement vector
    int t = 0; // A temp variable
    var p = ""; // The path we are going to return
    // Calculate the path the robot is going to take by input
    foreach (var c in n)
    {
        if (c == '>') { t = x; x = y; y = -t; } // Turn movement vector right
        if (c == '<') { t = x; x = -y; y = t; } //                      left
        if (c == '^') { a += x; b += y; }       // Move forward
    }
    int j = 0, k = 0; // The new movement coordinates (j=x,k=y)
    // While the target position is not reached, move the robot
    while (a != j | b != k)
    {
        int w = 0; // The forward variable, counting how many times we have to go forward
        int e = a - j, r = b - k; // The target position minus the current position (e=x,r=y)
        if (r >= e & r >= -e) { w = b - k; k += w; } // Up
        else if (r <= e & r <= -e) { p += ">>"; w = k - b; k -= w; } // Down
        else if (r >= e & r <= -e) { p += "<"; w = j - a; j -= w; } // Left
        else if (r <= e & r >= -e) { p += ">"; w = a - j; j += w; } // Right
        p += new string('^', w);
    }
    // Return the final path
    return p;
}

1

JavaScript (Node.js) , 187 byte

s=>{x=y=t=0;r=x=>"^".repeat(x<0?-x:x);for(c of s){t-=b=c<">"||-(c<"^");if(!b)[z=>++y,z=>++x,z=>--y,z=>--x][t&3]()}t=x<0?"<":">";return (y>0?r(y):"")+(x?t+r(x):"")+(y<0?(x?t:t+t)+r(y):"")}

Provalo online!

Versione golfizzata con spazi bianchi

-14 byte di @Neil


Ungolfed:

s=>{
  // convert turns to up/down/left/right movements to final destination
  let directions = [
    z=>++y, // up
    z=>++x, // right
    z=>--y, // down
    z=>--x  // left
  ];
  let x = y = direction = 0;
  for(c of s){
    let relativeDirection = "<^>".indexOf(c)-1; // relative turn offset: -1 = left, 1 = right
    direction += relativeDirection;
    if(direction<0){direction+=4} // make sure direction%4 > 0
    if(c==="^"){directions[direction%4]()} // do the movement if going forwards
  }
  // convert destination back to turns
  // the most efficient output has up before left/right before down
  let absoluteRepeat = num => "^".repeat(Math.abs(num));
  let turn = x<0 ? "<" : ">";
  let outp = "";
  if (y>0) { outp += absoluteRepeat(y) } // handle up before left/right
  if (x) { outp+=turn+absoluteRepeat(x) } // handle left/right
  if (y<0) { outp += (outp?turn:turn+turn)+absoluteRepeat(y)) } // handle down (including w/o left/right)
  return outp;
}

Usare t&3invece t%4perché funziona con il negativo in tmodo da poter rimuovere la 4+e la ()s. (x?"":t)+tpuò essere scritto (x?t:t+t)per un salvataggio di 1 byte. Il codice di spostamento della direzione sembra troppo lungo. Inoltre penso che dovresti probabilmente sostituire indexOfe Math.abscon confronti.
Neil,

@Neil Grazie! Potresti approfondire un po 'la sostituzione indexOfcon un confronto?
Birjolaxew,

Il meglio che potevo fare era t-=b=c<'>'||-(c<'^').
Neil,

1

Python 2 , 174 169 165 byte

Modifica 1: -5 byte consentendo alla direzione di essere fuori dall'intervallo 0-3 e rimuovendo gli spazi bianchi.

Modifica 2: -4 byte modificando l'input in (1, 2, 3) anziché (<, ^,>) poiché l'OP lo ha permesso, oltre a cambiare il mio sistema di coordinate per consentirmi di ridurre il calcolo della distanza.

n,d=[0,0],0
for c in input():exec'd-=1 n[d%2]+=(-1)**(d/2%2) d+=1'.split()[ord(c)-49]
print'2'*n[0]+'13'[n[1]>0]*any(n)+'2'*abs(n[1])+'13'[n[1]>0]*(n[0]<0)+'2'*-n[0]

Provalo online!

Determina le coordinate finali tramite i valori del dizionario in esecuzione, quindi stampa semplicemente il percorso diretto verso l'obiettivo finale.


0

Perl 5 , 185 + 1 (-p) = 186 byte

/</?$d--:/>/?$d++:/\^/?$m[$d%4]++:0for/./g;$y=$m[0]-$m[2];$x=$m[1]-$m[3];$q='^'x abs$x;$_=A.$q.B.('^'x-$y);$x<0?y/AB/</:$x?y/AB/>/:0;$_=('^'x$y).($x<0?'<':$x>0?'>':'').$q if$y>0;y/AB//d

Provalo online!


0

JavaScript (document.getElementById () kind), 343 caratteri

function b(s){s=s.split('');c=[0,0];r=0;p='';w='<';e='>';n='^';for(i in s){r+=s[i]==e?.5:s[i]==w?-.5:0;r=r>1?-.5:r<-.5?1:r;c[1-Math.ceil(Math.abs(r%1))]+=s[i]==n?r>0?1:-1:0;}x=c[0];y=c[1];j=x<0?-x:x;k=y<0?-y:y;f=function(a){p+=a==j?x<0?w:x>0?e:'':j>k?y<0?w:y>0?e:'':y>0?e+e:'';for(i=0;i<a;i++){p+=n}};if(j>k){f(j);f(k)}else{f(k);f(j)}alert(p)}

allargato:

function b(s){

s = s.split('');
c = [0, 0];
r = 0;
p = '';
w = '<';
e = '>';
n = '^';

for(i in s){

    r += s[i] == e ? .5 : s[i] == w ? -.5 : 0;
    r = r > 1 ? -.5 : r < -.5 ? 1 : r;

    c[1 - Math.ceil( Math.abs( r%1 ) )] += s[i] == n ? r > 0 ? 1 : -1 : 0;

}

x = c[0];
y = c[1];
j = x < 0 ? -x : x;
k = y < 0 ? -y : y;

f = function(a){

    p += a == j ? x < 0 ? w : x > 0 ? e : '' : j > k ? y < 0 ? w : y > 0 ? e : '' : y > 0 ? e+e : '';

    for( i = 0; i < a; i++){
        p += n
    }

};

if( j>k ){

    f(j);
    f(k)

} else {

    f(k);
    f(j)

}

alert(p)

}

Uso:

b('^<^^<^^<^^^^')

avvisi: >^^>^

Un robot con retromarcia sarebbe stato utile.

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.