Hành lang đáng sợ


8

Thử thách này được lấy cảm hứng từ một trò chơi cờ tôi đã chơi cách đây một thời gian.
Câu chuyện về thử thách này không nhất thiết phải được đọc, mục tiêu của phần thử thách sẽ giải thích mọi thứ cần thiết.

Câu chuyện

Mọi người bị nhốt trong một căn phòng lớn với một con quái vật ăn thịt người. Các bức tường của căn phòng bị mê hoặc, dịch chuyển các vật thể khắp phòng khi chạm vào. Quái vật nói diễu hành khắp phòng, săn lùng xác thịt. Con người đầu tiên trong tầm nhìn của nó sẽ bị tiêu thụ bởi hàm răng sắc nhọn của nó.

Mục tiêu của thử thách

Bạn được cung cấp bản đồ của căn phòng, bao gồm cả người và vị trí của quái vật.

%%%KLMNOPQRSTA%
%%J           B
%I       %    C
H             D
G   %%        E
F             F
E      %      G
D             H
C   %        I%
B           J%%
%ATSRQPONMLK%%%

Hãy chia nhỏ các thành phần của bản đồ.

  • Thư từ Ađến T: Nếu quái vật bước lên một trong số này, nó sẽ được dịch chuyển đến lần xuất hiện thứ hai của bức thư này và không thay đổi hướng của nó. Sẽ không bao giờ có 0 hoặc 2 chữ cái nào trên bảng.
  • %: Gạch ốp tường. Chỉ để định dạng và ngoại hình đẹp.
  • #: Vị trí bắt đầu của quái vật.
  • *: Địa điểm của mọi người.
  •  : Gạch rỗng, quái vật có thể di chuyển tự do trên chúng.

Một số điều cần lưu ý về bản đồ:

  • Kích thước bản đồ và vị trí đối tượng sẽ không đổi, do đó mã của bạn sẽ phải tự động thích ứng với điều đó.

Con quái vật sẽ luôn đi theo hướng mà nó hiện đang đối mặt (hướng về phía tây khi bắt đầu) trừ khi nó phát hiện ra một con người, trong trường hợp đó nó sẽ hướng về phía con người gần nhất .
Quái vật phát hiện ra một con người nếu không có gạch ốp tường hoặc dịch chuyển trong một đường thẳng hoặc ngang thẳng đứng giữa nó và con người.

Một điều cần lưu ý là nếu quái vật ở phía trước một bức tường vững chắc ( %) hoặc phải quyết định giữa hai người, nó sẽ luôn ưu tiên từ phải qua trái.

Nếu con quái vật không thể rẽ phải và tiến lên một bước vì một lý do nào đó, nó sẽ rẽ trái .

Vì vậy, cuối cùng, thứ tự mà con quái vật ưu tiên chỉ đường sẽ khiến chúng ta tiến lên, phải, trái, lùi.

Đầu vào

  • Bản đồ, bao gồm vị trí bắt đầu của quái vật và vị trí của mọi người như các nhân vật tương ứng của họ. Không nên có bất kỳ đầu vào nào khác ngoài chuỗi bản đồ hoặc mảng chuỗi hoặc ký tự.

Đầu vào có thể được nhận ở bất kỳ định dạng hợp lý; một chuỗi đơn hoặc một chuỗi các chuỗi cho bản đồ.

Đầu ra

Sự phối hợp của người đầu tiên bị quái vật ăn thịt.

Các tọa độ bắt đầu từ góc trên bên trái và được lập chỉ mục 0, vì vậy ô đầu tiên sẽ có tọa độ (0 | 0). Nếu bạn đang sử dụng lập chỉ mục 1, vui lòng chỉ định nó trong câu trả lời của bạn.

Quy tắc

  • Đây là , mã ngắn nhất tính bằng byte trong bất kỳ ngôn ngữ nào đều thắng.
  • Sơ hở tiêu chuẩn bị cấm.
  • Bạn có thể cho rằng quái vật sẽ luôn có thể tiếp cận một con người.

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

Đầu vào:

%%%KLMNOPQRSTA%
%%J           B
%I       %*   C
H   *         D
G   %%        E
F       #     F
E      %      G
D      *      H
C   %        I%
B           J%%
%ATSRQPONMLK%%%

Đầu ra : (10,2), vì quái vật không thể nhìn thấy hai người khác khi nó chạy qua họ, nó bị dịch chuyển sang Fbức tường khác , nơi nó sẽ nhìn thấy người cuối cùng.

Đầu vào:

%%%KLMNOPQRSTA%
%%J           B
%I      *     C
H     %%%   * D
G      #%     E
F     %%%   % F
E             G
D       %     H
C       *    I%
B       *   J%%
%ATSRQPONMLK%%%

Đầu ra: (12,3)

Đầu vào:

%%%KLMNOPQRSTA%
%%J           B
%I     %%%    C
H     *%#%    D
G             E
F             F
E       %     G
D             H
C            I%
B           J%%
%ATSRQPONMLK%%%

Đầu ra: (6, 3)

Đầu vào:

%%%%%%%%%%%%%%%
%#%       %%% %
%A%ABCD   %*% %
%*F     G %%% %
% %BC% FD     %
% %   %    %%%%
% %  %       %%
%   % %%   G  %
%             %
%*%    %    % %
%%%%%%%%%%%%%%%

Đầu ra: (1,9)


Chúc may mắn!


Bạn nên nói rõ, sớm và rõ trong phần mô tả, rằng con người không di chuyển. Lúc đầu tôi không nhận ra rằng họ đứng yên. Nếu tôi là một con người trong tình huống đó, tôi chắc chắn sẽ di chuyển!
DLosc

Câu trả lời:


6

Python 2 , 565 .. 422 445 1 .. 444 463 2 .. 468 467 463 byte

u,U='*%'
G=lambda s:u==s.strip('# ')[0]and len(N)-s.find(u)
b=input()
D=3;j=''.join;N,w,P,t,B=j(b),len(b[0]),[0,1,0,-1],{},map(j,zip(*b))
for c in N:
 l,r=N.find(c),N.rfind(c)
 if u<c:t[l]=r;t[r]=l
 if'#'==c:x,y=l%w,l/w
while u!=b[y][x]:
 O=[B[x][y-1::-1],b[y][x+1:],B[x][y+1:],b[y][x-1::-1]];L,R=O[D-1],O[~D]
 if u<b[y][x]:X=t[x+w*y];x,y=X%w,X/w
 elif(G(O[D])<1)*(G(R)+G(L)+(U==O[D][0])):D-=0<G(L)>G(R)or(U==R[0])*-~(U==L[0])or-1;D%=4
 x+=P[D];y+=P[~D]
print x,y

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

Đã lưu rất nhiều byte nhờ Halvard , IanJonathan

1: Có thời gian dài hơn, để khắc phục trường hợp quay hai lần và tìm vị trí của quái vật.
2: Thậm chí lâu hơn .. Quái vật không nên đổi hướng khi dịch chuyển tức thời.


Hơi bị đánh gôn tới 482 byte . Liên kết rút ngắn do TIO kéo dài
Halvard Hummel

@Halvard Một sân golf nhỏ, chỉ 1 byte: 481

1
l.replace('#',' ')-> l.replace(*"# ").
Jonathan Frech

Đã sửa, nhưng giờ nó có cùng độ dài với của bạn, 434 byte

2
@KevinCruijssen Tôi biết Ian nói câu trả lời của tôi là hợp lệ, nhưng dù sao tôi cũng sẽ thay đổi nó.
TFeld

5

Perl 6 ,343 334 333 328 322 308 byte

{my \m=%((^@^a X ^@a[0]).map:{.[0]i+.[1]=>@a[.[0]][.[1]]});my \a=m<>:k.classify
({m{$_}});my$m=a<#>[0];my$d=-1;{$d=($d,i*$d,-i*$d,-$d).min({$^q;first ?*,map
{(((my \u=m{$m+$_*$q})~~"%")*(1+!($_-1))+(u~~"A".."Z"))*m+(u~~"*")*$_},^m});
$m+=$d;$m=$d+(a{m{$m}}∖~$m).pick while m{$m}~~"A".."Z"}...{m{$m}~~"*"};$m}

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

(Không có dòng mới nào trong mã thực tế. Tôi đã chèn chúng chỉ để bọc các dòng để dễ đọc hơn.)

Điều này là không thể đối phó với các bản đồ nơi có thể nhìn thấy bên ngoài giới hạn bản đồ. (I. e. Bản đồ có khoảng trống ở viền.) Nếu điều này quan trọng, +5 byte. Nhưng, vì các dịch chuyển tức thời chặn LoS, nên không nên.

Giải thích : Đây là một chức năng lấy bản đồ làm danh sách các danh sách các ký tự. Hãy chia nó thành các tuyên bố:

my \m=%((^@^a X ^@a[0]).map:{.[0]i+.[1]=>@a[.[0]][.[1]]});: Chúng ta hãy tạo một hàm băm ("từ điển" cho Pythonists) được gọi là m(đó là một biến không rõ ràng, vì vậy chúng ta cần phải rõ ràng về việc gán một hàm băm vào nó %(...)) liên kết các khóa hình thức phức tạp x+iyvới các ký tự trong cột thứ nhất yxcột thứ của bản đồ.

my \a=m<>:k.classify({m{$_}});: Điều này tạo ra một "từ điển nghịch đảo" của m, được gọi là a: có một khóa tương ứng với mỗi giá trị trong mvà giá trị là một danh sách các tọa độ phức tạp (các khóa trong m) có chứa ký tự đó. Vì vậy, ví dụ a{"#"}sẽ đưa ra một danh sách tất cả các tọa độ nơi có một #bản đồ. (Đây cũng là một biến không rõ ràng, nhưng chúng tôi rất may mắn vì classifytrả về một hàm băm.)

my$m=a<#>[0];my$d=-1: Đặt vị trí quái vật ban đầu. Chúng tôi tìm kiếm #trong băm nghịch đảo a. Chúng ta phải sử dụng [0]a<#>vẫn là một danh sách, ngay cả khi nó chỉ chứa 1 phần tử. Cái $dchứa hướng của quái vật; chúng tôi đặt nó sang phương Tây. (Hướng cũng là một số phức, -1hướng tây cũng vậy .)

OK, tuyên bố tiếp theo là khá khó chịu. Trước tiên, hãy xem xét điều này: {$^q;first ?*,map {(((my$u=m{my$t=$m+$_*$q})~~"%")*(1+!($_-1))+($u~~"A".."Z"))*m+($u~~"*")*abs($t-$m)},^m}Đây là một thói quen đánh giá LoS ​​theo hướng đã cho. Nếu có một con người theo hướng này, nó sẽ trả lại khoảng cách cho con người. Nếu có một bức tường hoặc dịch chuyển tức thời theo hướng này, nó sẽ trả về tổng số ô vuông của bản đồ. (Vấn đề là đưa ra một con số cao đến mức nó lớn hơn bất kỳ khoảng cách hợp pháp nào với con người.) Cuối cùng, nếu bức tường nằm ở hướng này ở khoảng cách 1, chúng ta trả về 2 × tổng số ô vuông của bản đồ. (Chúng tôi muốn không bao giờ được chạy qua các bức tường, vì vậy những điều này thậm chí cần một số điểm lớn hơn. Chúng tôi sẽ sớm chọn mức tối thiểu.)

Chúng tôi sử dụng điều này trong xây dựng $d=($d,i*$d,-i*$d,-$d).min( LoS deciding block );. Vì chúng tôi sử dụng các số phức cho mọi thứ, chúng tôi có thể dễ dàng nhận được các hướng tương đối tiến, phải, trái và lùi từ hướng ban đầu chỉ bằng cách nhân nó với 1, i, -i (hãy nhớ rằng ytrục đi theo hướng khác mà bạn có thể được sử dụng từ toán học) và -1, tương ứng. Vì vậy, chúng tôi lập danh sách các hướng theo thứ tự này và tìm hướng có "khoảng cách đến con người" tối thiểu (theo khối ở trên), đảm bảo rằng bất kỳ con người nào đập bất kỳ bức tường nào và bất cứ thứ gì đập vào tường đều đúng dưới mũi của quái vật. Chúng tôi sử dụng thực tế là minhàm cho đầu tiêngiá trị tối thiểu. Nếu có một sự ràng buộc trong khoảng cách giữa một số hướng, quái vật sẽ thích chuyển từ phải sang trái sang lùi, đó chính xác là những gì chúng ta muốn. Vì vậy, chúng tôi nhận được một hướng mới mà sau đó được giao cho $d.

$m+=$d; chỉ làm cho quái vật bước theo hướng mới.

$m=$d+(a{m{$m}}∖~$m).pick while m{$m}~~"A".."Z"chăm sóc dịch chuyển tức thời. Hãy nói rằng con quái vật đang ở một dịch chuyển tức thời A. Đầu tiên chúng ta tìm kiếm Atrong hàm băm nghịch đảo %avà điều đó làm bật lên hai vị trí của dịch chuyển tức thời A, sau đó chúng ta loại bỏ vị trí hiện tại bằng cách sử dụng toán tử sai phân đặt (trông giống như dấu gạch chéo ngược). Vì có chính xác 2 lần xuất hiện của mỗi lần dịch chuyển tức thời trên bản đồ và quái vật chắc chắn đang đứng trên một, sự khác biệt sẽ là một tập hợp với 1 yếu tố. Sau đó, chúng tôi sử dụng .pickđể chọn một yếu tố ngẫu nhiên (tin hay không, nhưng đây là cách ngắn nhất để lấy phần tử của tập hợp 1 phần tử:. Điều này xảy ra cho đến khi con quái vật kết thúc ở một nơi không phải trong một cổng thông tin.

Tất cả mọi thứ trong 4 đoạn cuối mô tả một công trình đồ sộ {change direction; step; handle teleports}...{m{$m}~~"*"}. Đây là một chuỗi gọi khối bên trái ...cho đến khi điều kiện bên phải ...là đúng. Và điều đó là đúng khi con quái vật ở trên một hình vuông với một con người. Bản thân danh sách chứa các giá trị trả về của khối lớn ở bên trái, đó là rác (rất có thể (Any)) vì nó trả về giá trị của vòng lặp while ở cuối. Về cơ bản, chúng tôi sử dụng nó như một vòng lặp while rẻ hơn. Giá trị của danh sách bị loại bỏ (và trình biên dịch rên rỉ về "việc sử dụng vô dụng ...trong một cuộc thi chìm", nhưng ai quan tâm). Khi tất cả điều này được thực hiện, chúng tôi trở lại $m- vị trí của quái vật sau khi nó tìm thấy một con người, vẫn là một số phức (vì vậy, đối với thử nghiệm đầu tiên, chúng tôi đưa ra 10+2ivà cứ thế).


Giải thích tốt đẹp! :)
Ian H.

3

JavaScript (ES6), 258 245

g=>eval("m=g[I='indexOf']`#`,D=[w=g[I]`\n`+1,-1,-w,k=t=1],g=[...g];for(n=1/0;n;(o=g[m+=d=D[k]])>'@'?g[g[u=m]=t=1,m=g[I](o),u]=o:o<'%'?t=1:o<'*'&&(m-=d,k=k+t++&3))D.map((d,j)=>{for(q=0,u=m;g[u+=d]<'%';++q);g[u]=='*'&n>q&&(n=q,k=j)});[m%w,m/w|0]")

Ít chơi gôn

g=>{
    var u, // temp current position 
        q, // distance so far scanning for a human
        o, // value of grid at current position
        d, // offset to move given current direction
        n = 1/0 // current distance from human
        m = g.indexOf(`#`), // monster position
        w = g.indexOf(`\n`)+1, // grid width + 1 (offset to next row)
        D = [w,-1,-w,1], // offset for moves, clockwise
        k = 1, // current direction, start going west
        t = 1; // displacement for turn
    g=[...g]; // string to array
    while (n) // repeat while not found (distance > 0)
    {
      // look around to find humans
      D.forEach( (d,j) => { // for each direction
        // scan grid to find a human
        for(q=0, u=m; g[u+=d]<'$'; ++q); // loop while blank space
        if ( g[u] == '*' // human found at position u
             & n>q ) // and at a shorter distance than current
        {
           n = q; // remember min distance
           k = j; // set current direction
        }
      })
      // if human found, the current direction is changed accordingly
      d = D[k] // get delta
      m += d // move
      o = g[m] // current cell in o
      if (o > '@') // check if letter (teleporter)
      {
        t = 1 // keep current direction, next turn will be right
        u = m // save current position in u
        g[u] = 1 // clear current cell, so I can find only the other teleporter
        m = g.indexOf(o) // set current position to other teleporter
        g[u] = o // reset previous cell content
      }
      else if (o > '%') // check if '*'
      {
        // set result, so we can exit the loop
        r = [ m%w, m/w|0 ] // x and y position 
      }
      else if (o == '%') // check if wall
      {
        // turn
        m -= d // current position invalid, go back
        k = (k+t) % 4 // turn right 90° * t
        t = t+1 // next turn will be wider
      }
      else
      {
        t = 1 // keep current direction, next turn will be right
      }
    }
    return r
}

Kiểm tra

var F=
g=>eval("m=g[I='indexOf']`#`,D=[w=g[I]`\n`+1,-1,-w,k=t=1],g=[...g];for(n=1/0;n;(o=g[m+=d=D[k]])>'@'?g[g[u=m]=t=1,m=g[I](o),u]=o:o<'%'?t=1:o<'*'&&(m-=d,k=k+t++&3))D.map((d,j)=>{for(q=0,u=m;g[u+=d]<'%';++q);g[u]=='*'&n>q&&(n=q,k=j)});[m%w,m/w|0]")

var grid=[`%%%KLMNOPQRSTA%\n%%J           B\n%I       %*   C\nH   *         D\nG   %%        E\nF       #     F\nE      %      G\nD      *      H\nC   %        I%\nB           J%%\n%ATSRQPONMLK%%%`
,'%%%KLMNOPQRSTA%\n%%J           B\n%I      *     C\nH     %%%   * D\nG      #%     E\nF     %%%   % F\nE             G\nD       %     H\nC       *    I%\nB       *   J%%\n%ATSRQPONMLK%%%'
,'%%%KLMNOPQRSTA%\n%%J           B\n%I     %%%    C\nH     *%#%    D\nG             E\nF             F\nE       %     G\nD             H\nC            I%\nB           J%%\n%ATSRQPONMLK%%%'
,'%%%%%%%%%%%%%%%\n%#%       %%% %\n%A%ABCD   %*% %\n%*F     G %%% %\n% %BC% FD     %\n% %   %    %%%%\n% %  %       %%\n%   % %%   G  %\n%             %\n%*%    %    % %\n%%%%%%%%%%%%%%%'
]
$(function(){
  var $tr = $('tr')
  grid.forEach(x=>{
    $tr.eq(0).append("<td>"+x+"</td>")
    $tr.eq(1).append("<td>"+F(x)+"</td>")
  })
})
td {padding: 4px; border: 1px solid #000; white-space:pre; font-family:monospace }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table ><tr/><tr/></table>

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.