우주선은 어디로 갑니까?


15

Zgarb가 제안한 아이디어를 기반으로합니다 .

우주선이 일반 3D 그리드를 따라 움직입니다. 그리드의 셀은 오른쪽 좌표계 xyz 에서 정수로 색인됩니다 . 우주선은 원점에서 시작하여 양의 x 축을 따라 , 양의 z 축은 위쪽을 가리 킵니다.

우주선은 비어 있지 않은 일련의 움직임으로 정의 된 궤도를 따라 날아갈 것입니다. 각 움직임은 F우주선이 향하는 방향으로 하나의 셀을 이동 시키거나 6 회전 중 하나를 이동시키는 (또는) 방향 UDLRlr입니다. 이들은 다음과 같이 피치, 요 및 롤에 해당합니다.

파이어
다이어그램을 생성 한 Zgarb에게 감사합니다.

  • Up와 D자신은 우주선의 피치를 90도 변경합니다 (여기서 방향은 우주선의 코의 움직임에 해당합니다).
  • L송금 및 Right 90도 우주선의 요 변화. 그들은 단지 규칙적인 좌회전과 우회전입니다.
  • left와 right는 90도 회전 운동이며, 방향은 어느 날개가 아래로 움직이는지를 나타냅니다.

이것들은 항상 우주선과 관련하여 해석되어야하므로 관련 축이 함께 회전해야합니다.

수학 용어로 우주선은 처음에 위치 (0, 0, 0)를 향하고 (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 )

우주선의 최종 위치를 세 개의 정수 x , y , z 로 출력해야합니다 . 출력은 세 개의 개별 정수 또는이를 포함하는 목록 또는 문자열 일 수 있습니다. 지정하는 한 일관된 순서로 정렬 될 수 있습니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

표준 규칙이 적용됩니다.

테스트 사례

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)

작동 예

UFLrRFLRLR테스트 케이스 의 중간 단계는 다음과 같습니다 . 여기에서 모든 중간 좌표와 방향 벡터는 우주선에 대한 하나의 로컬과는 대조적으로 초기 전역 좌표 시스템으로 제공됩니다.

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)

이 도전의 차원 일반화 이 하나 뺀 교차 부분입니다.
orlp

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

@ username.ak 질문을 이해하지 못하는 것 같습니다. 당신은 무엇을 말하는가?
Martin Ender 2019

@Martin Büttner, 왜 180도 회전이 -180과 같지 않은지, 270이 -90과 같지 않음을 말합니다
username.ak

@ username.ak 아닌가요?
Martin Ender 2019

답변:


3

MATL , 76 75 바이트

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

이 언어의 현재 버전 (12.1.1)에서 작동합니다.

편집 (2016 년 4 월 4 일) : v언어의 릴리스 15.0.0에서 기능 동작 이 변경되었습니다. 위 코드를 실행하려면 첫 번째 코드를 제거 v하고 두 번째 코드를 바꿉니다 3$v. 다음 링크에는이 수정 사항이 포함되어 있습니다.

온라인으로 사용해보십시오 !

설명

선박의 상태는 두 가지 변수로 설명 할 수 있습니다.

  • 위치 : 3x1 벡터
  • 오리엔테이션 : 누적 회전 이있는 3x3 행렬 . 여기서 "축적 된"은 반복 된 행렬 곱을 의미합니다.

세 번째 변수는 선박이 향하는 방향이지만, 초기 방향 (열 벡터 [ 1;0;0])에 현재 방향을 곱한 값으로 얻을 수 있기 때문에 필요하지 않습니다 . 즉, 방향의 첫 번째 열입니다.

이 두 가지 상태 변수는 스택에 유지되며 각 문자로 업데이트됩니다. 각 문자 ULlDRr는 방향 행렬을 6 개의 회전 행렬 중 하나로 곱하여 방향을 업데이트합니다. 문자 F는 현재 위치와 방향 행렬의 첫 번째 열을 더합니다.

6 개의 회전 행렬은 다음과 같이 생성됩니다. 첫 번째는 직접 도입됩니다. 두 번째와 세 번째는 이전의 원형 이동입니다. 나머지 3 개는 다른 버전의 조판입니다.

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

옥타브, 175 바이트

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

읽을 수있는 버전 :

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

동적 필드 이름을 잘 사용합니다!
Luis Mendo

2
"판독 가능 버전 [인용 필요]";)
trichoplax

0

ES6, 265 259 바이트

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]

설명 : 일반적으로 우주선의 방향을 계산하려면 모든 회전을 함께 구성한 다음 각 이동에 대해 결과를 단위 벡터로 구성합니다 F = (1, 0, 0)(또는 행렬의 첫 번째 열을 간단히 추출). 예를 들어 FFrlFULULF => F + F + r⋅l⋅F + r⋅l⋅U⋅L⋅L⋅L⋅F. 행렬 곱셈은 연관성이 있으므로, 행렬 곱셈이 내장 된 언어는 부분 곱을 r⋅l⋅U⋅L⋅L⋅L따라 계산 한 다음 F필요한 용어를 곱한 다음 함께 더할 수 있습니다. 불행히도 나는 그 사치가 없기 때문에 가장 저렴한 옵션은 위의 표현에서 각 용어를 개별적으로 계산하여 처음부터 F다시 작업하는 것입니다. 이를 F위해 해당 지점까지의 모든 회전 이 발생할 때마다 목록이 필요합니다 . 나는 이것을 사용하여 이것을한다.replace$`나는 또한 내가 문자열의 나머지 부분을 무시 할 수 있도록 목록의 각 기간의 시작과 끝을 표시해야하므로. 약간 골퍼되지 않음 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.