Uzay gemisi nereye gidiyor?


15

Zgarb tarafından önerilen bir fikre dayanarak .

Bir uzay gemisi düzenli bir 3B ızgara etrafında hareket ediyor. Izgaranın hücreleri, sağ elle koordinat sistemi xyz'de tamsayılarla indekslenir . Uzay gemisi başlangıçta pozitif x ekseni boyunca , pozitif z ekseni yukarı bakacak şekilde başlar.

Uzay gemisi, boş olmayan bir hareket dizisi ile tanımlanan bir yörünge boyunca uçacaktır. Her hareket ya F( ya da ileri) olup, uzay gemisinin bir hücreyi baktığı yöne doğru hareket ettirmesini ya da altı rotasyondan birini gerçekleştirmesini sağlar UDLRlr. Bunlar aşağıdaki gibi eğim, sapma ve ruloya karşılık gelir:

PYR
Diyagramı oluşturduğu için Zgarb'a teşekkürler.

  • Up ve Dkendi uzay gemisinin perdesini 90 derece değiştirir (burada yön uzay gemisinin burnunun hareketine karşılık gelir).
  • Left ve Right uzay gemisinin sapmasını 90 derece değiştirir. Bunlar sadece düzenli sola ve sağa dönüşlerdir.
  • left ve right 90 derecelik yuvarlanma hareketleridir, burada yön hangi kanadın aşağı doğru hareket ettiğini gösterir.

Bunların daima uzay gemisine göre yorumlanması gerektiğini unutmayın, böylece ilgili eksenler onunla birlikte dönecektir.

Matematiksel terimlerle, uzay gemisi başlangıçta vektör (0, 0, 0)boyunca, yukarı bakacak şekilde pozisyondadır . Döndürmeler, koordinat sistemine uygulanan aşağıdaki matrislere karşılık gelir:(1, 0, 0)(0, 0, 1)

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 )

Uzay gemisinin son konumunu üç x , y , z tamsayı olarak çıkarmalısınız . Çıktı üç ayrı tamsayı veya bunları içeren bir liste veya dize olabilir. Belirttiğiniz sürece tutarlı bir sırada olabilirler.

STDIN (veya en yakın alternatif), komut satırı bağımsız değişkeni veya işlev bağımsız değişkeni ile girdi alarak ve sonucu STDOUT (veya en yakın alternatif), işlev dönüş değeri veya işlev (çıkış) parametresi aracılığıyla çıktı alarak bir program veya işlev yazabilirsiniz.

Standart kuralları geçerlidir.

Test Durumları

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)

Çalışılan örnek

İşte UFLrRFLRLRtest senaryosunun ara adımları . Burada, tüm ara koordinatlar ve yön vektörleri ilk küresel koordinat sisteminde (uzay gemisinin bir yerelinin aksine) verilir:

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)

Bu zorluk 3D genellemedir bu bir eksi kavşak parçası.
orlp

Neden 2! = 2, 3! = -1, 4! = 0! = -4, 1! = -3
kullaniciadi.ak

@ username.ak Soruyu anladığımı sanmıyorum. Ne demek istiyorsun?
Martin Ender

@Martin Büttner, 180 derece dönüşün neden -180 ile aynı olmadığını, 270'in -90 vb. İle aynı olmadığını söylüyorum
kullaniciadi.ak

@ kullaniciadi.ak değil mi?
Martin Ender

Yanıtlar:


3

MATL , 76 75 bayt

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

Bu, dilin geçerli sürümünde (12.1.1) çalışır.

Edit (4 Nisan 2016): vDilin 15.0.0 sürümünde işlev davranışı değişti. Yukarıdaki kodu çalıştırmak için ilk kodu kaldırın vve ikincisini değiştirin 3$v. Aşağıdaki bağlantı bu değişikliği içerir.

Çevrimiçi deneyin !

açıklama

Geminin durumu iki değişken olarak tanımlanabilir:

  • pozisyon: 3x1 vektör
  • oryantasyon: "birikmiş" tekrarlanan matris ürünü anlamına gelir , birikmiş dönme ile 3x3 matris .

Üçüncü bir değişken, geminin baktığı yön olabilir, ancak bu gerekli değildir, çünkü başlangıç ​​yönü olarak elde edilebilir (sütun vektörü [1;0;0] mevcut yönün ) ; yani, oryantasyonun ilk sütunu.

Bu iki durum değişkeni yığın üzerinde tutulur ve her harfle güncellenir. Harflerin her biri, ULlDRryönlendirmeyi güncellemek için yönlendirme matrisini altı dönüş matrisinden biriyle çarpar. Harf Fgeçerli konumu ve yönlendirme matrisinin ilk sütununu ekler.

Altı rotasyon matrisi aşağıdaki gibi oluşturulur: ilk önce doğrudan verilir; ikincisi ve üçüncüsü bir öncekinin dairesel kaymalarıdır; ve geri kalan üçü diğerlerinin aktarılmış versiyonlarıdır.

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

Oktav, 175 bayt

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

Okunabilir sürüm:

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

Dinamik alan adlarının güzel kullanımı!
Luis Mendo

2
"Okunabilir sürüm [alıntı gerekli]";)
trichoplax

0

ES6, 265 259 bayt

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]

Açıklama: Normalde uzay gemisinin yönünü hesaplamak için tüm dönüşleri bir araya getirirsiniz ve daha sonra her hareket için sonucu birim vektörüne yazarsınız F = (1, 0, 0)(veya matrisin ilk sütununu basitçe çıkarırsınız). Örneğin FFrlFULULF => F + F + r⋅l⋅F + r⋅l⋅U⋅L⋅L⋅L⋅F,. Matris çarpımı ilişkilendirilebilir olduğundan, yerleşik matris çarpımına sahip diller r⋅l⋅U⋅L⋅L⋅L, ileride Fbirlikte eklenen terimleri üretmek için gerektiği kadar çarparak kısmi ürünü açık bir şekilde hesaplayabilir . Ne yazık ki bu lüksüm yok, bu yüzden en ucuz seçenek, yukarıdaki ifadedeki her terimi ayrı ayrı hesaplamak Fve başlamak . Bunun için, Fo noktaya kadar tüm rotasyonların her biri için bir listeye ihtiyacım var . Bunu kullanarak yaparımreplaceile $`Ben de dize geri kalanını görmezden böylece listedeki her dönem başlangıcını ve sonunu işaretlemek gerekir böylece. Hafifçe soluksuz:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.