Dove va l'astronave?


15

Basato su un'idea suggerita da Zgarb .

Un'astronave si muove attorno a una normale griglia 3D. Le celle della griglia sono indicizzate con numeri interi in un sistema di coordinate destrorso, xyz . L'astronave inizia all'origine, puntando lungo l' asse x positivo , con l' asse z positivo rivolto verso l'alto.

L'astronave volerà lungo una traiettoria definita da una sequenza di movimenti non vuota. Ogni movimento è F(verso oriente) che fa muovere l'astronave di una cella nella direzione in cui è rivolta, o una delle sei rotazioni UDLRlr. Questi corrispondono a beccheggio, imbardata e rollio come segue:

PYR
Grazie a Zgarb per aver creato il diagramma.

  • Up e Dproprio cambiare il passo dell'astronave di 90 gradi (dove la direzione corrisponde al movimento del naso dell'astronave).
  • Logni volta che Rcambia l'imbardata della nave spaziale di 90 gradi. Sono solo curve a destra e sinistra.
  • left e right sono movimenti di rotolamento di 90 gradi, dove la direzione indica quale ala si muove verso il basso.

Si noti che questi devono sempre essere interpretati in relazione all'astronave in modo che gli assi pertinenti ruotino insieme ad essa.

In termini matematici, l'astronave è inizialmente in posizione (0, 0, 0), che punta lungo il (1, 0, 0)vettore, con la (0, 0, 1)punta verso l'alto. Le rotazioni corrispondono alle seguenti matrici applicate al sistema di coordinate:

U = ( 0  0 -1     D = ( 0  0  1
      0  1  0           0  1  0
      1  0  0 )        -1  0  0 )

L = ( 0 -1  0     R = ( 0  1  0
      1  0  0          -1  0  0
      0  0  1 )         0  0  1 )

l = ( 1  0  0     r = ( 1  0  0
      0  0  1           0  0 -1
      0 -1  0 )         0  1  0 )

Dovresti emettere la posizione finale dell'astronave come tre numeri interi x , y , z . L'output può essere tre numeri interi separati o un elenco o una stringa che li contiene. Possono essere in qualsiasi ordine coerente purché tu lo specifichi.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Si applicano le regole standard del .

Casi test

F                                                   => (1, 0, 0)
FDDF                                                => (0, 0, 0)
FDDDF                                               => (1, 0, 1)
LrDDlURRrr                                          => (0, 0, 0)
UFLrRFLRLR                                          => (1, 0, 1)
FFrlFULULF                                          => (3, 0, -1)
LLFRLFDFFD                                          => (-2, 0, -2)
FrrLFLFrDLRFrLLFrFrRRFFFLRlFFLFFRFFLFlFFFlUFDFDrFF  => (1, 5, 7)
FUrRLDDlUDDlFlFFFDFrDrLrlUUrFlFFllRLlLlFFLrUFlRlFF  => (8, 2, 2)
FFLrlFLRFFFRFrFFFRFFRrFFFDDLFFURlrRFFFlrRFFlDlFFFU  => (1, 2, -2)
FLULFLFDURDUFFFLUlFlUFLFRrlDRFFFLFUFrFllFULUFFDRFF  => (-3, -2, -3)

Esempio lavorato

Ecco i passaggi intermedi del UFLrRFLRLRtest case. Qui, tutte le coordinate intermedie e i vettori di direzione sono indicati nel sistema di coordinate globale iniziale (al contrario di un locale dell'astronave):

Cmd.  Position    Forward     Up
      ( 0, 0, 0)  ( 1, 0, 0)  ( 0, 0, 1)
U     ( 0, 0, 0)  ( 0, 0, 1)  (-1, 0, 0)
F     ( 0, 0, 1)  ( 0, 0, 1)  (-1, 0, 0)
L     ( 0, 0, 1)  ( 0, 1, 0)  (-1, 0, 0)
r     ( 0, 0, 1)  ( 0, 1, 0)  ( 0, 0, 1)
R     ( 0, 0, 1)  ( 1, 0, 0)  ( 0, 0, 1)
F     ( 1, 0, 1)  ( 1, 0, 0)  ( 0, 0, 1)
L     ( 1, 0, 1)  ( 0, 1, 0)  ( 0, 0, 1)
R     ( 1, 0, 1)  ( 1, 0, 0)  ( 0, 0, 1)
L     ( 1, 0, 1)  ( 0, 1, 0)  ( 0, 0, 1)
R     ( 1, 0, 1)  ( 1, 0, 0)  ( 0, 0, 1)

Questa sfida è una generalizzazione 3D di questa , meno la parte di intersezione.
orlp,

Perché 2! = 2, 3! = -1, 4! = 0! = -4, 1! = -3
username.ak

@ username.ak Non credo di aver capito la domanda. A cosa ti riferisci?
Martin Ender,

@Martin Büttner, dico perché la rotazione di 180 gradi non è la stessa di -180, 270 non è la stessa di -90 ecc.
username.ak

@ username.ak non è vero?
Martin Ender,

Risposte:


3

MATL , 76 75 byte

FFF!3Xyj"FFT_FTFv4BvtFT_YStTF_YS3:"3$y!]6$Xh@'ULlDRr'4#mt?X)Y*}xxt1Z)b+w]]x

Funziona nella versione corrente (12.1.1) della lingua.

Modifica (4 aprile 2016): il comportamento della funzione vè cambiato nella versione 15.0.0 della lingua. Per eseguire il codice sopra riportato, rimuovere il primo ve sostituire il secondo 3$v. Il seguente link include questa modifica.

Provalo online !

Spiegazione

Lo stato della nave può essere descritto in base a due variabili:

  • posizione: vettore 3x1
  • orientamento: matrice 3x3 con la rotazione accumulata , dove "accumulato" significa prodotto a matrice ripetuta.

Una terza variabile sarebbe la direzione in cui è rivolta la nave, ma non è necessaria, poiché può essere ottenuta come direzione iniziale (vettore colonna [ 1;0;0]) per l'orientamento corrente; cioè, la prima colonna dell'orientamento.

Queste due variabili di stato vengono mantenute nello stack e vengono aggiornate con ogni lettera. Ciascuna delle lettere ULlDRrmoltiplica la matrice di orientamento per una delle sei matrici di rotazione per aggiornare l'orientamento. La lettera Faggiunge la posizione corrente più la prima colonna della matrice di orientamento.

Le sei matrici di rotazione vengono create come segue: la prima viene introdotta direttamente; il secondo e il terzo sono spostamenti circolari del precedente; e le restanti tre sono trasposte versioni delle altre.

FFF!             % 3x1 vector [0;0;0]: initial position
3Xy              % 3x3 identity matrix: initial orientation
j                % input string
"                % for-each character in that string
  FFT_FTFv4Bv    %   rotation matrix for U: defined directly
  tFT_YS         %   rotation matrix for L: U circularly shifted to the left
  tTF_YS         %   rotation matrix for l: L circularly shifted down
  3:"            %   repeat three times
    3$y!         %     copy third matrix from top and transpose
  ]              %   end loop. This creates rotation matrices for D, R, r
  6$Xh           %   pack the 6 matrices in a cell array
  @              %   push current character from the input string
  'ULlDRr'4#m    %   this gives an index 0 for F, 1 for U, 2 for L, ..., 6 for r
  t?             %   if non-zero: update orientation
    X)           %     pick corresponding rotation matrix
    Y*           %     matrix product
  }              %   else: update position
    xx           %     delete twice (index and rotation matrix are not used here)
    t1Z)         %     duplicate orientation matrix and take its first column
    b+           %     move position vector to top and add
    w            %     swap the two top-most elements in stack
  ]              %   end if
]                % end for-each
x                % delete orientation matrix
                 % implicitly display position vector

1

Ottava, 175 byte

function p=s(i)m.U=[0,0,-1;0,1,0;1,0,0];m.D=m.U';m.L=[0,-1,0;1,0,0;0,0,1];m.R=m.L';m.l=flip(flip(m.L),2);m.r=m.l';a=m.F=eye(3);p=[0;0;0];for c=i p+=(a*=m.(c))*[c=='F';0;0];end

Versione leggibile:

function p=s(i)
  m.U=[0,0,-1;0,1,0;1,0,0];
  m.D=m.U';
  m.L=[0,-1,0;1,0,0;0,0,1];
  m.R=m.L';
  m.l=flip(flip(m.L),2);
  m.r=m.l';
  a=m.F=eye(3);
  p=[0;0;0];
  for c=i p+=(a*=m.(c))*[c=='F';0;0];
end

Buon uso di nomi di campi dinamici!
Luis Mendo,

2
"Versione leggibile [citazione necessaria]";)
trichoplax,

0

ES6, 265 259 byte

s=>[...s.replace(/F/g,"f$`s")].reverse().map(e=>d={U:(x,y,z)=>[-z,y,x],D:(x,y,z)=>[z,y,-x],L:(x,y,z)=>[-y,x,z],R:(x,y,z)=>[y,-x,z],r:(x,y,z)=>[x,-z,y],l:(x,y,z)=>[x,z,-y],F:(...d)=>d,f:(x,y,z)=>[a+=x,b+=y,c+=z]),s:_=>[1,0,0]}[e](...d),d=[1,0,a=b=c=0])&&[a,b,c]

Spiegazione: Normalmente per calcolare la direzione dell'astronave si comporrebbero insieme tutte le rotazioni, e quindi per ogni mossa si comporre il risultato sul vettore unità con quindi ho anche bisogno di segnare l'inizio e la fine di ogni termine nell'elenco quindi che posso ignorare il resto della stringa. Leggermente non golfato:F = (1, 0, 0) (o più semplicemente estrarre la prima colonna della matrice). Per esempio, FFrlFULULF => F + F + r⋅l⋅F + r⋅l⋅U⋅L⋅L⋅L⋅F. Poiché la moltiplicazione di matrici è associativa, i linguaggi con moltiplicazione di matrici incorporate possono ovviamente calcolare il prodotto parziale r⋅l⋅U⋅L⋅L⋅Lman mano che procedono, moltiplicandosi per Fquanto necessario per produrre i termini che vengono poi sommati. Sfortunatamente non ho quel lusso, quindi l'opzione più economica è calcolare ogni termine nell'espressione precedente separatamente, iniziando Fe lavorando indietro. Per questo, ho bisogno di un elenco per ciascuna delle occorrenze Fdi tutte le rotazioni fino a quel punto. Lo faccio usandoreplace$`

s=>[... // split the string into separate operations
    s.replace(/F/g,"f$`s")] // For each 'F', wrap the operations up to that point
  .reverse() // Play all the operations in reverse order
  .map(e=>d= // Update the direction for each operation
    { // set of operations
      U:(x,y,z)=>[-z,y,x], // Up
      D:(x,y,z)=>[z,y,-x], // Down
      L:(x,y,z)=>[-y,x,z], // Left turn
      R:(x,y,z)=>[y,-x,z], // Right turn
      r:(x,y,z)=>[x,-z,y], // right roll
      l:(x,y,z)=>[x,z,-y], // left roll
      F:(...d)=>d, // does nothing, `s` and `f` do the work now
      f:(x,y,z)=>[a+=x,b+=y,c+=z], // do the move
      s:_=>[1,0,0] // back to start
    }[e](...d), // apply the operation to the current direction
    d=[1,0,a=b=c=0] // initialise variables
  )&&[a,b,c] // return result
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.