Wohin fährt das Raumschiff?

15

Basierend auf einer Idee von Zgarb .

Ein Raumschiff bewegt sich um ein normales 3D-Gitter. Die Zellen des Gitters sind mit ganzen Zahlen in einem rechtshändigen Koordinatensystem, xyz, indiziert . Das Raumschiff beginnt am Ursprung und zeigt entlang der positiven x- Achse, wobei die positive z- Achse nach oben zeigt.

Das Raumschiff fliegt entlang einer Flugbahn, die durch einen nicht leeren Bewegungsablauf definiert ist. Jede Bewegung ist entweder F(oder vorwärts), wodurch sich das Raumschiff um eine Zelle in Richtung seiner Ausrichtung bewegt, oder eine der sechs Umdrehungen UDLRlr. Dies entspricht dem Pitch, Yaw und Roll wie folgt:

PYR
Vielen Dank an Zgarb für die Erstellung des Diagramms.

  • Up und Down ändern die Tonhöhe des Raumschiffs um 90 Grad (wobei die Richtung der Bewegung der Nase des Raumschiffs entspricht).
  • LNach und Rnach ändert sich das Gieren des Raumschiffs um 90 Grad. Sie sind nur regelmäßige Links- und Rechtskurven.
  • lEft und rEight sind 90-Grad-Rollbewegungen, wobei die Richtung angibt, welcher Flügel sich nach unten bewegt.

Beachten Sie, dass diese immer relativ zum Raumschiff interpretiert werden sollten, damit die relevanten Achsen mitrotieren.

Mathematisch gesehen befindet sich das Raumschiff zunächst an einer Position (0, 0, 0), die entlang des (1, 0, 0)Vektors zeigt und (0, 0, 1)nach oben zeigt. Die Rotationen entsprechen den folgenden Matrizen, die auf das Koordinatensystem angewendet werden:

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 )

Sie sollten die endgültige Position des Raumschiffs als drei ganze Zahlen x , y , z ausgeben . Die Ausgabe kann aus drei separaten Ganzzahlen oder einer Liste oder Zeichenfolge bestehen, die sie enthält. Sie können in beliebiger Reihenfolge angeordnet sein, solange Sie dies angeben.

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Es gelten die Standardregeln für .

Testfälle

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)

Gearbeitetes Beispiel

Hier sind die Zwischenschritte des UFLrRFLRLRTestfalls. Hier werden alle Zwischenkoordinaten und Richtungsvektoren im anfänglichen globalen Koordinatensystem (im Gegensatz zu einem lokalen zum Raumschiff) angegeben:

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)
Martin Ender
quelle
Diese Herausforderung ist eine 3D-Verallgemeinerung dieser Herausforderung abzüglich des Kreuzungsteils.
Orlp
Warum ist 2! = 2, 3! = -1, 4! = 0! = -4, 1! = -3
username.ak
@ username.ak Ich glaube nicht, dass ich die Frage verstehe. Worauf beziehen Sie sich?
Martin Ender
@ Martin Büttner, ich sage, warum 180-Grad-Drehung nicht gleich -180 ist, 270 nicht gleich -90 usw.
Benutzername.ak
@ username.ak ist es nicht?
Martin Ender

Antworten:

3

MATL , 76 75 Bytes

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

Dies funktioniert in der aktuellen Version (12.1.1) der Sprache.

Bearbeiten (4. April 2016): Das Funktionsverhalten vwurde in Version 15.0.0 der Sprache geändert. Entfernen Sie das erste, vund ersetzen Sie das zweite, um den obigen Code auszuführen 3$v. Der folgende Link enthält diese Änderung.

Probieren Sie es online !

Erläuterung

Der Zustand des Schiffes kann mit zwei Variablen beschrieben werden:

  • Position: 3x1 Vektor
  • Orientierung: 3x3 Matrix mit der akkumulierten Rotation, wobei "akkumuliert" wiederholtes Matrixprodukt bedeutet.

Eine dritte Variable wäre die Richtung, in die das Schiff blickt, dies ist jedoch nicht erforderlich, da sie als Anfangsrichtung (Spaltenvektor [ 1;0;0]) multipliziert mit der aktuellen Ausrichtung erhalten werden kann. das ist die erste Spalte der Orientierung.

Diese beiden Statusvariablen werden auf dem Stapel gespeichert und mit jedem Buchstaben aktualisiert. Jeder der Buchstaben ULlDRrmultipliziert die Orientierungsmatrix mit einer der sechs Rotationsmatrizen, um die Orientierung zu aktualisieren. Letter Ffügt die aktuelle Position plus die erste Spalte der Orientierungsmatrix hinzu.

Die sechs Rotationsmatrizen werden wie folgt erzeugt: Zuerst wird direkt eingeführt; zweite und dritte sind kreisförmige Verschiebungen der vorherigen; und die restlichen drei sind transponierte Versionen der anderen.

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
Luis Mendo
quelle
1

Oktave, 175 Bytes

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

Lesbare Version:

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
Rainer P.
quelle
Gute Verwendung dynamischer Feldnamen!
Luis Mendo
2
"Lesbare Version [Zitieren benötigt]";)
Trichoplax
0

ES6, 265 259 Bytes

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]

Erklärung: Um die Richtung des Raumschiffs zu berechnen, würden Sie normalerweise alle Rotationen zusammensetzen und dann für jede Bewegung das Ergebnis zum Einheitsvektor zusammensetzen F = (1, 0, 0)(oder einfach die erste Spalte der Matrix extrahieren). Zum Beispiel FFrlFULULF => F + F + r⋅l⋅F + r⋅l⋅U⋅L⋅L⋅L⋅F. Da die Matrixmultiplikation assoziativ ist, können Sprachen mit integrierter Matrixmultiplikation offensichtlich das Teilprodukt berechnen r⋅l⋅U⋅L⋅L⋅L, indem sie nach FBedarf multipliziert werden , um die Terme zu erzeugen, die dann addiert werden. Leider habe ich diesen Luxus nicht, daher ist es die billigste Möglichkeit, jeden Begriff im obigen Ausdruck separat zu berechnen, beginnend mit Fund abarbeitend. Dafür benötige ich eine Liste für jedes Vorkommen Faller Rotationen bis zu diesem Punkt. Ich mache das mitreplacemit $`so muß ich auch den Beginn und das Ende jeden Begriff in der Liste markieren , so dass ich den Rest der Zeichenfolge ignorieren kann. Leicht ungolfed:

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
Neil
quelle