Para obtener más información, mire este video y vaya a A276523 para ver una secuencia relacionada.
El Rompecabezas Mondrian (para un número entero n
) es el siguiente:
Encaje rectángulos no congruentes en una n*n
cuadrícula cuadrada. ¿Cuál es la diferencia más pequeña posible entre el rectángulo más grande y el más pequeño?
Para 6
, la diferencia óptima para M(6)
es 5
, y puede demostrarse así:
___________
| |S|_______|
| | | L |
| |_|_______|
| | | |
| |_____|___|
|_|_________| (fig. I)
El rectángulo más grande (L) tiene un área de 2 * 4 = 8
, y el rectángulo más pequeño (S) tiene un área de 1 * 3 = 3
. Por lo tanto, la diferencia es 8 - 3 = 5
.
Tenga en cuenta que actualmente no n > 44
se han encontrado soluciones óptimas para .
Su tarea es crear un programa que genere una cuadrícula Mondrian que contenga una solución (no óptima), dado un número entero n
.
Serás evaluado en los números del 100 al 150. Tu puntaje para cada prueba será la diferencia entre el rectángulo más grande y el más pequeño. Su puntaje total es la suma de sus puntajes para todas las pruebas de 100 a 150.
Debe presentar su salida así:
{number}
{grid}
¿Dónde number
está el puntaje (la diferencia entre el más grande y el más pequeño) y grid
es:
- Una cuerda de múltiples líneas, o
- Una lista bidimensional.
La cuadrícula DEBE mostrar claramente dónde comienza y termina un rectángulo.
Reglas:
- Su programa debe ajustarse a su respuesta.
- Su programa debe generar un valor para cualquier número entre 100 y 150 dentro de 1 hora en una computadora portátil moderna.
- Su programa debe generar la misma solución para un número entero
n
cada vez que se ejecuta el programa. - Debe proporcionar un enlace a las salidas de las 51 soluciones (usando Pastebin, Github Gist ... cualquier cosa, realmente).
- Debe tener al menos dos rectángulos en la cuadrícula cuadrada para su solución.
fuente
Respuestas:
Piet, 9625
(¡Finalmente funciona!)
La gente lo exigió, así que aquí está. Esta es una solución extremadamente ingenua (esencialmente lo mismo que los límites superiores sueltos en la página OEIS): divide cada cuadrado en solo dos rectángulos.
Esta esencia contiene los detalles en dos archivos:
?
es el indicador de entrada, seguido inmediatamente por la puntuación de salida, luego la cuadrícula.Explicación
Este programa toma un solo número
N
como entrada. Si el número es impar, la puntuación es el número; si incluso, el puntaje es el doble del número.Después de generar el puntaje, el resto del lado izquierdo del programa se gasta en llenar la pila con cinco lotes de la siguiente información:
N
)_
espacio o espacio)|
)El lado derecho del programa toma cada conjunto de cuatro valores e imprime esa parte de la cuadrícula.
fuente
C 6108
Esto utiliza una versión recursiva (realmente iterativa) de la solución mínima. En lugar de dividir el cuadrado en dos rectángulos donde uno es un poco más grande que la mitad del área, lo divide en N rectángulos. Entonces, el primer rectángulo es un poco más grande que
1/N
el área total. Luego, tomando el resto, el programa divide un rectángulo un poco más grande que1/(N-1)
el resto y así sucesivamente hasta que solo toma el resto como el último rectángulo. Los rectángulos se cortan del resto en una espiral en el sentido de las agujas del reloj, así que primero en la parte superior, luego a la derecha, etc.Dado que este es un método muy directo en lugar de una búsqueda en un espacio amplio, se ejecuta rápidamente: toma alrededor de 25 segundos (en una Raspberry Pi) para buscar 74 soluciones cada una para el conjunto de problemas dado.
Mi intención es utilizar estos resultados para informar mejor un algoritmo de búsqueda para un enfoque más sofisticado.
La salida proporciona la puntuación y un dibujo (ascii) y coordenadas para los vértices de los rectángulos. Los vértices están en el sentido de las agujas del reloj, comenzando desde la esquina superior izquierda del rectángulo en cuestión.
Desarrollado con gcc 4.9.2-10.
Resultados en https://github.com/JaySpencerAnderson/mondrian
Código:
fuente
C - 2982
Este programa implementa una búsqueda a través de un amplio conjunto de resultados. La parte importante de hacer que esta búsqueda sea práctica fue fallar temprano y / o no seguir malos caminos.
Esto genera un conjunto de rectángulos a considerar para la solución. El conjunto de rectángulos generados evita aquellos con dimensiones que no serían útiles. Por ejemplo, si el programa está tratando de encontrar la solución para un cuadrado de 128x128, dividido en 8 rectángulos, generará un rectángulo de 128x16. No generará que uno sea 120x17 porque no hay posibilidad de un rectángulo generador que tenga 8 de ancho para llenar el espacio al final de 120.
La estrategia inicial para colocar rectángulos es colocarlos en el interior del perímetro del cuadrado (función de construcción). De esa manera, el algoritmo obtiene una respuesta bastante rápida en cada esquina sobre si hay un problema con la secuencia elegida. Al colocar rectángulos, la lógica sigue observando si se desarrollan espacios de espacio demasiado estrechos para cualquier rectángulo. Una vez que el perímetro se ha poblado con éxito, la estrategia cambia para tratar de hacer coincidir el espacio restante con los rectángulos restantes (función de coincidencia).
Otra cosa que podría ser interesante es que esto implementa transacciones con reversión para las pilas de rectángulos.
Este programa no intenta encontrar el mejor ajuste posible. Se le asigna un presupuesto (64) y se cierra cuando encuentra la primera solución. Si nunca encuentra una solución, aumentamos el presupuesto (en 16) e intentamos nuevamente. El tiempo requerido (en una computadora portátil Dell con un procesador I7) varió de menos de un minuto a 48 minutos por 150 en un lado (149 en un lado tomó menos de 2 minutos). Las 51 soluciones usaron 11 rectángulos. Los puntajes de las 51 soluciones variaron de 41 a 78. Las razones por las que utilicé 11 rectángulos fueron que el puntaje era más bajo que con menos rectángulos y parecía que 12 rectángulos tomarían mucho más de la hora asignada.
Las soluciones y el código se pueden encontrar en https://github.com/JaySpencerAnderson/mondrian . Son los dos archivos my4 *.
Por cierto, si compila esto en "my4" y lo ejecuta de la siguiente manera: "./my4 -h", le dará uso. Si quiere verlo en acción trabajando lejos, intente algo como "./my4 -l 50 -n 8". Si cambia el "#if 0" a "#if 1", mostrará el espacio restante en la pantalla. Si desea cambiar esto para representar los rectángulos, busque el lugar donde el código ejecuta "gráfico (espacio, lado)" y cámbielo a "gráfico (pila de llamadas, lado)". También te sugiero que cambies el presupuesto inicial de 64 a 32 si quieres jugar con soluciones para cuadrados de aproximadamente 50 de ancho. La solución para cuadrados más pequeños tendrá una mejor puntuación con un presupuesto más pequeño.
El siguiente programa es funcional. Verifique github para obtener el código completo (con uso, comentarios, etc.).
fuente