追踪2D空间中的物体


11

描述

这项挑战的任务是设计一个程序或函数来跟踪n×n空间中的给定对象。

输入输出

您的程序将获得3个输入,可以以任何明智的方式获取

n将是飞机侧面的大小。(因此,对于n=5,您的平面将为5×5)。您可能会假设n它将始终是一个奇数整数。

s将是对象的起始位置,以一对(x,y)坐标给出。

D将是有序对的向量。D将遵循格式D=[(d0,t0),(d1,t1),...,(dn,tn)],其中dk将始终是一个'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW',对于基数和初级intercardinal方向,和tk将是的“滴答”的数量的整数。

有了这些输入,您的程序必须输出对平面中对象的跟踪。

规则

输出必须包含平面的边界。例如:

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

将是一个空的5×5平面的示例。上方和侧面的数字仅供参考,不需要打印。

您可以使用任何字符作为边界,只要它不是空格(或呈现为空格)即可。您选择的字符必须描绘整个平面,这意味着它们之间不能有间隙。

一些可接受的飞机包括:

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

不可接受的飞机包括:

      .... .... ++++。。
            。。+ +。。
            。+ +。。
    ; ....; ....; + +; 。。

要跟踪的对象可以是您选择的任何字符,只要它在平面上仅占用1个空间并且与边界字符不同即可。

跟踪对象的轨迹也可以是您选择的任何字符,只要它们在平面上仅占据1个空间并且与对象不同即可。

对于每个元素(dk,tk)D中,对象必须移动t朝向空间d,并留下痕迹。

如果物体碰到边界,它将被反映出来。如果对象还剩下任何移动,它将继续沿被反射的方向移动。

作为参考,这些指示相互反映:

ñ小号 →当顶部或底部边界被满足;

Ëw ^ →当横向边界被满足;

最终输出将包含最新的跟踪信息,也就是说,如果对象将跟踪信息留在已经存在跟踪信息的空间中,则更新的跟踪字符将覆盖较旧的跟踪字符。

像往常一样,默认情况下禁止标准漏洞

得分:

这是一个挑战。

例子:

输入:ñ=5s=00d=[ñw ^2小号2Ë1个]

解决:

Ť=0

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

Ť=2

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

Ť=4

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

Ť=5,这将是输出。

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

(0仅作为参考,它们不需要出现在最终输出中。)


输入:ñ=9s=3-1个d=[ñ2小号w ^8小号Ë3ñË8]

注意,当Ť=10

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

对象已经被反射两次:一次是在到达时底部,当去朝向平面的小号w ^,在那里它反映到ñw ^ ; 然后再次到达时,左侧面,其中ñw ^反映ñË

最终输出为Ť=21

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

测试用例:

输入:Ñ = 5,š = (0 ,0 ),d = [ (' Ñ w ^ ',2 ),(' 小号',2 ),(' é ',1 )ñ=5s=00d=[ñw ^2小号2Ë1个]

输出:

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


输入:ñ=9s=3-1个d=[ñ2小号w ^8小号Ë3ñË8]

输出:

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


输入:ñ=3s=1个1个d=[ñ5w ^5]

输出:

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


输入:ñ=11s=3-5d=[ñw ^8Ë5小号Ë3小号w ^5ñ6ñË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当然,没问题。只要确保在答案中指出即可。
J.Sallé18年

1
@Arnauld是的,允许您使用单个跟踪字符。我使用了不止一个,因此可视化测试用例会更容易,但这不是必需的。只要确保跟踪字符与被跟踪对象的字符不同即可。
J.Sallé18年

1
@Arnauld“ 要跟踪的对象可以是您选择的任何字符,只要它在平面上仅占据1个空间且与边界字符不同即可。被跟踪对象的轨迹也可以是您选择的任何字符,只要因为它们在飞机上仅占据1个空间,并且与物体不同。
凯文·克鲁伊森

Answers:


9

JavaScript(ES6),228个字节

将输入作为(n,x,y,[[dir,len],[dir,len],...])从逆时针编码方向的位置0 南至 7 西南。

输出带有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 。
  • 否则,我们将模拟完整路径,并查看其是否与当前位置交叉。我们将输出一个13是否输出,否则输出一个空格。
  • 如果到达正确的边界,我们将添加换行符。

总而言之,这可能不是最短的方法,但我认为值得尝试。


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是2D整数数组,其中方向是0索引整数:N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7。起始x,y坐标将是两个单独的参数sS。输出是一个字符矩阵。
#用作边界,*路径和O结束位置(但如果需要,可以将所有三个都设为Unicode范围内[33,99]相同字节数的任何ASCII字符)。

在线尝试。

-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

输入并跳转到xy(但求反,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)352323字节

多亏了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ÿ 演员的
  • 从第四点开始的所有参数对都是 dŤ 在哪里 d是方向(以数字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个空间并且与object有所不同除此之外,对我来说看起来不错。
J.Sallé18年

糟糕,感谢您注意到J.Sallé,我完全想念这一点。幸运的是,更正并未使程序更长。
Max Yekhlakov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.