Śledź obiekt w przestrzeni 2d

11

Opis

Zadaniem tego wyzwania jest opracowanie programu lub funkcji, która śledzi dany obiekt w przestrzeni n×n .

I / O

Twój program otrzyma 3 dane wejściowe, które można wykorzystać w dowolny rozsądny sposób :

nbędzie wielkości boku samolotu. (Zatem, dla n=5 , samolot będzie 5×5 ). Możesz założyć, nże zawsze będzie nieparzysta liczba całkowita.

sbędzie początkową pozycją obiektu, podaną jako para współrzędnych (x,y) .

Dbędzie wektorem uporządkowanych par. Dbędzie miała postać D=[(d0,t0),(d1,t1),...,(dn,tn)] , gdzie dk będzie zawsze jednym z 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', dla kardynalnego i pierwotnego kierunku międzysercowego, a tk będzie liczbą całkowitą dla liczby „tyknięć”.

Biorąc pod uwagę te dane wejściowe, program musi wyprowadzić śledzenie obiektu w płaszczyźnie.

Zasady

Dane wyjściowe muszą zawierać granice płaszczyzny. Na przykład:

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

byłby przykładem pustej płaszczyzny 5×5 . Liczby powyżej i z boku mają jedynie charakter poglądowy i nie muszą być drukowane.

Możesz użyć dowolnego znaku (znaków) dla granic, o ile nie jest to biały znak (lub jest renderowany jako biały znak). Wybrane postacie muszą wyznaczyć pełną płaszczyznę, co oznacza, że ​​między nimi nie może być przerw.

Niektóre akceptowalne samoloty obejmują:

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

Niedopuszczalne samoloty obejmują:

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

Obiektem, który ma być śledzony, może być dowolny wybrany przez ciebie znak, o ile zajmuje on tylko 1 pole na płaszczyźnie i różni się od znaków granicznych.

Śladem śledzonego obiektu mogą być również dowolne wybrane znaki, o ile zajmują one tylko 1 miejsce na płaszczyźnie i różnią się od obiektu.

Dla każdego elementu (dk,tk) wD obiekt musi przesunąćt spacje w kierunkud i pozostawić ślad za sobą.

Jeśli obiekt uderzy w granicę, zostanie odbity. Jeśli obiekt nadal ma jakieś ruchy, będzie poruszał się w kierunku, w którym został odbity.

Dla odniesienia, te kierunki odzwierciedlają się nawzajem:

NS → po spełnieniu górnej lub dolnej granicy;

EW → po spełnieniu granicy bocznej;

Ostateczne dane wyjściowe będą zawierać najnowsze możliwe ślady, to znaczy, jeśli obiekt pozostawiłby ślad w miejscu, w którym już jest ślad, nowszy znak śledzenia zastąpi starszy.

Jak zwykle standardowe luki są domyślnie zabronione .

Punktacja:

To wyzwanie dla .

Przykłady:

Dane wejściowe: n=5 , s=(0,0) , D=[(NW,2),(S,2),(E,1)]

Opracowanie:

t=0

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

t=2

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

t=4

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

t=5

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

(Zera są tylko w celach informacyjnych i nie muszą znajdować się w końcowym wyniku).


Dane wejściowe: n=9s=(3,1)D=[(N,2),(SW,8),(SE,3),(NE,8)]

t=10

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

SWNWNWNE

t=21

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

Przypadki testowe:

Dane wejściowe: n=5 , s=(0,0)D=[(NW,2),(S,2),(E,1)]

Wynik:

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


Dane wejściowe: n=9 , s=(3,1) , D=[(N,2),(SW,8),(SE,3),(NE,8)]

Wynik:

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


Dane wejściowe: n=3 , s=(1,1) , D=[(N,5),(W,5)]

Wynik:

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


Dane wejściowe: n=11 , s=(3,5) , D=[(NW,8),(E,5),(SE,3),(SW,5),(N,6),(NE,10)]

Wynik:

       0
 ┌───────────┐
 │ ∧ │
 │ / \ │
 │┌ - / - \ \ │
 │ \ | / \ \ │
 │ \ | \ \ │
0│ | / ⟩│
 │ | \ / / │
 │ | / ○ │
 │ | / \ │
 │ ∨ \ │
 │ \ │
 └───────────┘
J. Sallé
źródło
Zapomniałem wspomnieć, że to wyzwanie było piaskownicą .
J. Sallé,
Czy 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'zamiast tego możemy przyjmować jako liczbę całkowitą 0-indeksowaną (lub 1-indeksowaną)? Tak [('NW',2),('S',2),('E',1)]staje się [[7,2],[4,2],[2,1]]na przykład.
Kevin Cruijssen
@KevinCruijssen na pewno, nie ma problemu. Pamiętaj tylko, aby zaznaczyć to w odpowiedzi.
J. Sallé,
1
@Arnauld tak, możesz użyć jednego znaku śledzenia. Użyłem więcej niż jednego, aby łatwiej było wyobrazić sobie przypadki testowe, ale nie jest to wymagane. Upewnij się tylko, że znak śledzenia różni się od znaku śledzonego obiektu.
J. Sallé,
1
@Arnauld " Obiekt, który ma być śledzony, może być dowolną postacią, którą wybierzesz, o ile zajmuje on tylko 1 miejsce na płaszczyźnie i różni się od znaków granicznych. Ślad śledzonego obiektu może być dowolną postacią, którą wybierzesz, tak długo ponieważ zajmują tylko 1 miejsce w samolocie i różnią się od obiektu.
Kevin Cruijssen

Odpowiedzi:

9

JavaScript (ES6), 228 bajtów

(n,x,y,[[dir,len],[dir,len],...])07 dla południowo-zachodniej.

Generuje ciąg znaków z 0dla granicy, 1dla śladu i 3dla końcowej pozycji.

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

Wypróbuj online!

W jaki sposób?

Inicjowanie i rysowanie w „kanwie” (tj. Matrycy znaków) jest w JavaScript nieco uciążliwe i długotrwałe.

Ten kod stosuje inną strategię: zamiast przechowywać dane wyjściowe w tablicy 2D, buduje ciąg znaków po znaku, od lewej do prawej i od góry do dołu. Przy każdej iteracji:

  • Wyprowadzamy a, 0jeśli przekroczymy granicę.
  • W przeciwnym razie symulujemy pełną ścieżkę i sprawdzamy, czy przekracza ona naszą obecną pozycję. Wyprowadzamy albo, 1albo 3jeśli, albo spację w inny sposób.
  • Dołączamy linię, jeśli osiągnęliśmy właściwą granicę.

Podsumowując, może nie jest to najkrótsze podejście, ale pomyślałem, że warto spróbować.

Arnauld
źródło
9

Java 10, 350 343 340 336 bajtów

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

D2D jest liczbą całkowitą z matrycą, w którym kierunki są 0 indeksowanych liczb całkowitych N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7. Początkowe x,ywspółrzędne będą dwoma oddzielnymi parametrami si S. Wynikiem jest macierz znaków.
Używa #jako granicy, *ścieżki i Odla pozycji końcowej (ale wszystkie trzy mogą być dowolnymi znakami ASCII w zakresie Unicode [33,99]dla tej samej liczby bajtów, jeśli chcesz).

Wypróbuj online.

-4 bajty dzięki @ceilingcat .
Można zdecydowanie zagrać w golfa, upraszczając ruchy i kierunek, w którym podróżujemy.

Wyjaśnienie:

(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:7to gra w golfa poniżej, przy użyciu 4-ii 8-idla większości zmian kierunku:

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
Kevin Cruijssen
źródło
3

Węgiel drzewny , 74 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Pobiera dane w formacie n, x, y, d, gdzie d jest tablicą tablic par [odległość, kierunek], gdzie kierunek jest kodowaniem numerycznym 0 = południe zgodnie z ruchem wskazówek zegara do 7 = południowy wschód. Wyjaśnienie:

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

Wprowadź ni narysuj pole, którego wnętrze ma rozmiar wyśrodkowany na początku.

JN±N

Wejdź i przeskocz do xi y(ale zaneguj, yponieważ oś y Węgla rośnie w dół).

FA«

Pętla nad wpisami w d.

≔⊟ιζ

Wyodrębnij początkowy kierunek.

F⊟ι«

Powtórz dla żądanej odległości.

≔ζδ

Zapisz kierunek.

↷δ¶

Wykonaj eksperymentalny ruch w tym kierunku.

F›⊗↔ⅈθ≦±ζ

Jeśli to zejdzie na boki, odwróć kierunek w poziomie.

F›⊗↔ⅉθ≦⁻⁴ζ

Jeśli to zejdzie z góry lub z dołu, odwróć kierunek w pionie.

≧﹪⁸ζ

Zmniejsz kierunek modulo 8 (polecenia Pivot akceptują tylko wartości od 0 do 7).

↷⁴¶↶⁴

Cofnij eksperymentalny ruch.

↶δ↷ζ*¶

Ustaw właściwy kierunek, a następnie wydrukuj ślad i przesuń.

↶ζPo

Odwróć się do domyślnego kierunku i wydrukuj obiekt w bieżącej pozycji.

Neil
źródło
2

JavaScript, 206 bajtów

Pobiera dane wejściowe jako (n, x, y, [[katalog, len], [katalog, len], ...]), gdzie kierunki są kodowane za pomocą masek bitowych:

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

Zwraca ciąg z

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

Różne wartości granic służą do oceny następnego kierunku

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

Mniej golfa

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

TEST

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>

edc65
źródło
2

C (gcc) , 352 323 bajty

Gra w golfa w dół o 29 bajtów dzięki pułapowi cat.

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

Wypróbuj online!

Program przyjmuje dane wejściowe jako argumenty wiersza poleceń (jak a.out 10 1 1 3 5 0 4 7 2):

  • pierwszy argument to rozmiar pola,
  • (x,y) aktora,
  • (d,t)dEt

Wyjaśnienie

// 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 #
           );
}
Max Yekhlakov
źródło
1
Wydaje mi się, że w kodzie brakuje danych wyjściowych obiektu w pozycji końcowej, ponieważ Śladem śledzonego obiektu mogą być również dowolne wybrane znaki, o ile zajmują one tylko 1 miejsce na płaszczyźnie i różnią się od obiektu . Poza tym wygląda mi dobrze.
J. Sallé
Ups, całkowicie mi tego brakowało, dzięki za zwrócenie uwagi na J.Sallé. Na szczęście korekta nie wydłużyła programu.
Max Yekhlakov