No lo hagas Incluso. Parpadeo

50

ingrese la descripción de la imagen aquí

Tu vida podría depender de esto. No pestañees. Ni siquiera pestañees. Parpadea y estás muerto. Ellos son rápidos. Más rápido de lo que puedes creer. ¡No le des la espalda, no mires a otro lado y no pestañees! Buena suerte.

Los Ángeles llorones son una raza alienígena que no puede moverse mientras otro ser lo observa (incluso otro Ángel). Se alimentan enviando a sus víctimas en el tiempo. Usted ( el Doctor ) está atrapado en una habitación con algunos, y necesita llegar a su TARDIS.


Tarea

Escriba un programa que, dada una representación ASCII de una habitación rectangular, muestre un camino que lo llevará a la seguridad. Si algún ángel puede atacar, en cualquier momento durante su progreso , entonces ese camino no es seguro. Un ángel puede atacar si puede verte mientras tú u otro ángel no te ven.

Entrada

La entrada es de dos partes. Primero, la dirección que estás mirando (NSEW). Luego, en líneas sucesivas, una representación de la sala, que muestra las ubicaciones de inicio / finalización y la ubicación / orientación de todos los Ángeles.

El siguiente ejemplo muestra que hay un ángel mirando hacia el oeste, y usted comienza a mirar hacia el sur.

S
..........
....D.....
..........
..........
..........
..........
..........
..........
.........W
..........
...T......
  • . - Espacio vacio
  • D - El Doctor (posición inicial)
  • T - La TARDIS (posición final)
  • N,S,E,W - Un ángel, mirando hacia la dirección especificada (norte, sur, este, oeste)

Línea de visión

Puede ver cualquier espacio dentro de los 45 grados de la dirección que está mirando. La línea de visión está obstruida si hay otra entidad a lo largo de una horizontal directa, vertical o diagonal de 45 grados. Cualquier otra diagonal no obstruye la vista. La línea de visión de los ángeles funciona de la misma manera. Por ejemplo, a continuación, -representa su campo de visión, suponiendo que esté orientado hacia el sur.

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

Salida

La salida es una cadena que representa la ruta que tomará para salir. Si hay varias rutas seguras, elija una. Si ninguna ruta es segura, salida 0. Si el mapa está mal formado, haga lo que quiera, incluso estrellarse. Considérelo malformado si la habitación no es rectangular, no hay salida, etc. Si no hay ángeles, no tiene malformación, simplemente es fácil.

Para cada paso, puede hacer una de dos cosas: moverse en dirección NSEW o girar en dirección NSEW (sin cambiar de posición). Para moverse, simplemente envíe la letra para esa dirección. Para girar hacia una dirección, salida Fseguida de la letra apropiada. Por ejemplo, el siguiente resultado:

SSFESSSSSSSW

es una ruta segura para la muestra dada en la sección de entrada. Te mueves hacia el sur dos veces, miras hacia el este para mantener al ángel a la vista, luego muévete hacia el sur siete veces más y hacia el oeste una vez para ingresar a la TARDIS.

Casos de prueba

1) Puedes dar la vuelta al Ángel orientado al este para llegar a la TARDIS. A menos que te pares directamente entre ellos, se bloquean entre sí en su lugar, por lo que no importa en qué punto estés mirando en cualquier momento.

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

2) Pierdes No hay forma de superarlos. Se pueden ver hasta que te pares entre ellos. En ese punto, no puedes enfrentarlos a los dos y listo. También podría cerrar los ojos y acabar de una vez.

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

Victorioso

Se aplican las reglas de golf estándar y las lagunas , gana menos bytes. Intentaré obtener más casos de prueba pronto, pero no dudes en sugerir los tuyos mientras tanto.

Imagen y cita del Doctor Who.

Geobits
fuente
¿Podemos usar una biblioteca para encontrar una ruta a través de un gráfico?
Sparr
@Sparr Sí, pero todo lo necesario para cargar / incluir la biblioteca debe agregarse al recuento de bytes.
Geobits
2
¡Obviamente use un manipulador de vórtice!
TheDoctor
44
@TheDoctor Jack se llevó el suyo, y se puede ver que no está en ninguno de los mapas ( J).
Geobits
1
@Timmy Se puede usar cualquiera de las definiciones estándar .
Geobits

Respuestas:

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"

La entrada debe proporcionarse así:

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

Esencialmente, este enfoque se aplica para encontrar todos los estados (posición y dirección) que el Doctor puede alcanzar de forma segura, almacenando cómo llegó allí e imprimiendo el camino en caso de éxito. Las posiciones y direcciones se realizan con números complejos.

Probablemente podría guardar algunos caracteres usando la aritmética de números complejos de Sage, pero eso duraría mucho.

Primero pensé que podía salvar a seis personajes haciendo que el Doctor se volviera en una dirección específica después de llegar a la Tardis, pero me di cuenta de que esto podría dar como resultado soluciones incorrectas. También primero leí mal las reglas.

Aquí hay una versión mayormente no golfista:

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"

Casos de prueba

Caso de prueba 1:

SSSFSWWWSSSSFWEFSEFWE

Caso de prueba 2:

0

Caso de prueba de VisualMelon:

SSFWSSSSSFSWWSSWWWFWEEEEFSEFWEFSE
Wrzlprmft
fuente
1
No he probado su código, ¡pero parece que ha pegado la salida para el caso de prueba 1 dos veces! También me interesaría ver qué produce su programa si lo alimenta mi caso de prueba propuesto.
VisualMelon
@VisualMelon: Gracias por detectar y he integrado el caso de prueba.
Wrzlprmft
10

C # 1771 2034 1962 1887 1347bytes

Reescribió la comprobación de LOS bloqueante en 1 bucle, lo que lo hizo mucho más ordenado y unos 450 bytes más corto

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

Este es un programa completo que espera que la entrada termine con un EOF y se pase a STDIN. (Con suerte) imprime la ruta más corta a la TARDIS, o "0" si no existe una ruta. Utiliza una Breadth First Search de mala calidad para seguir todas las rutas posibles, luego retrocede desde la TARDIS hasta The Doctor para ensamblar la salida.

Código formateado:

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

Salida por ejemplo entrada

SFESWSSSSSSS

Salida para el caso de prueba 1)

WSWSWSSSESESE

Salida para el caso de prueba 2)

0

Presento, según lo solicitado, un nuevo caso de prueba:

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

Mis salidas de programa

SESESESESFNSSSSWW

Caso de prueba 1 de WozzeC:

EEEEFWSSSFNWWN

Caso de prueba 2 de WozzeC:

FSEEEESFWSSSSWFNWWWNFENNEES
VisualMelon
fuente
Extrañé totalmente la posibilidad de usar X = System.Console. Gracias por eso :)
WozzeC
@WozzeC es posible que desee consultar Consejos para jugar golf en código en C #
VisualMelon
Creo que el médico es atacado al inicio con su caso de prueba: S
WozzeC
@WozzeC El ángel del oeste en el sureste puede ver al ángel del este en el noroeste, por lo que The Doctor puede escapar, pero en ese punto, parece que mi solución no se da cuenta si el médico es atacado al inicio. ¿Por qué es este código tan difícil de probar?
VisualMelon
1
Lo siento, no importa. Eché de menos el pequeño detalle que no pueden mover si otro ángel está mirando.
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;}}

Derecha. Así que decidí intentarlo, y vaya, me tomó un tiempo. Se construye principalmente utilizando operadores lógicos.

  • Norte = 1 = N
  • Sur = 2 = S
  • Este = 4 = E
  • Oeste = 8 = W
  • Doctor = 6 = D
  • TARDIS = 5 = T
  • 15 =. <-Todos los espacios libres

Para evitar tener que buscar Null, etc., decidí usar un campo de [MAX_SIZE * 3] * [MAX_SIZE] * 3 y colocar el tablero de juego cerca del centro.

Las comprobaciones de bucle se realizan por dentro y por fuera hasta 50 (MAX_SIZE). Entonces algo como esto:

22222
21112
21D12
21112
22222

Cuando se encuentra un EWS o N, hago la misma verificación de su parte. Si se encuentra algo mirando a los Ángeles (No al Doctor), devuelven 15 como paso libre. Si no son atendidos, regresan de la manera que el Doctor debe enfrentar para estar a salvo. es decir, N devolvería 2 para el sur. A menos que sea NW o NE, en cuyo caso devolvería 6 (2 + 4) y 10 (2 + 8) respectivamente.

Si dos ángeles están observando al Doctor, los valores de retorno de estos serían "AND", por lo que en el ejemplo de prueba 2 las posiciones crunch 4 y 8 se convertirían en 0. Esto significa que la posición es mala y debe evitarse.

Código ampliado:

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

Resultados de la prueba

1 Ejemplo: FNSSSWNNNWSSSWSSSSENNESES

2 Ejemplo: no hay salida

Ejemplo de VisualMelon: FNSSSSSSSWNNNNNNNWSSSSSSSSSEEEE

Mi caso de prueba1: FSSENEEEFWSSFNSWWN

Mi caso de prueba2: FSEEEESFWSSSSFNWWWWNFENNFSEES

Como se puede ver, a mi doctor le encanta pavonearse como una ducha para mostrarles a los Ángeles lo divertido que es moverse. Puedo hacer que el software encuentre el camino más corto, pero lleva más tiempo y necesita más código.

Casos de prueba para ustedes

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

Otro:

E
D....
WNNN.
...E.
.WTE.
.SSE.
.....
WozzeC
fuente
1
Al código de golf le falta un espacio en un lugar que impida su compilación, pero con esa solución, ¡hago que tu byte cuente solo 1395! Es un buen trabajo hacerlo tan bajo, y es un juego perfectamente justo para que lo uses using S=System.Console;, o simplemente puedes eliminar el S por completo en tu código y ahorrar 6 bytes using System. Ahora tendré que intentar recortar mi enfoque ingenuo un poco más ...;)
VisualMelon
1
Oh, un espacio perdido, debería ocuparme de eso. Y, por supuesto, la S = ... Me dejé llevar cuando aprendí eso. :)
WozzeC
Buen trabajo para obtener la cuenta regresiva del byte;)
VisualMelon
Encontré un código que nunca se usó. Además de algunas cosas adicionales innecesarias.
WozzeC