Relativo vs assoluto


17

Se qualcuno rivolto a nord al punto A in questa griglia voleva che le indicazioni seguissero il percorso verde (poiché possono solo seguire le linee della griglia) al punto B, potresti dire loro:

Go North, North, West, East, East, South, East, East.

o equivalentemente

Go Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Dove un comando di Destra , Sinistra o Indietro implica implicitamente girare in quella direzione, quindi andare avanti.)

Percorso da A a B.

Scrivi una funzione con un argomento che traduca queste direzioni assolute e relative lungo lo stesso percorso , non solo nello stesso punto. Supponiamo che la persona diretta inizi sempre rivolta a nord.

Se l'argomento è una stringa di lettere NSEW, restituisce le direzioni relative equivalenti.
ad es. f("NNWEESEE")restituisce la stringa FFLBFRLF.

Se l'argomento è una stringa di lettere FBLR, restituisce le direzioni assolute equivalenti.
ad es. f("FFLBFRLF")restituisce la stringa NNWEESEE.

La stringa vuota si arrende. Non supporre altri casi di input.

Se la tua lingua non ha funzioni o stringhe usa ciò che sembra più appropriato.

Vince il codice più breve in byte .


Supponiamo che una persona inizi sempre con la testa rivolta a nord? In questo modo, in termini relativi per andare verso est, gli sarebbe richiesto di svoltare a destra, piuttosto che semplicemente dire Avanti
Ottimizzatore

@Optimizer Sì, a nord. E sì, all'altro punto. Rè uguale Eall'inizio.
Calvin's Hobbies,

1
Sìì! Hai cambiato la tua foto per confermare quello che ho sempre pensato!
Justin,

4
Sei di nuovo agganciato a PPCG? ;)
Martin Ender,

4
@ MartinBüttner O questo o sono molto bravo a nascondere i miei problemi di compiti a casa. ;)
Calvin's Hobbies,

Risposte:


6

CJam, 57 53 49

{"NESW""FRBL"_3$&!!:Q$:R^^f#0\{{+0\}Q*_@-R=\}%);}

Versione precedente

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}

Esempio:

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}:T;
"NNWEESEE"T
N
"FFLBFRLF"T

Produzione:

FFLBFRLF
NNWEESEE

Come funziona

{
  "NESW""FRBL"             " Push the two strings. ";
  _3$0=#W>                 " Check if the first character is in FRBL. ";
  :Q                       " Assign the result to Q. ";
  {\}*                     " Swap the two strings if true. ";
  :R;                      " Assign the top string to R and discard it. ";
  f#                       " Find each character of the input in the string. ";
  0\                       " Push a 0 under the top of the stack. ";
  {                        " For each item (index of character): ";
    {                      " If Q: ";
      +0\                  " A B -> 0 (A+B) ";
    }Q*
    _@-                    " C D -> D (D-C) ";
    R=                     " E -> E-th character in R ";
    \                      " Swap the top two items. ";
  }%
  );                       " Discard the last item in the list. ";
}

6

C ++, 99 97

Quanto segue è formattato come espressione lambda. Ne prende unochar* argomento e lo sovrascrive.

[](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];}

Per coloro che non hanno familiarità con questa funzione (come me 1 ora fa), utilizzala come segue:

#include <iostream>

int main()
{
    char s[] = "NNWEESEE";
    auto x = [](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];};

    x(s); // transform from absolute to relative
    std::cout << s << '\n';

    x(s); // transform from relative to absolute
    std::cout << s << '\n';
}

Alcune spiegazioni:

  • Quando si utilizza il codice come flag ? (x = y) : (x += z) , la seconda coppia di parentesi è richiesta in C. Quindi ho usato C ++ invece!
  • C ++ richiede di specificare un tipo restituito per una funzione. A meno che non utilizzi un'espressione lambda, cioè! Un ulteriore vantaggio è che non ho bisogno di sprecare 1 carattere nel nome della funzione.
  • Il codice *s*9%37&4verifica il primo byte; il risultato è 4 se è uno deiNESW ; 0 altrimenti
  • Il codice *s%11/3converte i byteNESW in 0, 1, 2, 3
  • Il codice *s%73%10converte i byteFRBL in 0, 9, 6, 3 (che è 0, 1, 2, 3 modulo 4)
  • Quando converto le direzioni relative in assoluto, non ho bisogno della dvariabile. Ho provato a riorganizzare il codice per eliminarlo completamente, ma sembra impossibile ...

1
Mi piace il modo in cui converti le lettere in numeri molto. :)
Emil,

6

JavaScript (E6) 84 86 88 92 104

Modifica: usando & invece di%, precedenza dell'operatore diversa (meno parentesi) e funziona meglio con numeri negativi
Modifica2: | invece di +, ancora una volta la precedenza, -2. Grazie DocMax
Edit3: la comprensione dell'array è 2 caratteri più corta di map (), per le stringhe

F=p=>[o+=c[d=n,n=c.search(i),n<4?4|n-d&3:n=n+d&3]for(i of n=o='',c='NESWFRBL',p)]&&o

Test nella console FireFox / FireBug

console.log(F('NNWEESEE'),F('FFLBFRLF'))

Produzione

FFLBFRLF NNWEESEE

@Optimizer non di più. E sperando di ridurlo ancora di più.
edc65,

Cosa significa && oalla fine?
Bebe,

2
@bebe la funzione map restituisce un array, al suo interno, come effetto collaterale, riempio la stringa o che è quello che devo restituire. array && valuevalutare valuecome valuta qualsiasi arraytruthy
edc65

1
Infine! Sto fissando questo da quando ha colpito 88. A meno che non mi manchi qualcosa, puoi sostituirlo 4+(n-d&3)con 4|n-d&3e salvare 2 caratteri.
DocMax,

4

APL, 72

{^/⍵∊A←'NESW':'FRBL'[1+4|-2-/4,3+A⍳⍵]⋄A[1+4|+\'RBLF'⍳⍵]}

Se le configurazioni dell'interprete possono essere modificate senza penalità, il punteggio è 66 , passando ⎕IOa 0:

{^/⍵∊A←'NESW':'FRBL'[4|-2-/0,A⍳⍵]⋄A[4|+\'FRBL'⍳⍵]}

3

Python, 171 139

Non è così breve come le altre soluzioni, ma immagino che dovrebbe essere relativamente buono per quello che si può fare con Python:

def f(i):a,b='NWSE','FLBR';I=map(a.find,'N'+i);return''.join((b[I[k+1]-I[k]],a[sum(map(b.find,i)[:k+1])%4])[-1in I]for k in range(len(i)))

Versione estesa per una migliore leggibilità:

def f(i):
    a, b = 'NWSE', 'FLBR'
    I = map(a.find,'N'+i)     # translate to numbers assuming abs. directions
    J = map(b.index,i)        # translate to numbers assuming rel. directions
    if not -1 in I:
        o = [b[I[k+1]-I[k]] for k in range(len(i))]    # rel. dir. is differences of abs. dir.
    else:
        o = [a[sum(J[:k+1])%4] for k in range(len(i))] # abs. dir. is sum of all rel. dir. so far
    return ''.join(o)

1

Vai, 201

type q string;func F(s q)q{d,z:=byte(0),make([]byte,len(s));for i,c:=range[]byte(s){if(c^4)*167%3<2{c=c*156%5;z[i],d="LBRF"[(d-c)%4],c-1;}else{c=(c^43)*3%7-1;d=(d+c)%4;z[i]="NESW"[d];};};return q(z);}

Versione leggibile:

func F(s string) string {
    d, z, R, A := 0, make([]byte, len(s)), "LBRFLBR", "NESW"
    for i, c := range []byte(s) {
        switch c {
        case 'N': c = R[d+3]; d = 0
        case 'E': c = R[d+2]; d = 1
        case 'S': c = R[d+1]; d = 2
        case 'W': c = R[d]; d = 3
        case 'F': c = A[d]
        case 'R': d = (d + 1) % 4; c = A[d]
        case 'B': d = (d + 2) % 4; c = A[d]
        case 'L': d = (d + 3) % 4; c = A[d]
        }
        z[i] = c
    }
    return string(z)
}


1

GNU sed, 356 byte

La sfida richiede una semplice trasformazione in un flusso di personaggi. sed, l'editor di stream è la scelta ovvia della lingua ;-)

/[FRBL]/bx                                     # Jump to label x if relative
:y                                             # label y (start of abs->rel loop)
/[FRBL]$/q                                     # quit if string ends in rel char
s/(^|[FRBL])N/\1F/;ty                          # Substitute next abs char with
s/(^|[FRBL])E/\1R/;tr                          #     rel char, then jump to
s/(^|[FRBL])S/\1B/;tb                          #     relevant rotation label if
s/(^|[FRBL])W/\1L/;tl                          #     a match was found
by                                             # loop back to y
:r;y/NESW/WNES/;by                             # Rotation labels: transform then
:b;y/NESW/SWNE/;by                             #     loop back to y
:l;y/NESW/ESWN/;by
:x                                             # label x (start of rel->abs loop)
/^[NESW]/q                                     # quit if string starts w/ abs char
/F([NESW]|$)/s/F([NESW]|$)/N\1/                # Matches for each direction:
/R([NESW]|$)/y/NESW/ESWN/;s/R([NESW]|$)/E\1/   #     rotate, then substitute
/B([NESW]|$)/y/NESW/SWNE/;s/B([NESW]|$)/S\1/
/L([NESW]|$)/y/NESW/WNES/;s/L([NESW]|$)/W\1/
bx                                             # loop back to x

(Commenti e spazi eliminati ai fini del calcolo del punteggio di golf)

Produzione:

$ sed -rf absrel.sed <<< NNWEESEE
FFLBFRLF
$ sed -rf absrel.sed <<< FFLBFRLF
NNWEESEE
$ 

Spiegazione:

L'idea qui è che quando cambiamo il quadro di riferimento, c'è sempre una mappatura diretta tra {N, E, S, W}e {F, R, B, L}.

Nel caso di assoluto in relativo, lavoriamo in avanti attraverso la stringa. Per ogni carattere mappiamo {N, E, S, W}a {F, R, B, L}, quindi ruotare le rimanenti [NESW]caratteri secondo il carattere che appena mappato, poi passare al carattere successivo.

Nel caso del relativo all'assoluto facciamo il contrario. Lavoriamo all'indietro attraverso la stringa, ruotando tutti i [NESW]caratteri seguenti in base al carattere immediatamente davanti. Quindi mappiamo quel personaggio fino {N, E, S, W}a {F, R, B, L}quando non arriviamo all'inizio della stringa.


0

Haskell, 224

import Data.Function
i=flip(\x->length.takeWhile(/=x))
r=['F','R','B','L']
a=['N','E','S','W']
f s@(x:_)|elem x a=map((r!!).(`mod`4).(4-))$zipWith((-)`on`(i a))('N':s)(s)|True=tail$map((a!!).(`mod`4)).scanl(+)(0)$map(i r) s

Questo assegna i numeri di rotazione alle direzioni relative e i numeri di orientamento alle direzioni assolute, quindi trova le rotazioni tra orientamenti successivi o orientamenti dopo rotazioni successive. La ifunzione trova l'indice all'interno delle due legende.

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.