不気味な廊下


8

この課題は、前にプレイしたボードゲームに触発されました。
この課題のストーリーは必ずしも読む必要はありません。課題のセクションでは、必要なすべてを説明する必要があります。

物語

人々は人間を食い尽くすモンスターがいる大きな部屋の中に閉じ込められています。部屋の壁はエンチャントされており、触れるとオブジェクトが部屋全体にテレポートします。怪物は部屋を横切って行進し、肉を探します。視界の最初の人間はその鋭い歯によって消費されます。

チャレンジの目標

あなたは、人とモンスターの場所を含む部屋の地図を与えられます。

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

マップのコンポーネントを分解してみましょう。

  • Ato からの文字T:モンスターがこれらのいずれかに踏み込むと、この文字の2番目の外観にテレポートされ、方向は変わりません。ボードには、文字が0つか2つしかありません。
  • %:壁のタイル。書式設定と見栄えだけのために。
  • #:モンスターの開始位置。
  • *:人々の場所。
  •  :空のタイル、モンスターはそれらの上を自由に移動できます。

マップについて注意すべきいくつかの追加事項:

  • マップの次元とオブジェクトの場所は一定ではないため、コードはそれに動的に適応する必要があります。

モンスターは、人間を見つけない限り、常に現在直面している方向(最初は西を向いています)に移動します。その場合、人間に最も近くなります。
壁とテレポーターのタイルが人間と人間の間に水平または垂直の直線状にない場合、モンスターは人間を見つけます。

もう1つ注意すべき点は、モンスターが堅い壁の前にいる場合(%)、または2人の人間の間で決定する必要がある場合は、常に右より左を優先するということです。

モンスターがなんらかの理由で右に曲がることができずに前進することができない場合、それは左に曲がります代わりにます。

つまり、最終的に、モンスターが方向を優先する順序は、前方、右、左、後方になります。

入力

  • モンスターの開始位置と人々の位置をそれぞれのキャラクターとして含むマップ。マップ文字列、文字列の配列、または文字以外の入力があってはなりません。

入力は適切な形式で受け取ることができます。マップの単一の文字列または文字列の配列。

出力

モンスターに最初に食べられる人のコーディネート。

座標は左上隅から始まり、0から始まるため、最初のタイルの座標は(0 | 0)になります。1インデックスを使用している場合は、回答でそれを指定してください。

ルール

  • これはで、どの言語でもバイト単位で最も短いコードが優先されます。
  • 標準の抜け穴は禁止されています。
  • あなたはモンスターが常に人間に到達できると仮定するかもしれません。

テストケース

入力:

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

出力:(10,2)、モンスターは他の2人を通り過ぎても他の2人を見ることができないため、他のF壁にテレポートされ、最後の人が表示されます。

入力:

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

出力: (12,3)

入力:

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

出力: (6, 3)

入力:

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

出力: (1,9)


幸運を!


説明の早い段階で、人間は動かないことを明示する必要があります。最初は静止していることに気づきませんでした。私がそのような状況で人間だったら、私は確かに動いているでしょう!
— DLosc 2017

回答:


6

パイソン2、565 .. 422 445 1 ... 444 463 2 ... 468の 467 463バイト

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

オンラインでお試しください!

Halvard、Ian、Jonathanのおかげで多くのバイトを節約

1:2回転する場合を修正し、モンスターの位置を見つけるために長くなった。
2:さらに長くなります。テレポートするときにモンスターが方向を変えてはいけません。


ややゴルフ482バイト。TIOが長くなりすぎたためリンクが短縮されました
— Halvard Hummel 2017

@Halvard小さなゴルフ、わずか1バイト:481

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

固定が、今ではあなたと同じ長さだ434バイト

2
@KevinCruijssenイアンが私の回答は有効であると見なしていると知っていますが、とにかく変更します。
— TFeld 2017

5

Perl 6、343 334 333 328 322 308バイト

{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}

オンラインでお試しください!

(実際のコードには改行はありません。読みやすくするために改行するために挿入しました。)

これは、マップ境界の外側を見ることが可能なマップを処理することができません。(つまり、境界に空のスペースがあるマップ。)これが重要な場合は、+ 5バイト。しかし、テレポーターは現在LoSをブロックしているので、ブロックすべきではありません。

説明:これは、文字のリストのリストとしてマップを取る関数です。それをステートメントに分解しましょう:

my \m=%((^@^a X ^@a[0]).map:{.[0]i+.[1]=>@a[.[0]][.[1]]});:呼ばれるハッシュ(Pythonistの "dictionary")を作成しましょうm(これはシギレス変数なので、ハッシュをに割り当てることを明示的に指定する必要があります%(...))。これは、フォームの複雑なキーを行と列にあるx+iy文字に関連付けます。マップの。yx

my \a=m<>:k.classify({m{$_}});:これにより、の「逆辞書」が作成さmれaます。:の各値に対応する1つのキーがmあり、値はmその文字を含む複雑な座標(のキー)のリストです。したがって、たとえば、地図上a{"#"}にあるすべての座標のリストが#表示されます。(これも簡単な変数ですclassifyが、ハッシュを返すので運が良かったです。)

my$m=a<#>[0];my$d=-1:モンスターの初期位置を設定します。#逆ハッシュでを調べますa。要素が1つしかない場合でも、はリストであるため[0]、使用する必要がありますa<#>。$dモンスターの方向が含まれています。西に設定しました。(方向も複素数なので-1、西です。)

OK、次のステートメントはかなり厄介です。まず、{$^q;first ?*,map {(((my$u=m{my$t=$m+$_*$q})~~"%")*(1+!($_-1))+($u~~"A".."Z"))*m+($u~~"*")*abs($t-$m)},^m}これを見てみましょう。これは、指定された方向でLoSを評価するルーチンです。この方向に人間がいる場合は、人間までの距離を返します。この方向に壁またはテレポートがある場合、マップの正方形の総数を返します。(ポイントは、人間までの正当な距離よりも大きいような高い数値を与えることです。)最後に、壁がこの方向にあり、、距離が1の場合、マップの正方形の総数の2×2を返します。(壁を突き抜けることは絶対に避けたいので、さらに大きなスコアが必要です。間もなく最小値を選択します。)

これを構文で使用します$d=($d,i*$d,-i*$d,-$d).min( LoS deciding block );。すべてに複素数を使用しているため、1、i、-iを掛けるだけで、元の方向から相対的に前後左右の方向を簡単に取得できます(y軸が他の方向に移動することに注意してください) math)と-1からそれぞれ使用されます。そのため、この順序で方向のリストを作成し、「人間までの距離」が最小の方向を見つけます(上記のブロックに従って)。これにより、人間が壁を打ち、何かが正しい壁を打ち破るようになります。モンスターの鼻の下。min関数が最初に与えるという事実を使用します最小値。複数の方向の間に距離がある場合、モンスターは前方から右、左から後方への移動を好みます。これはまさに私たちが望むことです。したがって、次に割り当てられる新しい方向を取得し$dます。

$m+=$d; モンスターを新しい方向に向けるだけです。

$m=$d+(a{m{$m}}∖~$m).pick while m{$m}~~"A".."Z"テレポートを処理します。モンスターがテレポートにAいるとしましょう。最初にA逆ハッシュを検索する%aと、テレポートの2つの位置が表示されますA。次に、差差演算子(バックスラッシュのように見えます)を使用して現在の位置を破棄します。マップ上の各テレポートは正確に2回発生し、モンスターは確実に1つ上に立っているため、違いは1つの要素を持つセットになります。次に、を使用.pickしてランダムな要素を選択します(信じられないかもしれませんが、これは1要素セットの要素を取得する最も短い方法です:—))。この種のことは、モンスターがポータルではない場所に到達するまで起こります。

最後の4段落のすべては、フォームの1つの大規模な構造を説明してい{change direction; step; handle teleports}...{m{$m}~~"*"}ます。これは、...の右側の条件...がtrue になるまで、の左側のブロックを呼び出すシーケンスです。そして、それはモンスターが人間と一緒に広場にいるときに本当です。リスト自体には、左側の巨大なブロックの戻り値が含まれています。これは(Any)、最後にwhileループの値を返すため、ガベージ(ほとんどの場合)です。本質的に、より安価なwhileループとして使用します。リストの値は破棄されます(そして、コンパイラは「...シンクコンテストでの無用な使用」についてうめきますが、誰も気にしません)。これがすべて完了すると$m、人間が見つかった後のモンスターの位置がまだ複素数として返されます(つまり、最初のテストでは10+2i、このように指定します)。


いい説明だ!:)
— 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]")

ゴルフが少ない

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
}

テスト

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>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.