Me intrigó el diseño de este gráfico del New York Times, en el que cada estado de EE. UU. Está representado por un cuadrado en una cuadrícula. Me preguntaba si colocaban los cuadrados a mano o si realmente encontraban una ubicación óptima de los cuadrados (bajo alguna definición) para representar las posiciones de los estados contiguos.
Su código asumirá una pequeña parte del desafío de colocar cuadrados de manera óptima para representar estados (u otras formas bidimensionales arbitrarias). Específicamente, va a suponer que ya tenemos todos los centros geográficos o centroides de las formas en un formato conveniente, y que la representación óptima de los datos en un diagrama como este es aquella en la que la distancia total desde los centroides de las formas a los centros de los cuadrados que los representan es mínima, con a lo sumo un cuadrado en cada Posible posición.
Su código tomará una lista de pares únicos de coordenadas X e Y de coma flotante de 0.0 a 100.0 (inclusive) en cualquier formato conveniente, y generará las coordenadas enteras no negativas de cuadrados unitarios en una cuadrícula colocada de manera óptima para representar los datos , preservando el orden. En los casos en que múltiples arreglos de cuadrados son óptimos, puede generar cualquiera de los arreglos óptimos. Se darán entre 1 y 100 pares de coordenadas.
Este es el código de golf, el código más corto gana.
Ejemplos:
Entrada: [(0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1.0, 0.0)]
Esta es una fácil. Los centros de los cuadrados en nuestra cuadrícula están en 0.0, 1.0, 2.0, etc. por lo que estas formas ya están perfectamente ubicadas en los centros de los cuadrados en este patrón:
21
03
Por lo tanto, su salida debe ser exactamente estas coordenadas, pero como enteros, en un formato de su elección:
[(0, 0), (1, 1), (0, 1), (1, 0)]
Entrada: [(2.0, 2.1), (2.0, 2.2), (2.1, 2.0), (2.0, 1.9), (1.9, 2.0)]
En este caso, todas las formas están cerca del centro del cuadrado en (2, 2), pero necesitamos alejarlas porque dos cuadrados no pueden estar en la misma posición. Minimizar la distancia desde el centroide de una forma al centro del cuadrado que lo representa nos da este patrón:
1
402
3
Entonces su salida debería ser [(2, 2), (2, 3), (3, 2), (2, 1), (1, 2)]
.
Casos de prueba:
[(0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1.0, 0.0)] -> [(0, 0), (1, 1), (0, 1), (1, 0)]
[(2.0, 2.1), (2.0, 2.2), (2.1, 2.0), (2.0, 1.9), (1.9, 2.0)] -> [(2, 2), (2, 3), (3, 2), (2, 1), (1, 2)]
[(94.838, 63.634), (97.533, 1.047), (71.954, 18.17), (74.493, 30.886), (19.453, 20.396), (54.752, 56.791), (79.753, 68.383), (15.794, 25.801), (81.689, 95.885), (27.528, 71.253)] -> [(95, 64), (98, 1), (72, 18), (74, 31), (19, 20), (55, 57), (80, 68), (16, 26), (82, 96), (28, 71)]
[(0.0, 0.0), (0.1, 0.0), (0.2, 0.0), (0.0, 0.1), (0.1, 0.1), (0.2, 0.1), (0.0, 0.2), (0.1, 0.2), (0.2, 0.2)] -> [(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)]
[(1.0, 0.0), (1.0, 0.1), (1.0, 0.2), (1.0, 0.3)] -> [(1, 0), (0, 0), (2, 0), (1, 1)] or [(1, 0), (2, 0), (0, 0), (1, 1)]
[(3.75, 3.75), (4.25, 4.25)] -> [(3, 4), (4, 4)] or [(4, 3), (4, 4)] or [(4, 4), (4, 5)] or [(4, 4), (5, 4)]
Distancia total desde los centroides de formas a los centros de los cuadrados que los representan en cada caso (¡avíseme si detecta algún error!):
0.0
3.6
4.087011
13.243299
2.724791
1.144123
Solo por diversión:
Aquí hay una representación de los centros geográficos de los Estados Unidos contiguos en nuestro formato de entrada, aproximadamente a la escala utilizada por el Times:
[(15.2284, 3.1114), (5.3367, 3.7096), (13.0228, 3.9575), (2.2198, 4.8797), (7.7802, 5.5992), (20.9091, 6.6488), (19.798, 5.5958), (19.1941, 5.564), (17.023, 1.4513), (16.6233, 3.0576), (4.1566, 7.7415), (14.3214, 6.0164), (15.4873, 5.9575), (12.6016, 6.8301), (10.648, 5.398), (15.8792, 5.0144), (13.2019, 2.4276), (22.3025, 8.1481), (19.2836, 5.622), (21.2767, 6.9038), (15.8354, 7.7384), (12.2782, 8.5124), (14.1328, 3.094), (13.0172, 5.3427), (6.142, 8.8211), (10.0813, 6.6157), (3.3493, 5.7322), (21.3673, 7.4722), (20.1307, 6.0763), (7.5549, 3.7626), (19.7895, 7.1817), (18.2458, 4.2232), (9.813, 8.98), (16.8825, 6.1145), (11.0023, 4.2364), (1.7753, 7.5734), (18.8806, 6.3514), (21.3775, 6.6705), (17.6417, 3.5668), (9.9087, 7.7778), (15.4598, 4.3442), (10.2685, 2.5916), (5.3326, 5.7223), (20.9335, 7.6275), (18.4588, 5.0092), (1.8198, 8.9529), (17.7508, 5.4564), (14.0024, 7.8497), (6.9789, 7.1984)]
Para obtenerlos, tomé las coordenadas de la segunda lista de esta página y las utilicé 0.4 * (125.0 - longitude)
para nuestra coordenada X y 0.4 * (latitude - 25.0)
para nuestra coordenada Y. Esto es lo que parece trazado:
¡La primera persona en usar la salida de su código con las coordenadas anteriores como entrada para crear un diagrama con cuadrados reales recibe una palmada en la parte posterior!
(1, 2)
, no(1, 1)
.Respuestas:
Mathematica, 473 bytes
Antes de jugar al golf:
Explicacion :
Este problema de optimización no es difícil de describir en Mathematica. Dada una lista de puntos
p
de longitudn
,x[i]
yy[i]
:v=Array[{x[#],y[#]}&,n]
,f=Total[Norm/@(p-v)]
,c=Flatten[v]∈Integers&&And@@(Or@@Thread[#1!=#2]&@@@Subsets[v,{2}])
.Y,
NMinimize[{f,cons},v,MaxIterations->Infinity]
dará el resultado. Pero desafortunadamente, este esquema directo parece demasiado complicado para converger.Para evitar el problema de la complejidad, se adoptan dos técnicas:
If[#1==#2,1*^4,0]&
Se utiliza para evitar colisiones entre puntos.Comenzamos desde una suposición inicial al redondear los puntos. Cuando las optimizaciones se realizan una por una, se espera que las colisiones se resuelvan y se establece una disposición optimizada.
La solución final es al menos buena, si no óptima. (Creo
:P
)Resultado :
El resultado de Solo por diversión se muestra a continuación. Los puntos verde oscuro son las entradas, los cuadrados grises son las salidas y las líneas negras muestran los desplazamientos.
La suma de los desplazamientos es 19.4595 . Y la solución es
fuente
Python 3, 877 bytes
Esto no es una implementación correcta. Falla en el segundo de los "casos de prueba adicionales", produciendo una solución con una distancia total de 13.5325, donde la solución proporcionada solo necesita 13.2433. Para complicar aún más las cosas es el hecho de que mi implementación de golf no coincide con la no golfizada que escribí primero ...
Sin embargo, nadie más ha respondido, y este es un desafío demasiado interesante para dejarlo pasar. Además, tengo una imagen generada a partir de los datos de EE. UU., Así que ahí está.
El algoritmo es algo como esto:
No tengo absolutamente ninguna prueba de optimización para ninguna parte de este algoritmo, solo una fuerte sospecha de que proporcionará resultados "bastante buenos". ¡Creo que eso es lo que llamamos un "algoritmo heurístico" en mis primeros días ...!
Y el resultado de ejecutarlo en los datos de EE. UU. (Gracias a una función de utilidad que convierte los resultados en SVG):
Esto es un poco peor que el que generó el código sin golf; La única diferencia visible es que el cuadrado superior derecho está uno más a la izquierda en el mejor.
fuente
MATLAB,
316 343326 bytesEste es un trabajo en progreso, no es rápido, pero es corto. Parece pasar la mayoría de los casos de prueba. Actualmente se está ejecutando el que solo se usa para ingresar datos divertidos del mapa, pero aún continúa después de 10 minutos, entonces ...
Y en un formato algo más legible:
Se espera que el formato de entrada sea una matriz MATLAB, como:
Lo cual está bastante cerca del formato en la pregunta, lo que permite un margen de maniobra.
La salida está en el mismo formato que la entrada, una matriz donde cualquier índice dado corresponde al mismo punto tanto en la entrada como en la salida.
Hmm, 8 horas y aún se está ejecutando en el mapa ... esta solución está garantizada para encontrar la más óptima, pero lo hace a través de la fuerza bruta, por lo que lleva mucho tiempo.
Se me ocurrió otra solución que es mucho más rápida, pero como la otra respuesta no logra encontrar la más óptima en uno de los casos de prueba. Curiosamente, el mapa que obtengo para mi otra solución (no publicado) se muestra a continuación. Alcanza una distancia total de 20.72.
fuente