Existe una variante del conocido problema de N-reinas que involucra a reinas y caballeros y se dice que es "considerablemente más difícil" 1 . La declaración del problema es la siguiente:
Debes colocar un número igual de caballeros ♞ y reinas ♛ en un tablero de ajedrez de modo que ninguna pieza ataque a ninguna otra pieza. ¿Cuál es el número máximo de piezas que puede colocar en el tablero y de cuántas maneras diferentes puede hacerlo?
En este desafío de código de golf , se le dará una entrada n entre 3 y 32 (de la manera que sea más adecuada para su idioma). Para un n dado , puede haber cero o más soluciones al problema anterior. En caso de que no haya solución, debe generar / devolver nada ( nulo , cadena vacía , falso , ...). De lo contrario, debe dar dos resultados:
- Un tablero de solución (ver más abajo) para el tamaño n donde no es posible agregar una pieza de ajedrez de reina o caballero sin tener ninguna pieza bajo ataque. Debe haber un número igual de reinas y caballeros .
- La fuente de un programa a ejecutar que no acepta entradas y proporciona (i) otra solución (o nada ) para el mismo tamaño n , en el mismo formato, así como (ii) otro programa para la próxima solución (y así sucesivamente) ...)
Tenga en cuenta que:
- La secuencia de programas nunca debe devolver la misma placa dos veces, debe cubrir todas las soluciones posibles para el problema del tamaño n y, finalmente, tiene que terminar (sin producir ninguna salida).
- Puede devolver dos valores, devolver uno e imprimir el otro, o imprimir los dos valores devueltos.
- Sin embargo , si imprime tanto la placa como el siguiente programa, no se debe considerar que la placa forma parte del siguiente programa (recomendaría imprimir la placa en comentario, o utilizar tanto la salida estándar como las secuencias de error).
- El programa como valor de retorno debe ser una cadena, no un cierre.
Formato de tablero
- Un tablero es un cuadrado de tamaño n .
- Una celda de tablero puede estar vacía, una reina o un caballero.
- Debe elegir valores distintos para cada tipo de celdas (es decir, puede usar otros símbolos que Q, N al imprimir el tablero).
- Si devuelve un tablero sin cadenas, debe ser una colección ordenada de los n 2 valores del tablero (por ejemplo, matriz, vector o lista en orden de fila / columna-mayor, ...).
Si imprime el tablero, puede imprimirlo al cuadrado o como una línea. Por ejemplo, una placa de solución de tamaño 4 se puede imprimir de la siguiente manera (no se requieren espacios; símbolos a su discreción):
Q - - - - - - - - - - - - - N -
Si lo cree así, también puede generar:
♛ · · · · · · · · · · · · · ♞ ·
... pero esto es suficiente:
Q-------------N-
No importa si recorre las celdas en un orden de fila mayor o columna mayor, porque hay soluciones simétricas. Por ejemplo, las soluciones para n = 4 son:
Q------N-------- Q----------N---- Q------------N-- Q-------------N- -Q----------N--- -Q------------N- -Q-------------N --Q---------N--- --Q----------N-- --Q------------N ---QN----------- ---Q----N------- ---Q---------N-- ---Q----------N- ---NQ----------- ----Q------N---- ----Q----------N N------Q-------- -------QN------- -------Q----N--- ---N----Q------- -------NQ------- --------Q------N N----------Q---- ----N------Q---- -----------QN--- -N----------Q--- --N---------Q--- -------N----Q--- -----------NQ--- N------------Q-- --N----------Q-- ---N---------Q-- N-------------Q- -N------------Q- ---N----------Q- -N-------------Q --N------------Q ----N----------Q --------N------Q
También puede ver las soluciones para n = 5 como matrices ; los tableros contiene #
, q
y n
símbolos, que son células vacías de diferentes tipos (véase mi respuesta a continuación). Yo cuento 2836 tablas para n = 6 , al igual que en la respuesta de Sleafar (introduje un error cuando se reduce el recuento de bytes, pero se ha resuelto ahora).
Muchas gracias a Sleafar por encontrar no uno sino dos errores en mi código.
Puntuación
El código más corto en bytes gana.
Medimos el tamaño del primer programa, el que acepta n .
1 . Queens and Knights , por Roger KW Hui (¡cuidado! Contiene una solución)
-------------------------N--------Q-
no es válida porque se pueden agregar más piezas :)Q--------N---------------N--------Q-
.Respuestas:
Groovy, 515 bytes
Pruebas
Proporcionar n como argumento de línea de comando:
La primera línea de la salida siempre es una solución como comentario (0 = vacío, 1 = reina, 2 = caballero), seguido del código en la segunda línea:
El siguiente script se puede usar para pruebas automatizadas (proporcione n como argumento nuevamente):
Porque traté de hacer la solución lo más pequeña posible, es muy lenta (ver más abajo para más detalles). Probé solo n = 4 con esta versión para ver si la quineificación funciona.
Resultados
n = 4: 40 soluciones ( formato convertido )
n = 5: 172 soluciones ( formato convertido )
n = 6: 2836 soluciones ( formato convertido )
Algoritmo
Esta es una versión no quine de la solución:
Quineification
Utilicé un enfoque muy simple aquí para mantener bajo el tamaño del código.
La variable X contiene el índice de la solución para imprimir a continuación. Y tiene una copia modificada del algoritmo anterior, que se utiliza para calcular todas las soluciones y luego seleccionar solo una de ellas, razón por la cual es tan lenta. La ventaja de esta solución es que no requiere mucho código adicional. El código almacenado en Y se ejecuta con la ayuda de Eval clase (no se requiere una quine verdadera).
El código modificado imprime la solución señalada por X , aumenta X y agrega una copia de sí mismo:
También intenté generar todas las soluciones como código para el segundo paso, pero para n = 6 estaba produciendo demasiado código para que Groovy lo manejara.
fuente
Lisp común, 737
auto-respuesta
Ejemplo
Pegue lo anterior en REPL, que devuelve un objeto de función:
Llámelo (la estrella está vinculada al último valor devuelto):
Esto imprime lo siguiente en la salida estándar:
Además, el valor devuelto por esta función es:
... que es una matriz literal. El número 5 representa las reinas, el 6 es para los caballeros y cualquier otra cosa representa una celda vacía, excepto que hay más información almacenada internamente. Si copiamos y pegamos la función devuelta a la respuesta, obtenemos una nueva función.
Y podemos llamarlo, sin argumentos:
Esta llamada devuelve una nueva solución.
#(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)
y el origen de otra función (no se muestra aquí). En caso de que la función original o la última generada no encuentre una solución, no se imprime nada y no se devuelve nada.Valores internos
Solía generar muy pocas soluciones. Ahora, propago qué celda es segura para una reina y un caballero, independientemente. Por ejemplo, aquí hay una salida para n = 5 con impresión bonita:
Cuando colocamos a la reina
Q
, las posiciones que están a un paso de distancia de esta reina aún son seguras para las reinas y se denotanq
. Del mismo modo, los caballeros a los que solo las reinas pueden llegar son seguros para otros caballeros. Los valores son bit a bit y -ed para representar los posibles movimientos y algunas celdas son accesibles por ningún tipo de pieza.Más precisamente, aquí está la secuencia de tableros que conducen a la siguiente solución (de izquierda a derecha), donde las celdas libres se restringen gradualmente con diferentes valores:
Enfoque no quine
Versión no comentada, comentada
Duplicados y errores
Mi primera solución produjo soluciones duplicadas. Para resolverlo, presenté dos contadores para reinas y caballeros. El contador para reinas (resp. Caballeros) realiza un seguimiento de la primera posición en el tablero donde existe una reina (resp. Caballero): agrego una reina (resp. Un caballero) solo en las posiciones que siguen esa posición mínima.
Esos métodos me impiden volver a visitar soluciones que ya se encontraron en iteraciones anteriores, porque itero con una posición creciente de reina (resp. Caballero).
Sin embargo, Sleafar notó que había soluciones para las que podría haber espacio para reinas y caballeros, lo que va en contra de las reglas. Durante un tiempo pensé que tenía que volver a una búsqueda normal y almacenar todas las soluciones conocidas para evitar duplicados, lo que me pareció demasiado costoso (tanto en términos de bytes como de uso de memoria).
En cambio, esto es lo que hago ahora: cuando se encuentra una placa de solución potencial, trato de agregar exactamente una reina y una caballero, sin tener en cuenta los contadores (es decir, para todas las celdas en el tablero). Si esto es posible, la placa actual es un duplicado de una anterior, y rechazo la solución.
Pruebas
Quineificación
Tenía diferentes ideas para hacer quines sucesivas. La más fácil es probablemente generar todas las soluciones primero como una lista de cadenas y escribir quines secuenciales que aparecen en esa lista en cada generación. Sin embargo, esto no parecía ser más corto que el enfoque actual. Alternativamente, traté de reescribir el código recursivo con una pila personalizada y volcar todas las variables de estado cada vez que encuentro una solución; El objetivo es que el siguiente paso se pueda procesar como una continuación del paso actual. Tal vez esto sería más adecuado para un lenguaje basado en pila. El actual es bastante simple y se basa en las variables del lector Common Lisp, que siempre son divertidas de usar.
fuente