しないでください。でも。点滅


50

ここに画像の説明を入力してください

あなたの人生はこれに依存する可能性があります。点滅しないでください。まばたきさえしないでください。点滅して、あなたは死んでいます。彼らは速いです。信じられないほど速く。背を向けたり、目をそらしたり、まばたきしたりしないでください!幸運を。

泣く天使は異星人種であり、別の存在(別の天使でさえ)によって観察されている間は移動できません。彼らは犠牲者を時間内に送り返すことで食事をします。あなた(The Doctor)はいくつかの部屋に閉じ込められており、TARDISに行く必要があります。


仕事

長方形の部屋のASCII表現が与えられると、安全につながるパスを出力するプログラムを作成します。進行中にいつでも天使が攻撃できる場合、そのパスは安全ではありません。天使は、あなたや他の天使に見られずにあなたを見ることができれば攻撃できます。

入力

入力は2つの部分です。まず、あなたが向いている方向(NSEW)。その後、後続の行に、部屋の表現、開始/終了位置、およびすべての天使の位置/向きを示します。

以下のサンプルは、1人の天使が西を向いており、あなたが南を向いていることを示しています。

S
..........
....D.....
..........
..........
..........
..........
..........
..........
.........W
..........
...T......
  • . - 空きスペース
  • D -ドクター(開始位置)
  • T -TARDIS(終了位置)
  • N,S,E,W -指定された方向(北、南、東、西)に面した天使

視線

あなたが向いている方向の45度以内の空間を見ることができます。直接水平、垂直、または45度の対角線に沿って別のエンティティがある場合、視線は遮られます。他の対角線はビューを遮りませ。天使の視線も同じように機能します。たとえば、次-の図は、南を向いていると仮定した場合の視野を表しています。

........
...D....
..---...
.-----..
-------.
---N----
---.--N-
---.----

出力

出力は、終了するパスを表す文字列です。安全なパスが複数ある場合は、いずれかを選択します。安全なパスがない場合は、を出力します0。マップの形式が正しくない場合は、クラッシュするなど、お好きなことをしてください。部屋が長方形ではない場合、出口がない場合など、不正な形式であると考えてください。天使がいない場合、不正な形式ではなく、簡単です。

各ステップについて、次の2つのいずれかを実行できます。NSEW方向に移動するか、NSEW方向に向きを変えます(位置を変更せずに)。移動するには、単にその方向の文字を出力します。向きを変えるには、出力のF後に適切な文字を続けます。たとえば、次の出力:

SSFESSSSSSSW

入力セクションで指定されたサンプルの安全なパスです。南に2回移動し、天使が見えるように東を向いてから、南にさらに7回移動し、西に1回移動してTARDISに入ります。

テストケース

1)東向きの天使を回ってTARDISに行くことができます。あなたがそれらの間を直接踏み込まない限り、彼らはお互いを所定の位置にロックするので、あなたがどの方向に直面しているかは問題ではありません。

W
...D....
........
........
........
.E.....W
........
........
...T....

2)負け。それらを乗り越える方法はありません。あなたが彼らの間を歩むまで、彼らはお互いを見ることができます。その時点で、両方に直面することはできません。目を閉じてそれを乗り越えてください。

S
...D....
........
........
........
E......W
........
........
...T....

勝ち

標準のゴルフ規則と抜け穴が適用され、最小バイトが勝ちます。もうすぐいくつかのテストケースを取得しようとしますが、それまでの間はお気軽にご提案ください。

Doctor Whoからの画像と引用。


グラフのパスを見つけるためにライブラリを使用できますか?
スパー

@Sparrはい。ただし、ライブラリをロード/インクルードするために必要なものはすべてバイトカウントに追加する必要があります。
ジオビット14

2
明らかに渦マニピュレーターを使用してください!
TheDoctor 14

4
@TheDoctor Jackは彼を連れて行きましたが、彼はどのマップにもいないことがわかります(J)。
ジオビット14

1
@Timmy任意の標準定義を使用できます。
ジオビット14

回答:


6

Python – 559 565 644 633

M=input()
I=1j
Q={"S":I,"N":-I,"E":1,"W":-1}
A=[]
e=enumerate
for y,l in e(M[2:].split()):
 for x,c in e(l):
    P=x+y*1j
    if c=="D":D=(P,Q[M[0]])
    elif c=="T":T=P
    elif c!=".":A+=[(P,Q[c])]
def s(D,h,r=[]):
 def L(X,p,d):
    S=[p+d*(i+j*I)for i in range(x+y)for j in range(-i+1,i)if j]
    for f in[1,1+I,1-I]:
     i=0
     while i<x+y>1>(S[-1]in[a[0]for a in[D]+A]+[T])*i:i+=1;S+=[p+i*f*d]
    return X[0]in S
 if y>=D[0].imag>=(D[0]in[a[0]for a in A])<all(any(L(a,*b)for b in[D]+A)for a in A if L(D,*a))>(D in r)<=D[0].real<=x:
    r+=[D]
    if D[0]==T:print h;exit()
    for n in"SWEN":s((D[0]+Q[n],D[1]),h+n,r);s((D[0],Q[n]),h+"F"+n,r)
s(D,"")
print"0"

入力は次のように提供する必要があります。

"W\n...D....\n........\n........\n........\nE......W\n........\n........\n...T....\n"

基本的に、このアプローチは、医師が安全に到達できるすべての状態(位置と方向)を見つけ、そこに到達した方法を保存し、成功した場合に道を印刷することに適用されます。位置と方向は複素数で実現されます。

Sageの複素数演算を使用して、おそらくいくつかのcharを安全にできますが、それは非常に長くかかります。

タルディスに到達した後、医師に特定の方向に向かわせることで、6人のキャラクターを救うことができると最初に思いましたが、これは間違った解決策につながる可能性があることに気付きました。また、最初にルールを読み間違えました。

ここにほとんどのバージョンはありません:

Map = input()

I = 1j
string_to_dir = {"S":I,"N":-I,"E":1,"W":-1}

Angels = []
Pos = 0
direction = string_to_dir[Map[0]]
for y,line in enumerate(Map[2:].split()):
    for x,char in enumerate(line):
        Pos = x+y*1j
        if char == "D":
            Doctor = (Pos, direction)
        elif char == "T":
            Tardis = (Pos, direction)
        elif char != ".":
            Angels += [(Pos,string_to_dir[char])]

reachables = []

def display(LoS, Doctor):
    string = ""
    for y,line in enumerate(Map[2:].split()):
        for x,char in enumerate(line):
            if x+y*1j == Doctor[0]:
                string += "D"
            elif x+y*1j in LoS:
                if char in ".D":
                    string += "*"
                else:
                    string += "X"
            elif char != "D":
                string += char
            else:
                string += "."

        string += "\n"
    print string

def LoS(angel,Doctor):
    p,d = angel
    Sight = []
    for i in range(x+y):
        for j in set(range(-i+1,i))-{0}:
            Sight += [p+d*i+d*j*I]
    for line in [d, (1+I)*d, (1-I)*d]:
        for i in range(1,x+y):
            Pos = p + i*line
            Sight += [Pos]
            if Pos in [angel[0] for angel in Angels+[Doctor, Tardis]]:
                break
    return Sight

def search(Doctor, history):
    global reachables

    Sight = sum([LoS(angel, Doctor) for angel in [Doctor]+Angels],[])

    if (
                all(angel[0] in Sight for angel in Angels if Doctor[0] in LoS(angel, Doctor))
            and not (Doctor in reachables)
            and (0<=Doctor[0].imag<=y)
            and (0<=Doctor[0].real<=x)
            and (Doctor[0] not in [angel[0] for angel in Angels])
        ):

        reachables += [Doctor]

        if Doctor[0] == Tardis[0]:
            print history
            exit()
        for new_direction in "SWEN":
            search((Doctor[0]+string_to_dir[new_direction], Doctor[1]), history + new_direction)
            search((Doctor[0], string_to_dir[new_direction]), history + "F" + new_direction)

search(Doctor, "")
print "0"

テストケース

テストケース1:

SSSFSWWWSSSSFWEFSEFWE

テストケース2:

0

VisualMelonのテストケース:

SSFWSSSSSFSWWSSWWWFWEEEEFSEFWEFSE

1
コードはテストしていませんが、テストケース1の出力を2回貼り付けたようです!また、提案されたテストケースにフィードを送信すると、プログラムが何を生成するのかを確認したいと思います。
VisualMelon 14

@VisualMelon:見つけてくれてありがとう、テストケースを統合しました。
Wrzlprmft 14

10

C#1771 2034 1962 1887 1347バイト

ブロッキングLOSチェックを1ループで書き直し、より整理し、約450バイト短くしました。

using C=System.Console;using T=System.Math;struct P{int x,y,d;static void Main(){int v=C.ReadLine()[0],w,h,i,o=0,x=0,y=0,O,E,F,e=46;var R=C.In.ReadToEnd().Replace("\r","");var M=new int[w=R.IndexOf("\n"),h=(R.Length+1)/(w+1)];for(;o<h;o++)for(i=0;i<w;i++)if((M[i,o]=R[o+o*w+i])==68)M[x=i,y=o]=e;System.Func<int,int,int,bool>S=null;S=(X,Y,D)=>{var Z="SSSE_WNNNE_W___E_W";int I=0,H=0,L=0,J=Y,K=M[X,Y],B;M[X,Y]=D>0?D:K;for(H=0;H<9;H++)for(I=X,J=Y;H!=4&(I+=H%3-1)<w&I>=0&(J+=H/3-1)<h&&J>=0;){if(((B=M[I,J])==Z[H]|B==Z[H+9])&(D<1||!S(I,J,0)))goto W;if(B!=e)break;}for(B=I=-1;++I<w;B=1)for(J=0;J<h;J++)if(I!=X&J!=Y&(((B=M[I,J])==87&I>X&(H=T.Abs(J-Y))<I-X)|(B==69&I<X&H<X-I)|(B==78&J>Y&(L=T.Abs(I-X))<J-Y)|(B==83&J<Y&L<Y-J))&(D<1||!S(I,J,0)))goto W;W:M[X,Y]=K;return B>1;};P a,p=new P{x=x,y=y,d=v};var A=new System.Collections.Generic.List<P>();System.Action q=()=>{if(((E=M[p.x,p.y])==e|E==84)&!A.Contains(p)&!S(p.x,p.y,p.d))A.Add(p);};q();for(o=0;(O=A.Count)!=o;o=O)for(i=O;i-->o;){p=A[i];if((E=M[p.x,p.y])==84)for(R="";;p=a){i=0;n:a=A[i++];O=T.Abs(p.y-a.y)+T.Abs(a.x-p.x);if(O==1&p.d==a.d)R=(a.y-p.y==1?"N":p.y-a.y==1?"S":a.x-p.x==1?"W":"E")+R;else if(O<1)R="F"+(char)p.d+R;else goto n;if(i<2)goto Z;}if(E==e){if(p.x-->0)q();p.x+=2;if(p.x<w)q();p.x--;if(p.y-->0)q();p.y+=2;if(p.y<h)q();p.y--;for(F=0;F<4;q())p.d="NESW"[F++];}}R="0";Z:C.WriteLine(R);}}

これは、入力がEOFで終了し、STDINに渡されることを期待する完全なプログラムです。(できれば)TARDISへの最短パス、またはパスが存在しない場合は「0」を出力します。見掛け倒しのBreadth First Searchを使用して、考えられるすべてのルートをたどり、TARDISからThe Doctorに戻って出力を組み立てます。

フォーマットされたコード:

using C=System.Console;
using T=System.Math;

struct P
{
    int x,y,d;

    static void Main()
    {
        int v=C.ReadLine()[0],w,h,i,o=0,x=0,y=0,O,E,F,e=46;
        var R=C.In.ReadToEnd().Replace("\r","");
        var M=new int[w=R.IndexOf("\n"),h=(R.Length+1)/(w+1)];

        for(;o<h;o++)
            for(i=0;i<w;i++)
                if((M[i,o]=R[o+o*w+i])==68)
                    M[x=i,y=o]=e;

        System.Func<int,int,int,bool>S=null;
        S=(X,Y,D)=>
        {
            var Z="SSSE_WNNNE_W___E_W";

            int I=0,H=0,L=0,J=Y,K=M[X,Y],B;
            M[X,Y]=D>0?D:K;

            for(H=0;H<9;H++)
                for(I=X,J=Y;H!=4&(I+=H%3-1)<w&I>=0&(J+=H/3-1)<h&&J>=0;)
                {
                    if(((B=M[I,J])==Z[H]|B==Z[H+9])&(D<1||!S(I,J,0)))
                        goto W;
                    if(B!=e)
                        break;
                }

            for(B=I=-1;++I<w;B=1)
                for(J=0;J<h;J++)
                    if(I!=X&J!=Y&(((B=M[I,J])==87&I>X&(H=T.Abs(J-Y))<I-X)|(B==69&I<X&H<X-I)|(B==78&J>Y&(L=T.Abs(I-X))<J-Y)|(B==83&J<Y&L<Y-J))&(D<1||!S(I,J,0)))
                        goto W;
        W:
            M[X,Y]=K;
            return B>1;
        };

        P a,p=new P{x=x,y=y,d=v};
        var A=new System.Collections.Generic.List<P>();
        System.Action q=()=>{if(((E=M[p.x,p.y])==e|E==84)&!A.Contains(p)&!S(p.x,p.y,p.d))A.Add(p);};
        q();

        for(o=0;(O=A.Count)!=o;o=O)
            for(i=O;i-->o;)
            {
                p=A[i];
                if((E=M[p.x,p.y])==84)
                    for(R="";;p=a)
                    {
                        i=0;
                    n:
                        a=A[i++];

                        O=T.Abs(p.y-a.y)+T.Abs(a.x-p.x);
                        if(O==1&p.d==a.d)
                            R=(a.y-p.y==1?"N":p.y-a.y==1?"S":a.x-p.x==1?"W":"E")+R;
                        else if(O<1)
                            R="F"+(char)p.d+R;
                        else goto n;

                        if(i<2)
                            goto Z;
                    }
                if(E==e)
                {
                    if(p.x-->0)q();
                    p.x+=2;if(p.x<w)q();p.x--;
                    if(p.y-->0)q();
                    p.y+=2;if(p.y<h)q();p.y--;

                    for(F=0;F<4;q())
                        p.d="NESW"[F++];
                }
            }
        R="0";
    Z:
        C.WriteLine(R);
    }
}

入力例の出力

SFESWSSSSSSS

テストケース1の出力

WSWSWSSSESESE

テストケース2の出力

0

要求に応じて、新しいテストケースを提示します。

S
..E..DS....
...........
...........
...........
...........
...........
...........
...........
....SSSSS.W
.......T...

私のプログラム出力

SESESESESFNSSSSWW

WozzeCのテストケース1:

EEEEFWSSSFNWWN

WozzeCのテストケース2:

FSEEEESFWSSSSWFNWWWNFENNEES

X = System.Consoleを使用する可能性を完全に逃しました。それをありがとう:)
WozzeC 14

@WozzeCあなたがチェックアウトする場合がありますC#のコード・ゴルフのためのヒントを
VisualMelon

私はあなたのテストケースで医師がスタートアップで攻撃されていると信じています:S
WozzeC 14

@WozzeC南東の西の天使は北西の東の天使を見ることができるので、医者は逃げることができますが、その点で、私のソリューションは起動時に医者が攻撃されても気づかないようです。このコードをテストするのが難しいのはなぜですか!
VisualMelon

1
すみません、気にしないでください。私は、別の天使が見ている場合、彼らが移動できないという細部を逃しました。
WozzeC 14

2

C#1454、1396、1373、1303 1279

class P{static int x,d,y=x=d=55,o=170,X=0,Y=0,u,k=3;static string[,]t=new string[o,o];static int[,]m=new int[o,o];static string e=" NS ETD W      .",q="0";static void Main(string[]s){m[0,1]=m[1,8]=-1;m[0,2]=m[1,4]=1;u=e.IndexOf(s[0][0]);for(;k<s[0].Length;k++){var c=s[0][k];if(c=='D'){X=x;Y=y;}if(c=='\\'){y++;x=d;k++;}else m[y,x++]=e.IndexOf(c);}k=A(X,Y,1);if((k&u)!=0){W(X,Y,k,"");}System.Console.Write(q);}static void W(int x,int y,int h,string s){t[y,x]=s;for(int i=1;i<9;i*=2){int l=y+m[0,i],g=x+m[1,i];if(m[l,g]==5)q=t[l,g]=s+e[i];else if(m[l,g]==15){m[l,g]=6;m[y,x]=15;int n=A(g,l,1),U;for(int j=1;j<9;j*=2){var z=t[l,g]??s;if((n&h&j)!=0&z.Length>=s.Length){U=u;u=j;W(g,l,n,s+((u!=j)?"F"+e[j]:"")+e[i]);u=U;}}m[y,x]=6;m[l,g]=0;}}}static int A(int x,int y,int L){int r=15,a,b,c,f=0,g,h,R,B;for(a=1;a<d-5;a++){g=1;for(b=y-a;b<=y+a;b++)for(c=x-a;c<=x+a;c++){B=m[b,c];R=0;bool W=(c+a-x)%a==0,V=(b+a-y)%a==0,z=W&V;if(B>0&B<9&B!=6&B!=5&g!=16&!((W|V)&(f&g)!=0)){h=R;if(b==y-a){R=1;if(c==x-a){h=4;R=9;}else if(c==x+a){h=8;R=5;}B&=h&2;}else if(b==y+a){R=2;if(c==x-a){h=4;R=10;}else if(c==x+a){h=8;R=6;}B&=h&1;}else if(c==x-a){B&=4;R=8;}else if(c==x+a){B&=8;R=4;}else B=0;if(B!=0){if(L==1&&A(c,b,0)==15)r&=R;if(L==0)return R;}}if(z){if(B<9&B>0&!(c==x&y==b))f|=g;g*=2;}}}return r;}}

右。それで私はこれを試してみることにしました、そして、少年はそれをしばらくしました。主に論理演算子を使用して構築されます。

  • 北= 1 = N
  • 南= 2 = S
  • 東= 4 = E
  • 西= 8 =西
  • ドクター= 6 = D
  • タルディス= 5 = T
  • 15 =。<-すべての空きスペース

Nullなどを確認する必要がないように、[MAX_SIZE * 3] * [MAX_SIZE] * 3のフィールドを使用して、ゲームボードを中央近くに配置することにしました。

ループチェックは、50(MAX_SIZE)まで内側と外側で行われます。このようなもの:

22222
21112
21D12
21112
22222

EWSまたはNが見つかった場合、それらについて同じチェックを行います。天使(医師ではない)を見て何かが見つかった場合、自由通路として15を返します。彼らが見られていない場合、彼らは医者が安全であるために直面​​すべきである方法で戻る。つまり、Nは南に2を返します。NWまたはNEである場合を除き、それぞれ6(2 + 4)および10(2 + 8)を返します。

2人の天使がDoctorを監視している場合、これらからの戻り値は「AND」されるため、テスト例では2のクランチポジション4と8が0になります。

拡張コード:

class P
{
    static int x,d,y=x=d=55,o=170,X=0,Y=0,u,k=3;
    static string[,] t = new string[o, o];
    static int[,] m = new int[o, o];
    static string e = " NS ETD W      .", q="0";
    static void Main(string[]s)
    {   
        m[0, 1]=m[1, 8]=-1;
        m[0, 2]=m[1, 4]=1;
        u=e.IndexOf(s[0][0]);
        for (;k<s[0].Length;k++)
        {
            var c = s[0][k];
            if (c == 'D') { X = x; Y = y; }
            if (c == '\\') { y++; x = d; k++; }
            else m[y, x++] = e.IndexOf(c);
        }
        k=A(X,Y,1);
        if ((k&u)!=0)
        {
            W(X, Y, k,"");
        }
        System.Console.Write(q);
    }
    static void W(int x,int y,int h,string s){
        t[y, x] = s;
        for (int i = 1; i < 9; i*=2)
        {
            int l = y+m[0, i], g = x+m[1, i];
            if (m[l, g] == 5)
                q = t[l, g] = s + e[i];
            else if (m[l, g] == 15)
            {
                m[l, g] = 6;
                m[y, x] = 15;
                int n = A(g, l,1),U;
                for (int j = 1; j < 9; j *= 2)
                {
                    var z = t[l, g]??s;
                    if ((n & h & j) != 0 & z.Length>=s.Length)
                    {
                        U = u;
                        u = j;
                        W(g, l, n,s+((u != j) ? "F" + e[j] : "") + e[i]);
                        u = U;
                    }
                }
                m[y, x] = 6;
                m[l, g] = 0;
            }
        }
    }
    static int A(int x, int y,int L)
    {
        int r = 15,a,b,c,f=0,g,h,R,B;
        for (a = 1; a < d - 5; a++)
        {
            g = 1;
            for (b = y - a; b <= y + a; b++)
                for (c = x - a; c <= x + a; c++)
                {
                    B=m[b, c];
                    R=0;
                    bool W=(c+a-x)%a==0,V=(b+a-y)%a==0,z=W&V; 
                    if (B>0&B<9&B!=6&B!=5&g!=16&!((W|V)&(f&g)!=0))
                    {
                        h=R;
                        if (b==y-a)
                        {
                            R=1;
                            if(c==x-a){h=4;R=9;}
                            else if(c==x+a){h=8;R=5;}
                            B&=h&2;
                        }
                        else if (b==y+a)
                        {
                            R=2;
                            if(c==x-a){h=4;R=10;}
                            else if (c==x+a){h=8;R=6;}
                            B&=h&1;
                        }
                        else if(c==x-a){B&=4;R=8;}
                        else if(c==x+a){B&=8;R=4;}
                        else B=0;
                        if (B!=0)
                        {
                            if(L==1&&A(c,b,0)==15)r&=R;
                            if (L==0)return R;
                        }
                    }
                    if (z)
                    {
                        if (B < 9 & B > 0 & !(c==x&y==b))
                           f |= g;
                        g *= 2;
                    }
                }
        }
        return r;
    }
}

試験結果

1例:FNSSSWNNNWSSSWSSSSENNESES

2例:出口なし

VisualMelonの例:FNSSSSSSSWNNNNNNNWSSSSSSSSSEEEEEE

私のテストケース1:FSSENEEEFWSSFNSWWN

私のテストケース2:FSEEEESFWSSSSFNWWWWNFENNFSEES

ご覧のように、私の医師は、天使たちに動き回ることの楽しさを示すために、潅水のように歩き回るのが大好きです。ソフトウェアに最短経路を見つけさせることはできますが、時間がかかり、より多くのコードが必要です。

あなたのためのテストケース

S
D....
..NE.
.WTS.
.S...

別のもの:

E
D....
WNNN.
...E.
.WTE.
.SSE.
.....

1
ゴルフされたコードには、コンパイルを停止するスペースが1か所ありませんが、その修正により、1395バイトしかカウントされません!それを非常に低くする素晴らしい仕事であり、あなたが使用するのは完全に公正なゲームですusing S=System.Console;、または単にコードからSを完全に削除して6バイト節約することができusing Systemます 今、私は私の素朴なアプローチをさらに
試行錯誤

1
ミスしたスペース、私はそれを大事にする必要があります。そしてもちろん、S = ...私がそれを学んだとき、少し夢中になりました。:)
WozzeC 14

バイト数を
減らす良い仕事

使用されなかったコードを見つけました。加えて、いくつかの追加の不必要なもの。
WozzeC 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.