Theo dõi một đối tượng trong không gian 2d


11

Sự miêu tả

Nhiệm vụ của thách thức này là để đưa ra một chương trình hay chức năng theo dõi một đối tượng nhất định trong một n×n không gian.

Tôi / O

Chương trình của bạn sẽ được cung cấp 3 đầu vào, có thể được thực hiện theo bất kỳ cách hợp lý nào :

nsẽ là kích thước của mặt phẳng. (vì vậy, với n=5 , mặt phẳng của bạn sẽ là 5×5 ). Bạn có thể giả sử nsẽ luôn là một số nguyên lẻ.

ssẽ là vị trí bắt đầu của đối tượng, được đưa ra dưới dạng một cặp tọa độ (x,y) .

Dsẽ là một vectơ của các cặp theo thứ tự. Dsẽ theo định dạng D=[(d0,t0),(d1,t1),...,(dn,tn)] , trong đó dk sẽ luôn là một trong số đó 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', đối với các hướng liên thông chính và chính, và tk sẽ là một số nguyên cho số lượng 'tick'.

Với các đầu vào này, chương trình của bạn phải xuất ra một bản theo dõi của đối tượng trong mặt phẳng.

Quy tắc

Đầu ra phải chứa ranh giới của mặt phẳng. Ví dụ:

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

sẽ là một ví dụ về một sản phẩm nào 5×5mặt phẳng 5 × 5. Các số ở trên và bên cạnh chỉ mang tính tham khảo và không cần phải in.

Bạn có thể sử dụng bất kỳ ký tự nào cho các ranh giới, miễn là nó không phải là khoảng trắng (hoặc hiển thị dưới dạng khoảng trắng). Các nhân vật bạn chọn phải phân định toàn bộ mặt phẳng, nghĩa là không thể có khoảng cách giữa chúng.

Một số mặt phẳng được chấp nhận bao gồm:

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

Các mặt phẳng không được chấp nhận bao gồm:

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

Đối tượng cần theo dõi có thể là bất kỳ ký tự nào bạn chọn, miễn là nó chỉ chiếm 1 khoảng trống trên mặt phẳng và khác với các ký tự biên.

Dấu vết của đối tượng được theo dõi cũng có thể là bất kỳ ký tự nào bạn chọn, miễn là chúng chỉ chiếm 1 khoảng trống trên mặt phẳng và khác với đối tượng.

Đối với mỗi phần tử tại , đối tượng phải di chuyển không gian đối với , và để lại một dấu vết phía sau.(dk,tk)Dtd

Nếu đối tượng sẽ chạm vào một ranh giới, nó sẽ được phản ánh. Nếu đối tượng vẫn còn bất kỳ di chuyển nào, nó sẽ tiếp tục di chuyển theo hướng mà nó được phản ánh.

Để tham khảo, các hướng này phản ánh với nhau:

NS → khi ranh giới trên hoặc dưới được đáp ứng;

EW → khi một ranh giới bên được đáp ứng;

Đầu ra cuối cùng sẽ chứa các dấu vết mới nhất có thể, nghĩa là, nếu đối tượng sẽ để lại dấu vết trong một không gian có dấu vết, ký tự dấu vết mới hơn sẽ ghi đè lên dấu cũ.

Như thường lệ, các lỗ hổng tiêu chuẩn bị cấm theo mặc định .

Ghi điểm:

Đây là một thách thức .

Ví dụ:

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

Làm việc ra:

t=0

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

t=2

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

t=4

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

t=5

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

(Số 0 chỉ mang tính tham khảo và chúng không cần phải ở đầu ra cuối cùng.)


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

t=10

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

SWNWNWNE

t=21

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

Các trường hợp thử nghiệm:

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

Đầu ra:

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


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

Đầu ra:

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


Đầu vào: n=3 , s=(1,1) , D=[(N,5),(W,5)]

Đầu ra:

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


Đầu vào: n=11 , s=(3,5) , D=[(NW,8),(E,5),(SE,3),(SW,5),(N,6),(NE,10)]

Đầu ra:

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


'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'Thay vào đó, chúng ta có thể lấy số nguyên 0 (hoặc 1 chỉ mục) không? Vì vậy, [('NW',2),('S',2),('E',1)]trở thành [[7,2],[4,2],[2,1]]ví dụ.
Kevin Cruijssen

@KevinCruijssen chắc chắn, không vấn đề gì. Chỉ cần chắc chắn để chỉ ra rằng trong câu trả lời.
J. Sallé

1
@Arnauld có, bạn được phép sử dụng một ký tự theo dõi duy nhất. Tôi đã sử dụng nhiều hơn một để dễ hình dung các trường hợp thử nghiệm hơn, nhưng không bắt buộc. Chỉ cần chắc chắn rằng nhân vật dấu vết khác với nhân vật của đối tượng được truy tìm.
J. Sallé

1
@Arnauld " Đối tượng cần theo dõi có thể là bất kỳ nhân vật nào bạn chọn, miễn là nó chỉ chiếm 1 khoảng trống trên mặt phẳng và khác với các ký tự ranh giới. Dấu vết của đối tượng được theo dõi cũng có thể là bất kỳ ký tự nào bạn chọn, miễn là vì chúng chỉ chiếm 1 khoảng trống trên máy bay và khác với vật thể. "
Kevin Cruijssen

Câu trả lời:


9

JavaScript (ES6), 228 byte

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

Xuất ra một chuỗi với 0một ranh giới, 1cho một dấu vết và 3cho vị trí cuối cùng.

(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)

Hãy thử trực tuyến!

Làm sao?

Khởi tạo và vẽ thành một "khung vẽ" (nghĩa là ma trận các ký tự) hơi tẻ nhạt và dài dòng trong JavaScript.

Mã này đang sử dụng một chiến lược khác: thay vì lưu trữ đầu ra trong một mảng 2D, nó xây dựng một chuỗi ký tự theo ký tự, từ trái sang phải và từ trên xuống dưới. Ở mỗi lần lặp:

  • Chúng tôi đầu ra 0nếu chúng tôi vượt qua một ranh giới.
  • Mặt khác, chúng tôi mô phỏng đường dẫn đầy đủ và xem liệu nó có vượt qua vị trí hiện tại của chúng tôi không. Chúng tôi đầu ra 1hoặc 3nếu có, hoặc một không gian khác.
  • Chúng tôi nối thêm một nguồn cấp dữ liệu nếu chúng tôi đạt đến đúng ranh giới.

Nói chung, đây có thể không phải là cách tiếp cận ngắn nhất, nhưng tôi nghĩ nó đáng để thử.


9

Java 10, 350 343 340 336 byte

(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;}

Dlà một mảng số nguyên 2D trong đó các hướng là các số nguyên có chỉ số 0 : N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7. Các x,ytọa độ bắt đầu sẽ là hai tham số riêng biệt sS. Đầu ra là một ma trận ký tự.
Nó sử dụng #làm đường viền, *làm đường mòn và Ocho vị trí kết thúc (nhưng có thể cả ba là bất kỳ ký tự ASCII nào trong phạm vi unicode [33,99]cho cùng một số byte nếu bạn muốn).

Hãy thử trực tuyến.

-4 byte nhờ @ceilingcat .
Chắc chắn có thể chơi gôn nhiều hơn bằng cách đơn giản hóa các chuyển động và theo hướng chúng ta sẽ đi du lịch nhiều hơn.

Giải trình:

(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:7là phiên bản được đánh gôn dưới đây bằng cách sử dụng 4-i8-icho hầu hết các thay đổi hướng:

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

Than , 74 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Đưa đầu vào theo định dạng n, x, y, d trong đó d là một mảng gồm các cặp [khoảng cách, hướng] trong đó hướng là mã hóa số 0 = nam theo chiều kim đồng hồ đến 7 = đông nam. Giải trình:

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

Nhập nvà vẽ một hộp có kích thước bên trong là trung tâm của nguồn gốc.

JN±N

Nhập và nhảy tới xy(nhưng phủ nhận yvì trục y của Char than đang tăng xuống).

FA«

Lặp lại các mục trong d.

≔⊟ιζ

Trích xuất hướng ban đầu.

F⊟ι«

Lặp lại cho khoảng cách mong muốn.

≔ζδ

Lưu hướng.

↷δ¶

Thực hiện một động thái thử nghiệm theo hướng đó.

F›⊗↔ⅈθ≦±ζ

Nếu cái này đi ra hai bên thì lật hướng theo chiều ngang.

F›⊗↔ⅉθ≦⁻⁴ζ

Nếu cái này đi ra khỏi đỉnh hoặc đáy thì lật hướng theo chiều dọc.

≧﹪⁸ζ

Giảm modulo 8 hướng (các lệnh Pivot chỉ chấp nhận các giá trị từ 0 đến 7).

↷⁴¶↶⁴

Hoàn tác di chuyển thử nghiệm.

↶δ↷ζ*¶

Đối mặt với hướng chính xác, và sau đó in một dấu vết và di chuyển.

↶ζPo

Quay mặt về hướng mặc định và in đối tượng ở vị trí hiện tại.


2

JavaScript, 206 byte

Đưa đầu vào là (n, x, y, [[dir, len], [dir, len], ...]) trong đó các hướng được mã hóa bằng bitmasks:

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

Xuất ra một chuỗi với

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

Các giá trị khác nhau cho các ranh giới được sử dụng để đánh giá hướng tiếp theo

(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``)

Ít chơi gôn

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``
)

KIỂM TRA

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 byte

Golf giảm 29 byte nhờ trần mèo.

#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);}

Hãy thử trực tuyến!

Chương trình lấy đầu vào làm đối số dòng lệnh (như a.out 10 1 1 3 5 0 4 7 2):

  • đối số đầu tiên là kích thước trường,
  • (x,y)
  • (d,t)dEt

Giải trình

// 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
Tôi tin rằng mã của bạn thiếu đầu ra đối tượng ở vị trí cuối, vì Dấu vết của đối tượng được theo dõi cũng có thể là bất kỳ ký tự nào bạn chọn, miễn là chúng chỉ chiếm 1 khoảng trống trên mặt phẳng và khác với đối tượng . Ngoài ra, nó có vẻ tốt với tôi.
J. Sallé

Rất tiếc, tôi hoàn toàn bỏ lỡ điều đó, cảm ơn vì đã chú ý đến J.Sallé. May mắn thay, sự điều chỉnh đã không làm cho chương trình dài hơn.
Max Yekhlakov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.