Відстежуйте об'єкт у 2d просторі


11

Опис

Завдання цього завдання - розробити програму або функцію, яка відслідковує заданий об’єкт у н×н просторі.

I / O

Вашій програмі буде надано 3 входи, які можуть бути зроблені будь-яким розумним способом :

nбуде розміром сторони площини. (значить, при н=5 ваша площина буде дорівнює 5×5 ). Ви можете припустити, що nце завжди непарне ціле число.

sбуде вихідним положенням об'єкта, заданим у вигляді пари(x,y) координат .

Dбуде вектором упорядкованих пар. Dдотримуватиметься формату , де завжди буде одним із , для кардинальних та первинних міжкардіальних напрямків, і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) у D об'єкт повинен переміщувати t пробілів у напрямку до d , а за собою залишати слід.

Якщо об'єкт потрапить на межу, він буде відображений. Якщо в об'єкта все ще залишилися рухи, він продовжуватиме рухатися у напрямку, в якому він був відбитий.

Для довідки ці вказівки відображають один одного:

NS → при дотриманні верхньої або нижньої межі;

EW → коли досягається бічна межа;

Кінцевий висновок буде містити новітні можливі сліди, тобто якщо об’єкт залишить слід у просторі, де вже є слід, новіший символ сліду замінить старіший.

Як завжди, стандартні лазівки за замовчуванням заборонені .

Оцінка:

Це проблема з .

Приклади:

Введення: n=5 , s=(0,0) , D=[(NW,2),(S,2),(E,1)]

Розробка:

t=0

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

т=2

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

т=4

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

т=5 , який буде результатом.

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

(0 є лише для ознайомлення, і їм не потрібно бути в кінцевому результаті.)


Вхідні дані: н=9 , с=(3,-1) , D=[('N',2),('SW',8),('SЕ',3),('NЕ',8)]

Зауважте, що при т=10 :

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

Об'єкт відбився двічі : один раз, коли досягає дна площини, рухаючись у напрямку до SW , де він відбивається на NW ; потім ще раз при досягненні лівого боку від площини, де NW відображає на NЕ .

Кінцевий вихід виходить при т=21 :

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

Тестові приклади:

Введення: n = 5 , s = ( 0 , 0 ) , D = [ ( ′ N W ′ , 2 ) , ( ′ S ′ , 2 ) , ( ′ E ′ , 1 ) н=5с=(0,0)D=[('NW',2),('S',2),('Е',1)]

Вихід:

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


Вхідні дані: н=9 , с=(3,-1) , D=[('N',2),('SW',8),('SЕ',3),('NЕ',8)]

Вихід:

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


Вхід: н=3 , с=(1,1) , D=[('N',5),('W',5)]

Вихід:

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


Введення: н=11 , с=(3,-5) , D=[('NW',8),('Е',5),('SЕ',3),('SW',5),('N',6),('NЕ',10)]

Вихід:

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

Забув згадати, що цей виклик був пісочницею .
J. Sallé

Чи можемо ми взяти 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'замість цього ціле число 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 простір на площині і відрізняється від граничних символів. Слід відстежуваного об'єкта також може бути будь-якими символами, які ви обрали, доки оскільки вони займають лише 1 простір у площині і відрізняються від об'єкта ".
Кевін Круїйсен

Відповіді:


9

JavaScript (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.

Цей код використовує іншу стратегію: замість того, щоб зберігати вихід у двовимірному масиві, він будує рядовий символ за символом, зліва направо і зверху вниз. На кожній ітерації:

  • Ми виводимо а, 0якщо ми перетинаємо межу.
  • В іншому випадку ми моделюємо повний шлях і бачимо, чи він перетинає наше поточне положення. Ми виводимо 1або, 3якщо це робиться, або пробіл інакше.
  • Ми додаємо прямий канал, якщо ми дійшли до правої межі.

Загалом, це може бути не найкоротший підхід, але я вважав, що варто спробувати.


9

Java 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є цілим числом 2D-масив , в якому напрям 0-індексовані цілі числа: N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7. Початковими x,yкоординатами будуть два окремих параметра sі S. Вихід - матриця символів.
Він використовується #як межа, *як слід, так і Oдля закінчуючої позиції (але всі три можуть бути будь-якими символами ASCII в діапазоні Unicode [33,99]для одного і того ж рахунку байтів, якщо ви хочете).

Спробуйте в Інтернеті.

-4 байти завдяки @ceilingcat .
Однозначно можна пограти ще трохи, спростивши рухи і в якому напрямку ми ще трохи подорожуємо.

Пояснення:

(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наведена нижче версія для гольфу, використовуючи 4-iта 8-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 (команди Pivot приймають значення лише від 0 до 7).

↷⁴¶↶⁴

Скасуйте експериментальний хід.

↶δ↷ζ*¶

Зверніться до правильного напрямку, а потім надрукуйте слід і рухайтесь.

↶ζPo

Поверніться назад до напрямку за замовчуванням та надрукуйте об'єкт у поточному положенні.


2

JavaScript, 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 байт

Поле на 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):

  • перший аргумент - розмір поля,
  • наступні два - початкові координати (х,у) актора,
  • всі пари аргументів, починаючи з четвертого, є (г,т) пари де г- напрямок (представлений у вигляді числа 0..7, починаючи з 0 = Eі повертаючи за годинниковою стрілкою) іт - кількість кроків.

Пояснення

// 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é. На щастя, корекція не зробила програму довшою.
Макс Єхлаков
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.