Introducción
Tienes la desgracia de estar atrapado en un automóvil fuera de control en una carrera de obstáculos. Todas las características del automóvil no responden, salvo el sistema de dirección, que está dañado. Puede conducir en línea recta o girar a la derecha. ¿Se puede guiar el automóvil hacia la seguridad?
Mecánica
Su automóvil comienza en la esquina superior izquierda de un mapa de 8x8, y está tratando de ponerse a salvo en la esquina inferior derecha. El automóvil tiene una orientación (inicialmente a la derecha), medida en incrementos de 90 grados. El automóvil puede realizar una de dos acciones:
- Conduzca un cuadrado hacia adelante, o
- Gire 90 grados en el sentido de las agujas del reloj, luego conduzca un cuadrado hacia adelante
Tenga en cuenta que el automóvil no puede girar lo suficientemente fuerte como para realizar un giro de 180 grados en una sola casilla.
Algunas de las plazas son obstáculos. Si el automóvil entra en una casilla de obstáculo, se estrella. Se supone que todo lo que está fuera del curso 8x8 es un obstáculo, por lo que salir del curso equivale a estrellarse.
El cuadrado inferior derecho es el cuadrado seguro, que permite al automóvil escapar de la carrera de obstáculos. Se supone que la casilla inicial y la casilla segura no son obstáculos.
Tarea
Debe escribir un programa o función que tome como entrada una matriz de 8x8 (matriz, lista de listas, etc.), que representa la carrera de obstáculos. El programa devuelve o imprime un booleano, o algo similarmente verdadero. Si es posible que el automóvil llegue a la plaza segura sin chocar (es decir, si el mapa tiene solución), la salida es True
, de lo contrario, es False
.
Puntuación
Reglas de golf de código estándar: el ganador es el código con la menor cantidad de bytes.
Bonificaciones:
Si, para un mapa solucionable, su código genera una serie válida de entradas del conductor que guían el automóvil hacia el cuadrado seguro, deduzca 10 puntos porcentuales de su puntaje. Un formato de salida de ejemplo podría ser
SRSSR
(que indica Derecho, Derecho, Derecho, Derecho, Derecho). Esta salida reemplazaría laTrue
salida estándar .Si, para un mapa sin solución, la salida de su código distingue entre situaciones en las que un choque es inevitable y situaciones en las que es posible conducir por la carrera de obstáculos para siempre, deduzca 10 puntos porcentuales de su puntaje. Un resultado de ejemplo podría ser
Crash
si un choque es inevitable, oStuck
si el automóvil está atascado en la carrera de obstáculos para siempre. Estas salidas reemplazarían laFalse
salida estándar para un mapa insoluble.
Ejemplo
Si el programa recibe una matriz de 8x8 como esta:
[[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 0]]
Se interpretaría como un mapa como este, con cuadrados negros que indican obstáculos:
Y una posible solución podría ser:
Como existe una solución, el programa debe devolver / imprimir True
para este mapa. La secuencia de movimientos que se muestra aquí es SSSSRSRRRSRSSRRRSSRSSS
.
Crash
yStuck
. Están aquí por lo largos que son. Fila 2 llena, todo lo demás vacío ->Crash
. Fila 7 llena, todo lo demás vacío ->Stuck
Respuestas:
JavaScript (ES6) - 122
124148bytes162172178187190193208Muchas gracias a Optimizer y DocMax por sus útiles sugerencias sobre cómo mejorar este código:
Devuelve
true
(verdadero) para solucionable yfalse
(falso) para insoluble.Funciona solo en Firefox a partir de hoy debido a las características de JavaScript 1.7.
Tablero de prueba
fuente
D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a)
.D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})
- Probado.[[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
. Eso debería dar falso.x
comoy
ambos son globales, no puede ejecutar dos casos de prueba antes de volver a cargar la página ...x+=d?d^2?0:-1:1
conx+=d&1?0:1-d
yy+=d^1?d^3?0:-1:1
cony+=d&1&&2-d
.Python 2-123
125 133 146 148 150 154 160True
en el éxito,False
en el fracaso.Debe proporcionar información como
f(b=var_containing_board)
.Versión Lambda - 154
Devoluciones
0
(falsas) por fracaso,True
por éxito.Gracias a Will y Brandon por hacer la función más corta que la lambda. También para agregar más desplazamiento horizontal: D
¡Gracias a xnor por su excelente bit-bashing y lógica!
Nota de edición: estoy razonablemente seguro de que
b[y][x]
nunca se ejecutará cuando esté fuera de rango. Como estamos fuera del tablero, la verificación del historials in c
seráFalse
. Entonces la verificación de límites(x|y)&8
será8
. Entonces python ni siquiera verificará el último valor de==
porque los dos primeros ya son diferentes.fuente
x|y>7or
funciona, perox|y<0or
no ...0o
.C (GNU-C), 163 bytes * 0.9 = 146.7
#C (GNU-C), 186 bytes * 0.9 = 167.4Mi nueva versión usa un entero con signo en lugar de sin signo. Anteriormente tenía miedo de firmar el desplazamiento a la derecha, pero me di cuenta de que, dado que el bit de signo es el cuadrado del gol, no importa lo que ocurra después de eso.
La función toma una matriz de bits (los que representan cuadrados bloqueados) en forma de un entero de 64 bits. Los bits están ordenados de menor a mayor importancia de la misma manera que leerías un libro. Devuelve -1 por un accidente, 0 por conducir para siempre o 1 por escapar a la esquina inferior derecha.
Programa de prueba
Salida
Python convertidor de matriz a hexadecimal:
fuente
memset(&M,~1,8)
(15 caracteres) conM=~(-1ULL/255)
(14 caracteres).P(0x00fefefefefefefe);
= (Debería ser un disparo directo a la esquina superior derecha, una vuelta, directamente a la esquina. Lo mismo paraP(0x00eeeeeeeeeeeeee);
(callejón sin salida en la cuarta columna). No creo que deba asignara
inicialmente.0x7f7f7f7f7f7f7f00
. También es necesario inicializara
porque más tarde solo se modifica mediante ORing en bits adicionales, por lo que no puedo permitirme tener un conjunto de bits no deseado inicialmente.Pitón, 187
213207 caracteres, 10% de bonificación por ruta de impresión
En la entrada de prueba, encuentra una ruta ligeramente diferente:
SSSSRSRSRRSSRSSRRSRSSRSSSSS
El enfoque general es convertir primero la entrada en espacios y
o
s. Los espacios tienen un hexadecimal de20
, por lo que los cuatro bits inferiores no están configurados.o
tiene un hexadecimal de6F
, por lo que los cuatro bits bajos están todos establecidos.Se
o
coloca un borde de s alrededor del tablero para que no tengamos que preocuparnos por los malos índices.Mientras caminamos por el tablero, usamos los bits en cada mosaico para ver si se nos permite pasar cuando venimos de ese lado. De esta manera, evitamos bucles infinitos. No es suficiente tener un solo booleano por mosaico, ya que la dirección de salida depende de la dirección de entrada, por lo que los mosaicos se pueden visitar dos veces.
Luego hacemos una búsqueda recursiva de un camino seguro.
fuente
9
en lugar dew=len(b[0])+1
, etc.?p==79
conp-79
. Obtuve un error de sintaxis haciendo esto en ambos sentidos sin un espacio antes delelse
. Creo que ese truco solo funcionaif
.-~x
==x+1
pero ambos operadores unarios tienen mayor prioridad que la multiplicación, división y módulo! Entonces(d+1)%4
podría ser-~d%4
! Esto también funcionaríax-1
pero solo se usaría~-x
en su lugar.Javascript -
270 - 20% =216262 - 20% = 210 bytesDado que debería haber al menos una solución que gane ambas bonificaciones (y no conduzca a una profundidad de pila ridícula;) ...
Minified:
Expandido:
v
es una tabla hash con claves que son triples de estado(x,y,d)
correspondientes a (x, y) coordenadas y dirección de entradad
. Cada tecla tiene un valor asociado que es la cadena de movimientosS
(rectos) yR
(girar a la derecha) necesarios para alcanzar el estado representado por la tecla.El código también mantiene una pila de triples (en variable
n
) que aún no se han procesado. Inicialmente, la pila contiene solo el triple (0,0,0), correspondiente al estado en el que el automóvil se enfrenta a la derecha en la celda (0,0). En el bucle externofor( S = ... )
, la rutina verifica si quedan triples sin procesar. Si es así, se ejecuta cada triples sin procesar a través del bucle interno,n.map( ...
.El circuito interno hace cinco cosas:
K
Sin embargo, marcamos la salida FALSO como (atascada), ya que hemos encontrado al menos un bucle donde el automóvil puede continuar dando vueltas para siempre sin estrellarse.v
) y a la pila de triples sin procesar (m
) para el próximo paso del bucle externov
, su valor se establece en el valor del estado de origen (la secuencia de movimientos) másR
o enS
función del movimiento actualx
yy
son7
, el valor del estado de origen (la secuencia de movimientos tomados para alcanzar el estado de origen) se copiaS
, ya que esta secuencia de movimiento es una solución al problemaDespués de que termina el bucle interno,
n
(la pila) se reemplaza porm
(la nueva pila).Después de que termina el bucle externo (no se alcanzaron nuevos estados), la función devuelve su salida. Si se alcanzó la celda (7,7),
S
contendrá una secuencia de movimientos que conducen a esta celda, y esto se generará. Si no se alcanzó la celda,S
será la cadena vacía, y la rutina pasa a la salidaO
, que contendráK
(atascada) si y solo si se encontró un bucle, oC
(choca) si el automóvil inevitablemente chocará.fuente
Python 339 - 10% = 305 bytes
Utilicé una búsqueda recursiva de profundidad primero, que termina temprano en el éxito a través de
exit
. También imprime la ruta del éxito en forma de00001010101010101010101110100111001000
,0
por derecho,1
por derecho. La respuesta será más larga que la óptima, ya que es profunda primero. Estoy seguro de que algunas optimizaciones del algoritmo podrían hacer que la cuenta de bytes disminuya bastante.fuente
a
elfor
bucle. Tampoco necesita espacios alrededor de los operadores, por ejemplo,(v+1) % 4
->(v+1)%4
. También puede unir varias declaraciones en una línea utilizando;
si no hayif
ofor
, etc. en la línea, por ejemploc(l+"0");c(l+"1")
. Algunos otros campos de golf:x,y,v=0,0,2
,x|y>7 or x|y<0
,x==y==7
. Buena suerte :)