Martin Ender recientemente alcanzó los 100K, y ha creado algunos lenguajes asombrosos . Vamos a divertirnos un poco con uno de ellos, Hexagony (y un poco de expresión regular para Retina )
Como breve descripción general, debe escribir un programa que ingrese una cuadrícula de Hexagony y determine si hay una ruta en esa cuadrícula que coincida con una cadena de texto
Generando
Hexagony genera hexágonos a partir de una cadena de texto mediante los siguientes pasos:
- Calcule el tamaño mínimo del hexágono (tome la longitud de la cuerda y redondee al número hexadecimal más cercano )
- Envolviendo el texto en un hexágono del tamaño anterior
- Llenar las ubicaciones restantes con
.
.
Por ejemplo, la cadena de texto abcdefghijklm
requiere un hexágono de longitud lateral 3 y, por lo tanto, se convierte en:
a b c
d e f g
h i j k l
m . . .
. . .
Ahora, observe que hay 6 direcciones posibles que puede viajar en un hexágono. Por ejemplo, en el hexágono anterior, e
está adyacente a abfjid
.
Envase
Además, en Hexagony, los hexágonos envuelven:
. . . . . a . . . . f . . a . .
a b c d e . . b . . . . g . . . b . . f
. . . . . . g . . c . . . . h . . a . c . . g .
. . . . . . . . h . . d . . . . u . . b . . d . . h . .
f g h i j k . i . . e . . j . . c . e . . i . .
. . . . . . j . . f k . . d . . . j . .
. . . . . k . . . . e . . k . .
Si observa el segundo y cuarto ejemplo, observe cómo a
y k
están en los mismos lugares, a pesar del hecho de que está envolviendo en diferentes direcciones. Debido a este hecho, estos puntos son solo adyacentes a otros 5 lugares .
Para aclarar esto:
a b c d
e f g h i
j k l m n o
p q r s t u v
w x y z A B
C D E F G
H I J K
- Los bordes se envuelven a su vecino opuesto (
b->I
yG->j
). - Las esquinas superior / inferior se envuelven en la esquina central opuesta y arriba / abajo (
d->K,p
yH->a,v
). - Las esquinas centrales se envuelven en las esquinas superior e inferior (
v->a,H
)
Caminos
Una ruta para ser una secuencia de ubicaciones adyacentes sin volver a la misma ubicación.
a b c
d e f g
h i f k l
m . . .
. . .
En el hexágono anterior, aefkgm
es una ruta válida. Sin embargo, abfd
no es una ruta válida ( f
y d
no es adyacente), y abea
no es válida (vuelve a la a
ubicación).
Podemos usar estas rutas para hacer coincidir el texto (como regex) . Un carácter alfanumérico coincide con sí mismo (y solo con él mismo), y un .
coincide con cualquier carácter. Por ejemplo, la ruta aej..lgm
se correspondería aej..lgm
, aejAAlgm
, aeja.lgm
, o aej^%gm
.
De entrada y salida
Su programa debe tomar dos cadenas (en cualquier orden). La primera cadena no estará vacía y constará solo de caracteres alfanuméricos [a-zA-Z0-9]
. Esto representará el hexágono en el que está operando. La segunda cadena consistirá en caracteres imprimibles.
Debe devolver un valor verdadero si hay una ruta en el hexágono que coincida con la cadena de texto dada, de lo contrario, un valor falso.
Casos de prueba
Verdad:
"a","a"
"ab","a"
"ab","b"
"ab","ba"
"ab","aba"
"ab","&"
"ab","#7.J!"
"ab","aaaaaa"
"ab","bgjneta"
"ab","cebtmaa"
"abcdefg","dfabcg"
"AbCDeFG","GCbAeFD"
"aaaabbb","aaababb"
"abcdefghijklmnopqrs","alq"
"abcdefghijklmnopqrs","aqnmiedh"
"abcdefghijklmnopqrs","adhcgkorbefjimnqlps"
"11122233344455","12341345123245"
"abcdefgh","h%a"
"abcdefghijklm","a)(@#.*b"
"abcdefghijklm","a)(@#.*i"
"abcdefghij","ja"
"abcdefghijklmno","kgfeia"
"abcdefghijklmno","mmmmmiea"
"abcdefghijklmno","mmmmmlae"
"abcdefghijklmno","ja"
"abcdefghijklmnopqrs","eijfbadhmnokgcsrql"
Falsy
"a","b"
"a","%"
"a","."
"a","aa"
"a","a."
"ab","#7.J!*"
"ab","aaaaaaa"
"ab","aaaabaaa"
"ab","123456"
"abcdefg","bfgedac"
"abcdefg","gecafdb"
"abcdefg","GCbaeFD"
"aaaabbb","aaaaabb"
"abcdefghijklmnopqrs","aqrcgf"
"abcdefghijklmnopqrs","adhlcgknbeifjm"
"abcdefghijklmnopqrs","ja"
"abcdefghijklm","a)(@#.*&"
"abcdefghijklmno","a)(@bfeijk"
"abcdefghijklmno","kgfeic"
"abcdefghijklmno","mmmmmmiea"
Este es un código de golf , así que haga sus respuestas lo más cortas posible en su idioma favorito.
fuente
Respuestas:
Retina , 744 bytes
Lo siento amigos, no Hexagony esta vez ...
El recuento de bytes asume la codificación ISO 8859-1.
Espera la cadena objetivo en la primera línea y el hexágono en la segunda línea de la entrada. Impresiones
0
o en1
consecuencia.Pruébalo en línea! (La primera línea habilita un conjunto de pruebas, donde cada línea es un caso de prueba, que se utiliza
¦
para la separación en lugar de un salto de línea).La forma correcta de resolver este desafío es con una expresión regular, por supuesto. ;) Y si no fuera por el hecho de que este desafío también involucra el procedimiento de desarrollo del hexágono , esta respuesta en realidad consistiría en nada más que una simple expresión regular de ~ 600 bytes.
Esto todavía no está muy optimizado, pero estoy bastante contento con el resultado (mi primera versión de trabajo, después de eliminar los grupos con nombre y otras cosas necesarias para la cordura, era de alrededor de 1000 bytes). Creo que podría ahorrar unos 10 bytes intercambiando el orden de la cadena y el hexágono, pero requeriría una reescritura completa de la expresión regular al final, lo que no estoy sintiendo en este momento. También hay un ahorro de 2 bytes al omitir la
G
etapa, pero ralentiza la solución considerablemente, por lo que esperaré haciendo ese cambio hasta que esté seguro de haber jugado al golf tan bien como pueda.Explicación
La parte principal de esta solución hace un uso extensivo de los grupos de equilibrio , por lo que le recomiendo leerlos, si desea entender cómo funciona esto en detalle (no lo culparé si no lo hace ...).
La primera parte de la solución (es decir, todo excepto las dos últimas líneas) es una versión modificada de mi respuesta a Desplegar el código fuente de Hexagony . Construye el hexágono, mientras deja intacta la cadena objetivo (y en realidad construye el hexágono antes de la cadena objetivo). He realizado algunos cambios en el código anterior para guardar bytes:
×
lugar de un espacio para que no entre en conflicto con espacios potenciales en la entrada._
en cambio.
, de modo que las celdas de la cuadrícula se pueden identificar de forma fiable como caracteres de texto.Aquí hay un ejemplo. Para el siguiente caso de prueba:
Obtenemos:
Compare esto con el diseño habitual del hexágono:
Podemos ver que los vecinos ahora son todos los 8 vecinos habituales de Moore, excepto los vecinos del noroeste y sureste. Por lo tanto, debemos verificar la adyacencia horizontal, vertical y sur-oeste / noreste (bueno, y luego están los bordes de envoltura). El uso de este diseño más compacto también tiene la ventaja de que podremos usarlos
××
al final para determinar el tamaño del hexágono sobre la marcha cuando lo necesitemos.Después de construir este formulario, hacemos un cambio más en toda la cadena:
Esto reemplaza los dígitos con las letras ASCII extendidas
Dado que se reemplazan tanto en el hexágono como en la cadena objetivo, esto no afectará si la cadena coincide o no. Además, dado que son letras
\w
y\b
aún las identifican como celdas hexagonales. El beneficio de hacer esta sustitución es que ahora podemos usar\D
en la próxima expresión regular para que coincida con cualquier carácter (específicamente, saltos de línea, así como caracteres sin salto de línea). No podemos usar las
opción para lograr eso, porque necesitaremos.
hacer coincidir los caracteres sin salto de línea en varios lugares.Ahora el último bit: determinar si alguna ruta coincide con nuestra cadena dada. Esto se hace con una sola expresión monstruosa. Te preguntarás por qué?!?! Bueno, esto es fundamentalmente un problema de retroceso: comienzas en algún lugar e intentas un camino siempre que coincida con la cadena, y una vez que no lo haces, retrocedes e intentas con un vecino diferente del último personaje que funcionó. La única cosaque obtienes gratis cuando trabajas con regex es un retroceso. Eso es literalmente lo único que hace el motor regex. Entonces, si solo encontramos una manera de describir una ruta válida (que es lo suficientemente complicada para este tipo de problema, pero definitivamente posible con grupos de equilibrio), entonces el motor de expresiones regulares resolverá encontrar esa ruta entre todos los posibles para nosotros. Ciertamente sería posible implementar la búsqueda manualmente con múltiples etapas ( y lo he hecho en el pasado ), pero dudo que sea más corto en este caso particular.
Un problema con la implementación de esto con una expresión regular es que no podemos tejer arbitrariamente el cursor del motor de expresión regular hacia adelante y hacia atrás a través de la cadena durante el retroceso (que necesitaríamos ya que la ruta podría subir o bajar). Entonces, en cambio, hacemos un seguimiento de nuestro propio "cursor" en un grupo de captura y lo actualizamos en cada paso (podemos movernos temporalmente a la posición del cursor con una búsqueda). Esto también nos permite almacenar todas las posiciones pasadas que usaremos para verificar que no hayamos visitado la posición actual antes.
Vamos a por ello. Aquí hay una versión un poco más sensata de la expresión regular, con grupos con nombre, sangría, un orden menos aleatorio de vecinos y algunos comentarios:
Espero que la idea general sea más o menos clara a partir de esto. Como ejemplo de cómo funciona uno de esos movimientos a lo largo del camino, veamos el bit que mueve el cursor hacia el sur:
Recuerde que las retrospectivas deben leerse de derecha a izquierda (o de abajo hacia arriba), porque ese es el orden en que se ejecutan:
Tenga en cuenta que no es necesario poner un ancla frente al
\k<pos>
para asegurarse de que esto realmente llegue al comienzo de la cadena.<pos>
siempre comienza con una cantidad×
que no se puede encontrar en ningún otro lugar, por lo que esto ya actúa como un ancla implícita.No quiero hinchar esta publicación más de lo necesario, por lo que no entraré en los otros 11 casos en detalle, pero en principio todos funcionan de manera similar. Verificamos que
<next>
se puede encontrar en alguna dirección específica (admisible) desde la posición del cursor anterior con la ayuda de grupos de equilibrio, y luego almacenamos la cadena hasta esa coincidencia como la nueva posición del cursor<pos>
.fuente
Python 3,
990943770709 bytesPrimera respuesta, yay!
EDITAR: Lista de adyacencia de golf. Ahora uso una fórmula ligeramente diferente
EDIT 2: Se eliminó la pelusa innecesaria, se jugó mucho más.
EDITAR 3: acorté el código para la conversión del índice en la lista a las coordenadas, golfé algunas cosas más.
La mayoría de los bytes se relaciona con la creación de la lista de adyacencia (tiene el mayor potencial para jugar golf). A partir de entonces, es una simple cuestión de forzar a la solución (lo que podría hacer en menos bytes).
Golfizado:
Sin golfista con explicación:
¡Tan cerca de Retina! :(Yay, vencer a Retina!fuente
Javascript (ES6),
511500496 bytesUngolfed y comentó
Casos de prueba
El fragmento a continuación recorrerá todos los casos de prueba de verdad y falsedad.
Mostrar fragmento de código
fuente