Не варто. Навіть. Мигніть


50

введіть тут опис зображення

Від цього може залежати ваше життя. Не моргайте. Навіть не моргніть. Мигніть і ви мертві. Вони швидкі. Швидше, ніж можна повірити. Не повертайтеся спиною, не відволікайте погляд і не моргайте! Удачі.

Плачучі ангели - це чужа раса, яка не може рухатися, спостерігаючи іншу істоту (навіть інший Ангел). Вони годують, відправляючи жертв назад у часі. Ви ( Лікар ) потрапили в пастку з кімнатою з деякими, і вам потрібно дістатися до свого ТАРДІС.


Завдання

Напишіть програму, яка дасть уявлення ASCII прямокутної кімнати, виведе шлях, який призведе вас до безпеки. Якщо будь-який Ангел може напасти - в будь-який час під час вашого прогресу - тоді цей шлях не є безпечним. Ангел може напасти, якщо він може бачити вас, не бачивши вас чи інший Ангел.

Вхідні дані

Вхід - дві частини. По-перше, напрямок, у якому ви стикаєтесь (NSEW). Потім на наступних лініях представлення кімнати, де відображаються початкові / кінцеві місця та місцеположення / обличчя всіх Ангелів.

Зразок нижче показує, що один ангел звернений на захід, і ви починаєте звернутись на південь.

S
..........
....D.....
..........
..........
..........
..........
..........
..........
.........W
..........
...T......
  • . - Порожній простір
  • D - Лікар (вихідна позиція)
  • T - TARDIS (кінцева позиція)
  • N,S,E,W - Ангел, звернений до вказаного напрямку (північ, південь, схід, захід)

Лінія зору

Ви можете бачити будь-який простір у напрямку 45 градусів у напрямку, перед яким ви стикаєтеся. Лінія зору перешкоджає, якщо по прямій горизонтальній, вертикальній або 45-градусної діагоналі є інше утворення. Будь-яка інша діагональ не перешкоджає погляду. Лінія зору Ангелів працює так само. Наприклад, у наведеному нижче -зображено ваше поле зору, припускаючи, що ви стикаєтесь на південь.

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

Вихід

Вихід - це рядок, що представляє шлях, який ви пройдете до виходу. Якщо є кілька безпечних шляхів, виберіть будь-який. Якщо жоден шлях не є безпечним, виведіть 0. Якщо карта неправильна, робіть все, що завгодно, у тому числі вибиваючи з ладу. Вважайте його неправильним, якщо кімната не прямокутна, немає виходу і т. Д. Якщо немає Ангелів, вона не деформована, просто легко.

Для кожного кроку ви можете зробити одну з двох речей: рухатися в напрямку NSEW або повертатися в напрямку NSEW (без зміни позицій). Для переміщення просто виведіть букву в цьому напрямку. Щоб повернутись обличчям до напрямку, виведіть Fподаний відповідний лист. Наприклад, такий вихід:

SSFESSSSSSSW

- це безпечний шлях для вибірки, наведеної у вхідному розділі. Ви двічі рухаєтесь на південь, обличчям на схід, щоб ангел не було видно, потім ще пів разів рухаєтесь на південь і один раз на захід, щоб увійти в ТАРДІС.

Випробування

1) Ви можете об'їхати Ангела, що виходить на схід, щоб дістатися до TARDIS. Якщо ви не переходите безпосередньо між ними, вони фіксують один одного на місці, тому не має значення, в який бік ви стикаєтеся в будь-який момент.

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

2) Ви програєте. Неможливо обійти їх. Вони можуть бачити один одного, поки ви не переступите між ними. На той момент ви не можете зіткнутися з ними обома, і ви закінчите. Можна також просто заплющити очі і перебрати це.

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

Перемога

Застосовуються стандартні правила для гольфу та лазівки , виграє найменше байт. Я спробую найближчим часом отримати ще кілька тестових випадків, але сміливо підкажу тим часом свої.

Зображення та цитата від Doctor Who.


чи можемо ми використовувати бібліотеку для пошуку шляху через графік?
Спарр

@Sparr Так, але все необхідне для завантаження / включення бібліотеки слід додати до кількості байтів.
Геобіт

2
Очевидно, використовуйте вихровий маніпулятор!
TheDoctor

4
@Доктор Джек взяв його з собою, і ви можете бачити, що він не знаходиться на жодній із карт ( J).
Геобіц

1
@Timmy Будь-яке із стандартних визначень може бути використане.
Геобіц

Відповіді:


6

Пітон - 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"

По суті, саме цей підхід застосовується для пошуку всіх станів (положення та напряму), до яких лікар може безпечно дістатися, зберігаючи, як він потрапив туди, і друкуючи шлях у випадку успіху. Позиції та напрямки реалізуються складними числами.

Я, певно, міг би захистити деякі знаки, використовуючи складну арифметику Сейджа, але це триватиме надзвичайно довго.

Я спершу подумав, що зможу врятувати шість персонажів, змусивши Доктора повернутись у певний напрямок після досягнення Тардіса, але зрозумів, що це може призвести до неправильних рішень. Також я спочатку неправильно прочитав правила.

Ось здебільшого неозорений варіант:

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! Також мені було б цікаво подивитися, що виробляє ваша програма, якщо ви її подаєте в запропонованому нами тестовому випадку.
VisualMelon

@VisualMelon: Дякую за те, що ви побачили, і я інтегрував тестовий випадок.
Wrzlprmft

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", якщо шлях не існує. Для спостереження за всіма можливими маршрутами він використовує похмурий Широкий пошук, щоб відслідковувати всі можливі маршрути.

Форматований код:

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

@WozzeC Ви можете перевірити поради щодо гольф-коду в C #
VisualMelon

Я вважаю, що лікаря атакують при запуску разом із вашим тестовим випадком: S
WozzeC

@WozzeC Західний ангел на Південному Сході може бачити Східного ангела на Північному Заході, тож Лікар може врятуватися, але в цьому пункті, схоже, моє рішення не помічає, якщо доктора нападають при запуску. Чому цей код так важко перевірити!
VisualMelon

1
Вибачте, неважливо. Я пропустив невелику деталь, яку вони не можуть рухати, якщо дивиться інший ангел.
WozzeC

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 = Е
  • Захід = 8 = Вт
  • Лікар = 6 = D
  • TARDIS = 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) відповідно.

Якщо два ангели спостерігають за лікарем, то значення повернення від них були б "ANDed", тому в прикладі тесту 2 криптовалюти 4 AND 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: FNSSSSSSSWNNNNNNNWSSSSSSSSSEEEEE

Мій тест1: FSSENEEEFWSSFNSWWN

Мій тест2: FSEEEESFWSSSSFNWWWWNFENNFSEES

Як видно, мій лікар любить тупотіти навколо, як душ, щоб показати Ангелам, як весело рухатись. Я можу змусити програмне забезпечення знайти найкоротший шлях, але це займає більше часу і потребує більше коду.

Випробування для вас, хлопці

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

Інший:

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

1
У коді для гольфу відсутній пробіл в одному місці, яке зупиняє його збір, але за допомогою цього виправлення я змушую вас байт рахувати лише 1395! Приємна робота, що знижує її так низько, і це абсолютно чесна гра, яку ви можете використовувати using S=System.Console;, або ви можете просто видалити S у своєму коді і зберегти 6 байт using System. Тепер мені доведеться спробувати
поправити

1
О пропущений простір, я повинен про це подбати. І звичайно S = ... Трохи захопився, коли я дізнався про це. :)
WozzeC

Хороша робота з підрахунком байтів;)
VisualMelon

Я знайшов якийсь код, який ніколи не використовувався. Плюс додаткові непотрібні речі.
WozzeC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.