¿Puedes bucle sin estrellarte?

14

Muchos de nosotros estamos familiarizados con el juego Tron. Usted controla un "ciclo de luz" colocado en una cuadrícula. El ciclo de luz siempre se mueve hacia adelante (aunque controlas la dirección) y deja un rastro permanente detrás de él. Si te encuentras con un sendero, ¡te estrellas!

El objetivo aquí es determinar si una ruta dada es un bucle válido, es decir, vuelve a su punto de partida sin "bloquearse". Para hacer esto, asumimos que comenzamos en el punto (0,0). Se proporciona una entrada en el formulario N2E1S2W1, con una serie de direcciones cardinales ( Nes north, Ees east, etc.), cada una seguida de la distancia para recorrer esa dirección. En este ejemplo, viajarías

N2 : North 2 to (0,2)
E1 : East 1  to (1,2)
S2 : South 2 to (1,0)
W1 : West 1  to (0,0)

Una ruta se considera válida si termina (0,0)sin visitar ninguna otra coordenada más de una vez (visita (0,0)exactamente dos veces. Una al comienzo y otra al final). Tenga en cuenta que en el ejemplo anterior, para llegar de (0,0)a (0,2), necesariamente visitar (0,1)también.

Otros ejemplos:

input        -> output
N1E1S1W1     -> true
N1E1N1E1S2W2 -> true
N1S1E1W1     -> false     // Visits (0,0) 3 times
N4E2S2W4S2E2 -> false     // Visits (0,2) twice
N3E2S3       -> false     // Does not return to (0,0)
N1S1         -> anything  //I don't care how you evaluate this case

Su salida puede ser de cualquier forma siempre que proporcione la misma salida para cualquier valor verdadero o falso.

La entrada se puede tomar como una cadena o como una lista de caracteres, ya sea en forma S1N2E3... o SNNEEE... Tampoco hay un límite estricto en el tamaño de la cuadrícula, pero suponga que la entrada no desbordará nada. Mientras el código sea fundamentalmente sólido, no es crucial manejar casos como este N99999999999999.

NOTA: Es posible evaluar los casos N1S1, E1W1, S1N1, y W1E1no obstante le gustaría. Son caminos técnicamente válidos, pero van en contra del espíritu "Tron" del desafío.

Puntuación

Este es el , por lo que gana la respuesta más corta.

Lord Farquaad
fuente
N1S1debe ser verdadero para ser coherente con sus definiciones porque alcanza (0, 0)dos veces y (0, 1)una vez, lo cual es válido según su definición.
HyperNeutrino
¿Puedo tomar Nas 1j, Eas 1, Sas -1jy Was -1?
Leaky Nun
@LeakyNun Creo que estoy de acuerdo con eso, ya que todos deberían estar más o menos haciendo algo como esto de todos modos. Solo asegúrate de especificar eso en tu respuesta.
Lord Farquaad
1
@HyperNeutrino pero desde el punto de vista de Tron, su ciclo de luz pasa por (0, 0.5) dos veces, incluso si la entrada nunca lo pondrá en ese punto. Es por eso que creo que uno tiene una salida flexible (aunque para la mayoría de los idiomas será más fácil volver verdadero)
Value Ink
1
@steenbergh (0,0) no está en la esquina, por lo que puede ir debajo o a la izquierda; incluso los dos si te sientes loco! Además, no hay un límite estricto en el tamaño de la cuadrícula, pero suponga que la entrada no desbordará nada. Mientras el código sea fundamentalmente sólido, no me importa si no puede manejar entradas comoN99999999999999
Lord Farquaad

Respuestas:

6

JavaScript, 247 200 bytes

n=s=>{r=s.match(/\w\d+/g)
x=y=z=0
e=""
for(d of r){a=d[0]
b=d.slice(1)
while(b--){
y+=a=="N"
y-=a=="S"
x+=a=="E"
x-=a=="W"
p=[x,y]+";"
if(~e.indexOf(p))if(!x&!y)z++
else return 0
e+=p}}return!x&!y&!z}

nes una función de cadena de entrada sque devuelve 1verdadero y 0falso

Aquí hay una versión sin golf para referencia / explicación:

function n(s)
{
    var dir = s.match(/\w\d+/g);
    var x = y = z = 0;
    var been = "";
    for (d of dir)
    {
        var a = d[0];
        var b = 1*d.substring(1);
        while(b-- > 0)
        {
            if (a == "N") y++;
            if (a == "S") y--;
            if (a == "E") x++;
            if (a == "W") x--;
            var pt = [x,y] + ";";
            if (~been.indexOf(pt))
                if (x==0 && y==0)
                    z++;
                else
                    return false;
            been += pt;
        }
    }
    return (x == 0 && y==0 && z == 0);
}

n=s=>{r=s.match(/\w\d+/g)
x=y=z=0
e=""
for(d of r){a=d[0]
b=d.slice(1)
while(b--){
y+=a=="N"
y-=a=="S"
x+=a=="E"
x-=a=="W"
p=[x,y]+";"
if(~e.indexOf(p))if(!x&!y)z++
else return 0
e+=p}}return!x&!y&!z}

console.log(n("N1E1S1W1"))
console.log(n("N1E1N1E1S2W2"))
console.log(n("N1S1E1W1"))
console.log(n("N4E2S2W4S2E2"))
console.log(n("N3E2S3"))

WaffleCohn
fuente
no lo noté, gracias
WaffleCohn
Parece que containsno es una función en ningún dialecto de javascript. ¿Podría especificar el dialecto?
Monja goteante
Solo estaba usando la consola de Chrome para probar, funciona perfectamente allí
WaffleCohn
En realidad, también funciona en mi consola Chrome ... pero ¿tal vez considerarías cambiarlo a una respuesta más universal?
Leaky Nun
5

Python 3 , 236 161 150 bytes

import re
p=0
a=[]
for i in''.join(s[0]*int(s[1:])for s in re.findall(r".\d+",input())):p+=1j**"NESW".find(i);a+=[p]
print(len({*a})-len(a)==0==a[-1])

Pruébalo en línea!

-75 bytes gracias a Leaky Nun
-11 bytes gracias a Leaky Nun O, si se nos permite tomar la entrada como una lista de números complejos decodificados de longitud de ejecución:

Python 2 , 85 73 bytes

c=0;k=[]
for i in input():c+=i;k+=[c]
print(k[-1]==0==len(set(k))-len(k))

Pruébalo en línea!

-12 bytes gracias al Sr. Xcoder / -9 bytes gracias a Leaky Nun (fusionada en una edición)

Esto me parece demasiado largo jajaja

Hiperneutrino
fuente
3
Mientras sea más corta que 10 veces la solución Pyth, no es demasiado larga.
Leaky Nun
@LeakyNun lol está bien: P
HyperNeutrino
161 bytes
Leaky Nun
@LeakyNun oh, qué bueno. veo demasiado tiempo, como dije: P
HyperNeutrino
76 bytes
Leaky Nun
3

Jalea , 14 12 bytes

Œṙ+\µQ⁼ȧṛ/¬$

Esta es mi primera vez jugando al golf en Jelly. Las sugerencias son bienvenidas.

La entrada es como una matriz de [direction, distance]pares, donde la dirección se da como un número complejo.

Explicación:

Œṙ+\µÇȧṛ/¬$   Main link. Argument: n     = [[i, 3], [1, 2], [-i, 3]]
Œṙ            Run-length decode          = [i, i, i, 1, 1, -i, -i, -i]
  +\          Cumulative sum             = [i, 2i, 3i, 3i+1, 3i+2, 2i+2, i+2, i]
    µ         Begin a new monadic chain
     Q        Remove duplicates          = [i, 2i, 3i, 3i+1, 3i+2, 2i+2, i+2]
      ⁼       Equal to original?         = 0
           $  Make a monadic link:
        ṛ/      Reduce by right argument   = i
                (Gets the last element)
          ¬     Logical NOT:               = 0
       ȧ      Logical AND the two values = 0
Fruta Esolanging
fuente
Debería fallar el último caso.
Leaky Nun
0

Retina , 86 bytes

\d+
$*
1(1*)
$1
+`(.)1
$1$1
.
 $`$&¶
%O`.
+`NS|E(.*)W
$1
M`\w$|(?m)(^.+$)(?s).+^\1$
^0

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

\d+
$*

Convierte los números a unarios.

1(1*)
$1
+`(.)1
$1$1

Run-length decodifica las letras. N111necesita convertirse en NNN, por lo que se resta uno de cada número unario y luego cada 1 duplica la letra anterior.

.
 $`$&¶

Genere todos los prefijos (es decir, puntos en la ruta) como líneas separadas. Se antepone un espacio para evitar problemas con las líneas vacías.

%O`.
+`NS|E(.*)W
$1

Ordene todas las letras de cada línea en orden y luego elimine los pares coincidentes. Terminamos con un código único para cualquier punto dado en la cuadrícula.

M`\w$|(?m)(^.+$)(?s).+^\1$

Verifique una de dos cosas: a) el último punto no termina en un espacio (es decir, el bucle no se cerró), o dos puntos duplicados en la ruta. Si la ruta es válida, todas las comprobaciones fallan y el resultado es cero.

^0

Invierte el resultado.

Neil
fuente
0

Perl, 140

Funciona con entrada de cadena. Quizás pueda acortar con array, pero lo dudo. Feliz por cualquier ayuda de golf :)

sub w{$i=$_[0];%d=(E,[0],S,[1,-1],W,[0,-1]);$i=~s/(.)(.)/($d,$o)=(@{$d{$1}},1,1);for(1..$2){$s[$d]+=$o;$r+=$d{"@s"}++}/eg;!($s[0]+$s[1]+$r)}
bytepusher
fuente