Es hora de embarcarse en una peligrosa búsqueda para derrotar a la inteligencia británica. El objetivo de este desafío es escribir el código más corto que resolverá un Nonograma.
¿Qué es un nonograma?
Las reglas son simples. Tiene una cuadrícula de cuadrados, que debe rellenarse en negro o dejarse en blanco. Al lado de cada fila de la cuadrícula se enumeran las longitudes de las corridas de cuadrados negros en esa fila. Arriba de cada columna se enumeran las longitudes de las corridas de cuadrados negros en esa columna. Tu objetivo es encontrar todos los cuadrados negros. En este tipo de rompecabezas, los números son una forma de tomografía discreta que mide cuántas líneas continuas de cuadrados rellenos hay en una fila o columna dada. Por ejemplo, una pista de "4 8 3" significaría que hay conjuntos de cuatro, ocho y tres cuadrados rellenos, en ese orden, con al menos un cuadrado en blanco entre grupos sucesivos. [ 1 ] [ 2 ]
Entonces, la solución al Nonograma anterior sería:
Detalles de implementacion
Puedes elegir representar el Nonograma como quieras y tomarlo como entrada de la forma que consideres adecuada para tu idioma. Lo mismo vale para la salida. El objetivo de este desafío es, literalmente, hacer el trabajo; si puede resolver el nonograma con cualquier salida que le dé su programa, eso es válido. Una advertencia es que no puedes usar un solucionador en línea :)
Este problema es muy desafiante desde el punto de vista algorítmico (np-complete), ya que no existe una solución completamente eficiente y, como tal, no se lo penalizará por no poder resolver los más grandes, aunque su respuesta será muy recompensada si es capaz de manejar grandes casos (ver bonificación). Como punto de referencia, mi solución funciona hasta aproximadamente 25x25 en 5-10 segundos. Para permitir flexibilidad entre diferentes idiomas, las soluciones que toman menos de 5 minutos para un nonograma de 25x25 son lo suficientemente buenas.
Puede suponer un rompecabezas en un nonograma NxN cuadrado.
Puede usar este fabricante de rompecabezas de nonogramas en línea para probar sus soluciones.
Puntuación
Por supuesto, puede usar el idioma que desee y, dado que se trata de código de golf, las entradas se ordenarán en el orden: sin accuracy -> length of code -> speed.
embargo, no se desanime por los idiomas de código de golf, las respuestas en todos los idiomas que muestran intentos de golf de una manera interesante será votado!
Prima
De hecho, aprendí sobre Nonogramas de una tarjeta de Navidad criptográfica lanzada por la inteligencia británica aquí . La primera parte fue básicamente un enorme Nonograma de 25x25. Si su solución puede resolver esto, recibirá felicitaciones :)
Para facilitarle la vida en términos de entrada de datos, he proporcionado cómo representé los datos para este rompecabezas específico para su uso gratuito. Las primeras 25 líneas son las pistas de fila, seguidas de una línea de separación '-', seguida de 25 líneas de las pistas de columnas, seguidas de una línea de separación '#', y luego una representación de la cuadrícula con las pistas cuadradas rellenas.
7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 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 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 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 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 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 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 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 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 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 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 1 0 0 0 0 1 0 0 0 0 1 0 0 0 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 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 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 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 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
Y aquí hay una versión ligeramente diferente para su conveniencia; una tupla separada por comas (fila, col) donde cada elemento es una lista de listas.
([[7, 3, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 1, 3, 1],
[1, 3, 1, 1, 6, 1, 3, 1],
[1, 3, 1, 5, 2, 1, 3, 1],
[1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[3, 3],
[1, 2, 3, 1, 1, 3, 1, 1, 2],
[1, 1, 3, 2, 1, 1],
[4, 1, 4, 2, 1, 2],
[1, 1, 1, 1, 1, 4, 1, 3],
[2, 1, 1, 1, 2, 5],
[3, 2, 2, 6, 3, 1],
[1, 9, 1, 1, 2, 1],
[2, 1, 2, 2, 3, 1],
[3, 1, 1, 1, 1, 5, 1],
[1, 2, 2, 5],
[7, 1, 2, 1, 1, 1, 3],
[1, 1, 2, 1, 2, 2, 1],
[1, 3, 1, 4, 5, 1],
[1, 3, 1, 3, 10, 2],
[1, 3, 1, 1, 6, 6],
[1, 1, 2, 1, 1, 2],
[7, 2, 1, 2, 5]],
[[7, 2, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 3, 1, 3, 1],
[1, 3, 1, 1, 5, 1, 3, 1],
[1, 3, 1, 1, 4, 1, 3, 1],
[1, 1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[1, 1, 3],
[2, 1, 2, 1, 8, 2, 1],
[2, 2, 1, 2, 1, 1, 1, 2],
[1, 7, 3, 2, 1],
[1, 2, 3, 1, 1, 1, 1, 1],
[4, 1, 1, 2, 6],
[3, 3, 1, 1, 1, 3, 1],
[1, 2, 5, 2, 2],
[2, 2, 1, 1, 1, 1, 1, 2, 1],
[1, 3, 3, 2, 1, 8, 1],
[6, 2, 1],
[7, 1, 4, 1, 1, 3],
[1, 1, 1, 1, 4],
[1, 3, 1, 3, 7, 1],
[1, 3, 1, 1, 1, 2, 1, 1, 4],
[1, 3, 1, 4, 3, 3],
[1, 1, 2, 2, 2, 6, 1],
[7, 1, 3, 2, 1, 1]])
fuente
s=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
Respuestas:
Brachylog ,
7069 bytesEsto toma una lista de dos listas (primero los indicadores de filas, luego los de columna). Cada indicador es en sí mismo una lista (para situaciones como
[3,1]
en una fila).Esta versión tarda unos 3 minutos en resolver el ejemplo 5 por 5 del desafío.
Versión mucho más eficiente, 91 bytes
Pruébalo en línea!
Esta no es la fuerza bruta completa: la única diferencia es que esta impone restricciones en los valores de las celdas de modo que el número de 1s en cada fila y columna coincida con los números dados como indicadores en la entrada. La única parte de la fuerza bruta es encontrar una cuadrícula con esas restricciones para las cuales los "bloques" de 1 coinciden con lo que se da como indicación.
Este toma alrededor de 0.05 segundos en el ejemplo 5 por 5 del desafío. Esto todavía es demasiado lento para el caso de bonificación, ya que no tengo idea de cómo expresar los bloques de unos separados por uno o más ceros en términos de restricciones.
Explicación
Explicaré a continuación la versión de 93 bytes. La única diferencia entre los dos es la llamada al predicado 3, que no existe en la versión de 70 bytes, y la numeración de los predicados (ya que hay uno menos).
Predicado principal:
Predicado 1: obliga a las filas a tener una longitud específica y que cada celda sea 0 o 1.
Predicado 2: restringir una variable para que sea 0 o 1
Predicado 3: la suma de 1s en una lista debe ser igual a la suma de los indicadores (por ejemplo, si el indicador es [3: 1], entonces la lista debe tener la suma 4)
Predicado 4: Verifique que los bloques de 1s coincidan con el indicador
Predicado 5: verdadero para bloques de 1s, falso de lo contrario
fuente
Haskell,
242 230 201 199 177 163 160 149131 bytesFinalmente por debajo de 200 bytes, crédito a @Bergi. Muchas gracias a @nimi por ayudar a casi reducir a la mitad el tamaño.
Guau. Casi a la mitad del tamaño ahora, en parte por mí, pero principalmente por @nimi.
La función mágica es
(#)
. Encuentra todas las soluciones de un nonograma dado.Esto es capaz de resolver todos los casos, pero puede ser súper lento, ya que se trata de su complejidad
O(2^(len a * len b))
. Un punto de referencia rápido reveló 86 GB asignados para un nonograma 5x5.Dato curioso: funciona para todos los nonogramas, no solo los cuadrados.
Cómo funciona:
a#b
: Dadas listas de listas de enteros que representan el número de cuadrados, generan todas las cuadrículas (map(chunk$length b).mapM id$a>>b>>[[0,1]]
) y filtran los resultados para mantener solo los válidos.g
: Dado un nonograma potencial, suma las corridas de 1 horizontalmente.fuente
m(chunk$l b)
yreplicate(l$a>>b)
import Data.Lists
es suficiente, ya que re-exportaciones de ambosData.List
yData.List.Split
.Pyth,
917271 bytesUn programa que toma la entrada de una lista de la forma
[size, [horizontal clues], [vertical clues]]
donde cada pista es una lista de enteros (las pistas vacías son la lista vacía[]
), e imprime cada solución, separada por una nueva línea, en forma de una cuadrícula binaria donde1
está sombreada y no0
está sombreada .Esta es una fuerza bruta, por lo que es más o menos
O(2^n^2)
. Comienza a tomar mucho tiempo para rompecabezas más grandes, pero resolverá cualquier tamaño arbitrario con el tiempo suficiente.Pruébalo en línea
Cómo funciona
El programa genera todos los diseños posibles al tomar el producto cartesiano repetido
[0, 1]
con una longitud igual asize^2
. Esto se divide en trozos, dando una lista para cada línea horizontal. Cada línea está codificada por longitud de recorrido, filtrada por la presencia1
y aplanada, dejando la pista para esa línea. Esto luego se verifica contra la entrada. El proceso anterior se repite para la transposición de los fragmentos, verificando las líneas verticales. Si hay un hit, cada fragmento se concatena, y los fragmentos concatenados se unen en nuevas líneas y se imprimen implícitamente, con una nueva línea final.Gracias a @ Pietu1998 por algunos consejos
fuente
=ZhZ
es igual a=hZ
, yFN
es igual aV
.Javascript (ES6),
401386333 bytesEste es un intento temprano. No es muy eficiente, pero tenía curiosidad por probar una solución usando expresiones regulares en la representación binaria de las filas y columnas.
Por ejemplo, traducirá la pista
[3,1]
a la siguiente expresión regular:En este momento, esta versión no tiene en cuenta las pistas cuadradas. Probablemente agregaré esto más tarde.
Código
Salida
La solución se muestra en formato binario. Como:
Prueba
Esta es una prueba simple en la cuadrícula de ejemplo.
fuente
Haskell, 109 bytes
Descargo de responsabilidad: esto se deriva de la respuesta de @ ThreeFx . Lo ayudé a descifrar su respuesta, pero parece haber perdido interés en incluir mis últimas mejoras sustanciales, así que las publico como una nueva respuesta.
Ejemplo de uso:
[[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]
->[[" ## "," ### ","### ","### #"," #"]]
.Fuerza bruta. Pruebe todas las combinaciones de
y
#
, divida trozos int de#
, cuente las longitudes y compárelo con la entrada.fuente
PHP,
751833 (720)753724726710691680682 bytesEstaba ansioso por construir un incremento de secuencia especializado y probar mi generador cartesiano una vez más;
pero dejó caer el cartesiano a favor de retroceder para resolver el gran rompecabezas más rápido.
$r
para sugerencias de fila, sugerencias$c
de columna y$s
sugerencias cuadradas.invalid argument supplied for foreach
si no encuentra solución.\n
y elimine los otros dos saltos de línea.descripción
1) a partir de sugerencias de fila,
genere posibles filas que satisfagan las sugerencias cuadradas
y recuerde sus recuentos para cada índice de fila.
2) retroceda sobre las combinaciones de filas:
si la combinación satisface los consejos de la columna, busque una combinación
más profunda o devuelta, o intente la siguiente posibilidad para esta fila
3) solución de impresión
El último golf tuvo un impacto severo en el rendimiento;
pero eliminé las asignaciones de perfiles para los puntos de referencia finales.
Reemplace
$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
con
if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
para deshacer el último paso de golf.
ejemplos
Para el pequeño ejemplo (
17 a 21alrededor de12876.75.3 ms), usepara el rompecabezas de navidad:
5037.845.5alrededor de 36 segundoscoloque los datos de la pregunta en un archivo
christmas.nonogram
y use este código para importar:Descompostura
fuente
$d
tiene que estar en el orden correcto paraforeach