Отслеживание объекта в 2d пространстве


11

Описание

Задача этой задачи - разработать программу или функцию, которая отслеживает данный объект в пространстве n×n .

I / O

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

nбудет размер стороны самолета. (таким образом, для ваша плоскость будет ). Вы можете предположить, что всегда будет нечетным целым числом.n=55×5n

sбудет начальной позицией объекта, заданной в виде пары координат.(x,y)

Dбудет вектором упорядоченных пар. Dбудет следовать формату , где всегда будет одним из , для кардинального и основного межкардинальных направлений, а будет целое число для числа «тиков».D=[(d0,t0),(d1,t1),...,(dn,tn)]dk'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=9s=(3,1)D=[(N,2),(SW,8),(SE,3),(NE,8)]

Обратите внимание, что при :t=10

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

Объект был отражен дважды : один раз при достижении дна плоскости при движении к , где он отражается к ; затем еще раз при достижении левой стороны плоскости, где отражает .SWNWNWNE

Окончательный результат получается при :t=21

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

Тестовые случаи:

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

Выход:

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


Ввод: ,n=9s=(3,1) ,D=[(N,2),(SW,8),(SE,3),(NE,8)]

Выход:

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


Ввод: , ,n=3s=(1,1)D=[(N,5),(W,5)]

Выход:

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


Ввод: , ,n=11s=(3,5)D=[(NW,8),(E,5),(SE,3),(SW,5),(N,6),(NE,10)]

Выход:

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

Забыл упомянуть, что этот вызов был изолирован .
Ж. Салле

Можем ли мы взять 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'вместо этого 0-индексированное (или 1-индексированное) целое число? Так [('NW',2),('S',2),('E',1)]делается [[7,2],[4,2],[2,1]]например.
Кевин Круйссен,

@KevinCruijssen конечно, нет проблем. Обязательно укажите это в ответе.
Ж. Салле

1
@Arnauld да, вы можете использовать один символ трассировки. Я использовал более одного, чтобы было проще визуализировать тестовые примеры, но это не обязательно. Просто убедитесь, что символ трассировки отличается от характера объекта трассировки.
Ж. Салле

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)

Попробуйте онлайн!

Как?

Инициализация и рисование в «canvas» (то есть в матрице символов) немного утомительно и долго в 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 в диапазоне Юникода [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):

  • первый аргумент - это размер поля,
  • (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é. К счастью, коррекция не сделала программу длиннее.
Макс Ехлаков
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.