2D 공간에서 물체 추적


11

기술

이 과제의 과제는 공간 에서 주어진 물체를 추적하는 프로그램 또는 기능을 고안하는 것 입니다.n×n

I / O

귀하의 프로그램에는 3 가지 입력이 주어지며, 이는 합리적인 방법 으로 취할 수 있습니다 :

n평면의 크기가됩니다. 따라서 경우 평면은 입니다. 항상 홀수 정수 라고 가정 할 수 있습니다 .n=55×5n

s 좌표 쌍으로 제공된 객체의 시작 위치가 됩니다.(x,y)

D순서 쌍으로 구성된 벡터가됩니다. D포맷 따를 , 여기서 항상 것 하나 의 기수 일차 intercardinal 방향에 대한, 그리고 것 '틱'수에 대한 정수D=[(d0,t0),(d1,t1),...,(dn,tn)]dkt k'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'tk

이러한 입력이 주어지면 프로그램은 평면에서 객체의 추적을 출력해야합니다.

규칙

출력 에는 평면의 경계 포함 되어야 합니다. 예 :

-21012 +
+ ┌─────┐
2│ │
1│ │
0│ │
1│ │
2│ │
-└─────┘

빈 평면 의 예입니다 . 위와 옆의 숫자는 참조 용일 뿐이며 인쇄 할 필요는 없습니다.5×5

공백이 아니거나 공백으로 렌더링되는 한 경계에 어떤 문자를 사용할 수 있습니다. 선택한 문자는 전체 평면을 나타냅니다. 즉, 문자 사이에 간격이 없어야합니다.

허용되는 비행기는 다음과 같습니다.

┌──┐ .... ---- +-+
│ │. . | | | |
│ │. . | | | |
└──┘; ....; ----; +-+

허용되지 않는 비행기는 다음과 같습니다.

      .... .... ++++. .
            . . + +. .
            . + +. .
    ; ....; ....; + +; . .

추적 할 객체는 평면에서 1 개의 공간 만 차지하고 경계 문자와 다른 한 선택한 문자가 될 수 있습니다.

추적 된 객체의 추적은 평면에서 1 개의 공간 만 차지하고 객체와 다른 한 선택한 문자가 될 수 있습니다.

각 요소 에 대해 객체는 공간을 쪽으로 이동 하고 추적을 남겨야합니다.(dk,tk)Dtd

객체가 경계에 부딪히면 반영됩니다. 개체가 여전히 왼쪽으로 움직이면 반영된 방향으로 계속 움직입니다.

참고로 이러한 방향은 서로 반영됩니다.

NS → 상단 또는 하단 경계가 충족 될 때;

EW 경계 → 측면 경계에 했을 때;

최종 출력에는 가능한 가장 새로운 트레이스가 포함됩니다. 즉, 이미 트레이스가있는 공간에 객체가 트레이스를 남기면 새로운 트레이스 문자가 더 오래된 트레이스를 덮어 씁니다.

일반적으로 표준 허점은 기본적으로 금지되어 있습니다.

채점 :

이것은 도전입니다.

예 :

입력 : , ,n=5s=(0,0)D=[(NW,2),(S,2),(E,1)]

그것을 해결 :

t=0

    0
 ┌─────┐
 │ │
 │ │
0│ ○ │
 │ │
 │ │
 └─────┘

t=2

    0
 ┌─────┐
 │ ○ │
 │ \ │
0│ \ │
 │ │
 │ │
 └─────┘

t=4

    0
 ┌─────┐
 │∧ │
 │ | \ │
0│ ○ \ │
 │ │
 │ │
 └─────┘

t=5 이며 출력이됩니다.

    0
 ┌─────┐
 │∧ │
 │ | \ │
0│└ ○ \ │
 │ │
 │ │
 └─────┘

(0은 단지 참조 용이며 최종 출력에있을 필요는 없습니다.)


입력 : n=9 , s=(3,1) , D=[(N,2),(SW,8),(SE,3),(NE,8)]

공지 사항 t=10 :

      0     
 ┌─────────┐
 │ │
 │ │
 │ │
 │ ∧ │
0│ / | │
 │ ○ / | │
 │⟨ / │
 │ \ / │
 │ ∨ │
 └─────────┘

물체가 반사되어 일단 도달 할 때 바닥 향해 진행하는 평면 SW 는에 반영 NW ; 다시 한번 도달 할 때 좌측 면의 NW 로 반영 NE .

최종 출력은 t=21 .

      0     
 ┌─────────┐
 │ ○ │
 │ \ │
 │ \ │
 │ \ │
0│ / | ⟩│
 │ ∧ / / │
 │⟨ \ / / │
 │ \ \ / │
 │ ∨ ∨ │
 └─────────┘

테스트 사례 :

n=5s=(0,0)D=[(NW,2),(S,2),(E,1)]

산출:

    0
 ┌─────┐
 │∧ │
 │ | \ │
0│└ ○ \ │
 │ │
 │ │
 └─────┘


입력 : n=9 , s=(3,1) , D=[(N,2),(SW,8),(SE,3),(NE,8)]

산출:

      0     
 ┌─────────┐
 │ ○ │
 │ \ │
 │ \ │
 │ \ │
0│ / | ⟩│
 │ ∧ / / │
 │⟨ \ / / │
 │ \ \ / │
 │ ∨ ∨ │
 └─────────┘


입력 : n=3 , s=(1,1) , D=[(N,5),(W,5)]

산출:

   0
 ┌───┐
 │ | │
0│- ○ ┐│
 │ | │
 └───┘


입력 : n=11 , s=(3,5) , D=[(NW,8),(E,5),(SE,3),(SW,5),(N,6),(NE,10)]

산출:

       0
 ┌───────────┐
 │ ∧ │
 │ / \ │
 │┌-/-\ \ │
 │ \ | / \ \ │
 │ \ | \ │
0│ | / ⟩│
 │ | \ / / │
 │ | / ○ │
 │ | / \ │
 │ ∨ \ │
 │ \ │
 └───────────┘

이 도전이 샌드 박스 였다는 것을 잊어 버렸습니다 .
J. Sallé

우리가 취할 수 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'a는 0 색인 정수 대신 (또는 1 인덱스)로? 그래서 [('NW',2),('S',2),('E',1)]이된다 [[7,2],[4,2],[2,1]]예를 들어.
Kevin Cruijssen

@KevinCruijssen 물론 문제 없습니다. 대답에서 지적하십시오.
J. Sallé

1
@Arnauld 예, 단일 추적 문자를 사용할 수 있습니다. 테스트 사례를보다 쉽게 ​​시각화 할 수 있도록 둘 이상을 사용했지만 반드시 그럴 필요는 없습니다. 추적 문자가 추적중인 오브젝트의 문자와 다른지 확인하십시오.
J. Sallé

1
@Arnauld " 추적 할 개체는 평면의 한 칸만 차지하고 경계 문자와 다른 한 원하는 문자 일 수 있습니다. 추적 된 개체의 추적은 선택한 문자 일 수도 있습니다. 비행기에서 1 개의 공간 만 차지하고 물체와는 다른 점이 있습니다. "
Kevin Cruijssen

답변:


9

자바 스크립트 (ES6), 228 바이트

(n,x,y,[[dir,len],[dir,len],...])07

0경계, 1추적 및 3최종 위치 가 포함 된 문자열을 출력합니다 .

(n,x,y,a)=>(g=X=>Y>n?'':(Y%n&&X%n&&a.map(([d,l],i)=>(M=H=>(h-X|v-Y||(k|=a[i+!l]?1:3),l--&&M(H=(h+H)%n?H:-H,h+=H,v+=V=(v+V)%n?V:-V)))(~-(D='12221')[d],V=~-D[d+2&7]),h=x+n/2,v=n/2-y,k=' ')&&k)+(X<n?'':`
`)+g(X++<n?X:!++Y))(Y=!++n)

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

어떻게?

'캔버스'(즉, 문자 행렬)로 초기화하고 그리는 것은 JavaScript에서 약간 지루하고 길다.

이 코드는 다른 전략을 사용합니다. 출력을 2D 배열로 저장하는 대신 왼쪽에서 오른쪽으로, 위에서 아래로 문자열을 문자별로 작성합니다. 각 반복에서 :

  • 0경계를 넘으면 a를 출력합니다 .
  • 그렇지 않으면 전체 경로를 시뮬레이션하여 현재 위치를 교차하는지 확인합니다. 우리 출력하거나 1또는 3그렇습니다, 또는 다른 공간합니다.
  • 올바른 경계에 도달하면 줄 바꿈을 추가합니다.

대체로 이것이 가장 짧은 접근법은 아니지만 시도해 볼 가치가 있다고 생각했습니다.


9

자바 10 350 343 340 336 바이트

(n,s,S,D)->{int N=n+2,x=N/2+s,y=N/2-S,i=N*N;var r=new char[N][N];for(;i-->0;)r[i/N][i%N]=i/N*(i%N)<1|i/N>n|i%N>n?'#':32;r[y][x]=42;for(var d:D)for(i=d[0];d[1]-->0;r[y+=i%7<2?1/y*2-1:i>2&i<6?y<n?1:-1:0][x+=i>0&i<4?x<n?1:-1:i>4?1/x*2-1:0]=42)i=y<2&i<2|y>=n&i>2&i<5?4-i:x<2&i>4|x>=n&i>0&i<4?8-i:y<2&i>6?5:y<n|i!=5?i:7;r[y][x]=79;return r;}

D방향이 0 색인 정수인 2D 정수 배열 N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7입니다. 시작 x,y좌표는 두 개의 개별 매개 변수 sS입니다. 출력은 문자 행렬입니다.
그것은 사용 #, 테두리로 *흔적으로, 및 O종료 위치에 대한 (그러나 세 가지 모두 유니 코드 범위에있는 ASCII 문자가 될 수 있습니다 [33,99]당신이 원하는 원하는 경우 동일 바이트 카운트).

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

@ceilingcat 덕분에 -4 바이트 .
움직임을 단순화하고 더 많은 방향으로 나아가면서 확실히 골프를 더 할 수 있습니다.

설명:

(n,s,S,D)->{           // Method with `n`,`s,S`,`D` parameters & char-matrix return-type
  int N=n+2,           //  Set `N` to `n+2`, since we use it multiple times
      x=N/2+s,         //  Calculate the starting `x` coordinate
      y=N/2-S,         //  Calculate the starting `y` coordinate
      i=N*N;           //  Index integer
  var r=new char[N][N];//  Result char-matrix of size `N` by `N`
  for(;i-->0;)         //  Loop `i` in the range (`N**2`, 0]
    r[i/N][i%N]=       //    Set the cell at position `i` divmod-`N` to:
      i/N*(i%N)<1|i/N>n|i%N>n?
                       //     If we're at a border:
       '#'             //      Set the current cell to '#'
      :                //     Else:
       32;             //      Set the current cell to ' ' (a space) instead
  r[y][x]=42;          //  Then set the starting position `x,y` to a '*'
  for(var d:D)         //  Loop over the `D` input:
    for(i=d[0];        //   Set `i` to the current direction
        d[1]-->0       //   Inner loop the current `d` amount of times
        ;              //     After every iteration:
         r[y+=         //      Change `y` based on the current direction
            i%7<2?     //       If the current direction is N, NE, or NW
             1/y*2-1   //        If we're at the top border:
                       //         Go one row down
                       //        Else
                       //         Go one row up
            :i>2&i<6?  //       Else-if the current direction is S, SE, or SW
             y<n?      //        If we're at the bottom border
              1        //         Go one row up
             :         //        Else
              -1       //         Go one row down
            :          //       Else (directions E or W)
             0]        //        Stay in the same row
          [x+=         //      Change `x` based on the current direction
            i>0&i<4?   //       If the current direction is E, NE, or SE
             x<n?      //        If we're NOT at the right border
              1        //         Go one column to the right
             :         //        Else:
              -1       //         Go one column to the left
            :i>4?      //       Else-if the current direction is W, NW, or SW
             1/x*2-1   //        If we're NOT at the left border:
                       //         Go one column to the left
                       //        Else:
                       //         Go one column to the right
            :          //       Else (directions N or S)
             0]        //        Stay in the same column
               =42)    //      And fill this new `x,y` cell with a '*'
      i=               //    Determine the new direction
        y<2&i<2|y>=n&i>2&i<5?4-i:x<2&i>4|x>=n&i>0&i<4?8-i:y<2&i>6?5:y<n|i!=5?i:7;
                       //     (See loose explanation below)
  r[y][x]=79;          //  And finally set the last `x,y` cell to 'O'
  return r;}           //  And return the result-matrix

y<2&i<2|y>=n&i>2&i<5?4-i:x<2&i>4|x>=n&i>0&i<4?8-i:y<2&i>6?5:y<n|i!=5?i:7아래에 설명이의 golfed 버전 4-i8-i대부분의 방향 변화는 :

y<2?     // If we're at the top border
 i==0?   //  If the current direction is N
  4      //   Change it to direction S
 :i==1?  //  Else-if the current direction is NE
  3      //   Change it to SE
 :i==7?  //  Else-if the current direction is NW
  5      //   Change it to SW
 :       //  Else
  i      //   Leave the direction the same
:x<2?    // Else-if we're at the left border
 i==7?   //  If the current direction is NW
  1      //   Change it to NE
 :i==6?  //  Else-if the current direction is W
  2      //   Change it to E
 :i==5?  //  Else-if the current direction is SW
  3      //   Change it to SE
 :       //  Else
  i      //   Leave the direction the same
:y>=n?   // Else-if we're at the bottom border
 i==3?   //  If the current direction is SE
  1      //   Change it to NE
 :i==4?  //  Else-if the current direction is S
  0      //   Change it to N
 :i==5?  //  Else-if the current direction is SW
  7      //   Change it to NW
 :       //  Else
  i      //   Leave the direction the same
:x>=n?   // Else-if we're at the right border
 i==1?   //  If the current direction is NE
  7      //   Change it to NW
 :i==2?  //  Else-if the current direction is E
  6      //   Change it to W
 :i==3?  //  Else-if the current direction is SE
  5      //   Change it to SW
 :       //  Else
  i      //   Leave the direction the same
:        // Else
 i       //  Leave the direction the same

3

, 74 바이트

NθJ⊘⊕θ⊘⊕θUR±⊕⊕θJN±NFA«≔⊟ιζF⊟ι«≔ζδ↷δ¶F›⊗↔ⅈθ≦±ζF›⊗↔ⅉθ≦⁻⁴ζ≧﹪⁸ζ↷⁴¶↶⁴↶δ↷ζ*¶↶ζPo

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. n, x, y, d 형식으로 입력을받습니다. 여기서 d는 방향이 숫자 인코딩 0 = 남쪽에서 7 = 남동쪽 인 숫자 인 [거리, 방향] 쌍의 배열 배열입니다. 설명:

NθJ⊘⊕θ⊘⊕θUR±⊕⊕θ

n내부가 원점을 중심으로하는 크기의 상자를 입력 하고 그립니다.

JN±N

입력하고 점프 x하고으로 이동합니다 y(그러나 y숯의 y 축이 아래로 증가 하기 때문에 부정 합니다).

FA«

의 항목을 반복합니다 d.

≔⊟ιζ

초기 방향을 추출하십시오.

F⊟ι«

원하는 거리만큼 반복하십시오.

≔ζδ

방향을 저장하십시오.

↷δ¶

그 방향으로 실험 이동하십시오.

F›⊗↔ⅈθ≦±ζ

이것이 측면을 벗어나면 방향을 수평으로 뒤집습니다.

F›⊗↔ⅉθ≦⁻⁴ζ

이것이 위 또는 아래로 떨어지면 방향을 수직으로 뒤집습니다.

≧﹪⁸ζ

방향 모듈로 8을 줄입니다 (피벗 명령은 0에서 7 사이의 값만 허용합니다).

↷⁴¶↶⁴

실험적 움직임을 취소하십시오.

↶δ↷ζ*¶

올바른 방향을 향한 다음 흔적을 인쇄하고 이동하십시오.

↶ζPo

기본 방향으로 돌아가서 현재 위치에서 개체를 인쇄하십시오.


2

자바 스크립트, 206 바이트

방향을 비트 마스크를 사용하여 인코딩하는 (n, x, y, [[dir, len], [dir, len], ...])로 입력을받습니다.

S : 1  
N : 2   
E : 4  
W : 8  
SE: 5 (1|4)  
SW: 9 (1|8)
NE: 6 (2|4)
NW:10 (2|8)

문자열을 출력

- 1 for top and bottom boundary
- 4 for left and right boundary 
- 5 for corners 
- 0 for trace
- 8 for the final position.

경계의 다른 값은 다음 방향을 평가하는 데 사용됩니다

(n,x,y,d)=>(Q=[e=`
5`+'1'[R='repeat'](n)+5,o=n+3,-o,c=[...e+(`
4`+' '[R](n)+4)[R](n)+e],1,1+o,1-o,,-1,o-1,~o],p=1-o*(~n/2+y)-~n/2+x,c[d.map(([q,s])=>{for(a=q;s--;p+=Q[a^=c[p+Q[a]]*3])c[p]=0}),p]=8,c.join``)

덜 골프

F=(n,x,y,d) => (
  o = n+3, // vertical offset, accounting for boundaries and newline
  // Q = offsets for different directions, bitmask indexed 
  Q = [,  // 0000 no direction
     o,   // 0001 S
     -o,  // 0010 N
     ,    // 0011 NS - invalid
     1 ,  // 0100 E
     1+o, // 0101 SE
     1-o, // 0110 NE
     ,    // 0111 NSE - invalid
     -1,  // 1000 W
     o-1, // 1001 SW
    -o-1],// 1010 NW

  e = `\n5`+'1'.repeat(n)+5, // top and bottom boundary
  c = [...e + (`\n4` + ' '.repeat(n) + 4).repeat(n) + e], // canvas
  p = 1 - o*(~n/2+y) - ~n/2 + x, // start position
  d.map( ([q,s]) => { // repeat for each element in 'd'
    a = q; // starting offset pointer - will change when bounce
    while( s-- )
    {
      c[p] = 0; // trace
      b = c[p + Q[a]] // boundary value or 0 (space count 0)
      a ^= b * 3 // xor with 0 if no bounce, else 3 or 12 or 15
      p += Q[q]  // advance position
    }
  })
  c[p] = 8, // set end position
  c.join``
)

테스트

var F=
(n,x,y,d)=>(Q=[e=`
5`+'1'[R='repeat'](n)+5,o=n+3,-o,c=[...e+(`
4`+' '[R](n)+4)[R](n)+e],1,1+o,1-o,,-1,o-1,~o],p=1-o*(~n/2+y)-~n/2+x,c[d.map(([q,s])=>{for(a=q;s--;p+=Q[a^=c[p+Q[a]]*3])c[p]=0}),p]=8,c.join``)

var out=x=>O.textContent+=x

var test=(n,x,y,d)=>{
  var dd = d.map(([d,s])=>[,'S','N',,'E','SE','NE',,'W','SW','NW'][d]+' '+s)
  out([n,x,y]+' ['+dd+']')
  out(F(n,x,y,d))
  out('\n\n')
}

test(5,0,0,[[10,2],[1,2],[4,1]])
test(9,3,-1,[[2,2],[9,8],[5,3],[6,8]])
test(11,3,-5,[[10,8],[4,5],[5,2],[9,5],[2,6],[6,10]])
<pre id=O></pre>


2

C (GCC) , 352 (323) 바이트

ceilingcat 덕분에 29 바이트가 줄었습니다.

#define G(x,a)x+=a=x<2|x>m-3?-a:a
#define A(p)atoi(v[p])
m,r,c,x,y,s,a,b;main(q,v)int**v;{m=A(1)+2;int f[r=m*m];for(x=A(2)+m/2;r--;f[r]=32);for(y=A(s=3)+m/2;++s<q;)for(a=cos(A(s)*.8)*2,b=sin(A(s)*.8)*2,c=A(++s);c--;G(y,b),f[y*m+x]=42)G(x,a);for(f[y*m+x]=64;++r<m;puts(""))for(c=0;c<m;c++)putchar(c%~-m&&r%~-m?f[r*m+c]:35);}

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

프로그램은 입력을 명령 행 인수로 사용합니다 (예 a.out 10 1 1 3 5 0 4 7 2:).

  • 첫 번째 인수는 필드 크기입니다.
  • (x,y)
  • (d,t)dEt

설명

// Update the coordinate AND simultaneously modify the direction (if needed)
#define G (x, a) x += a = x < 2 || x >= m - 2 ? -a : a

// Get the numeric value of an argument
#define A (p) atoi (v[p])

// variables
m, // width and height of the array with field data
r, c, // helpers
x, y, // current coordinates of the actor
s, // helper
a, b; // current direction of the movement

main (q, v) char **v;
{
    // array size is field size + 2 (for borders)
    m = A (1) + 2;

    // allocate the array
    int f[r = m * m];

    // fill the array with spaces,
    for
    (
        // but first get x of the actor
        x = A (2) + m / 2;

        r--;

        f[r] = 32
    );

    // trace: iterate over remaining commandline argument pairs
    for
    (
        // but first get y of the actor
        y = A (s = 3) + m / 2;

        ++s < q; // loop until no args left
    )
        // for each such pair
        for
        (
            a = cos (A (s) * .8) * 2,  // get the x-increment
            b = sin (A (s) * .8) * 2, // get the y-increment
            c = A (++s);  // then get the number of steps

            c--;

            // after each step:
            G (y, b), // update y and maybe the y-direction
            f[y * m + x] = 42 // draw the trail
        )
            G (x, a); // update x and maybe the x-direction

   // output
   for
   (
       f[x * m + y] = 64; // put a @ to the current position of the actor
       ++r < m; // r == -1 at the beginning of the loop so preincrement

       puts("") // terminate each row with newline
   )
       // iterate over columns in the row
       for (c = 0; c < m; c++)
           putchar
           (
               c % ~ -m && r % ~ -m ? // if it is not a border cell,
               f[r * m + c] // output the character from the array
               : 35 // otherwise output the #
           );
}

1
추적 된 객체의 추적은 평면의 1 칸만 차지하고 객체다른 한 추적 된 객체의 추적도 원하는 문자가 될 수 있기 때문에 코드에 객체 출력이 누락되었다고 생각합니다 . 그 외에는 나에게 좋아 보인다.
J. Sallé

죄송합니다. J.Sallé를 알아 주셔서 감사합니다. 다행히도 수정으로 인해 프로그램이 더 길어지지 않았습니다.
Max Yekhlakov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.