Fiquei intrigado com o design deste gráfico do New York Times, no qual cada estado dos EUA é representado por um quadrado em uma grade. Gostaria de saber se eles colocaram os quadrados à mão ou realmente encontraram uma colocação ótima de quadrados (sob alguma definição) para representar as posições dos estados contíguos.
Seu código assumirá uma pequena parte do desafio de colocar quadrados de maneira ideal para representar estados (ou outras formas bidimensionais arbitrárias). Especificamente, ele assumirá que já temos todos os centros geográficos ou centróides das formas em um formato conveniente, e que a representação ideal dos dados em um diagrama como esse é aquela em que a distância total dos centróides das formas aos centros dos quadrados que os representam é mínima, com no máximo um quadrado em cada posição possível.
Seu código fará uma lista de pares exclusivos de coordenadas X e Y de ponto flutuante de 0,0 a 100,0 (inclusive) em qualquer formato conveniente e produzirá as coordenadas inteiras não negativas dos quadrados da unidade em uma grade posicionada de maneira ideal para representar os dados , preservando a ordem. Nos casos em que vários arranjos de quadrados são ótimos, você pode produzir qualquer um dos arranjos ótimos. Serão dados entre 1 e 100 pares de coordenadas.
Este é o código de golfe, o código mais curto vence.
Exemplos:
Entrada: [(0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1.0, 0.0)]
Este é fácil. Os centros dos quadrados em nossa grade estão em 0,0, 1,0, 2,0, etc., portanto, essas formas já estão perfeitamente posicionadas nos centros de quadrados neste padrão:
21
03
Portanto, sua saída deve ser exatamente essas coordenadas, mas como números inteiros, em um formato de sua escolha:
[(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)]
Nesse caso, todas as formas estão próximas do centro do quadrado em (2, 2), mas precisamos afastá-las porque dois quadrados não podem estar na mesma posição. Minimizar a distância do centróide de uma forma ao centro do quadrado que a representa nos dá este padrão:
1
402
3
Portanto, sua saída deve ser [(2, 2), (2, 3), (3, 2), (2, 1), (1, 2)]
.
Casos de teste:
[(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)]
Distância total entre os centróides de formas e os centros dos quadrados que os representam em cada caso (entre em contato se detectar algum erro!):
0.0
3.6
4.087011
13.243299
2.724791
1.144123
Apenas por diversão:
Aqui está uma representação dos centros geográficos dos Estados Unidos contíguos em nosso formato de entrada, aproximadamente na escala que o Times usou:
[(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 obtê-las, peguei as coordenadas da segunda lista nesta página e usei 0.4 * (125.0 - longitude)
para nossa coordenada X e 0.4 * (latitude - 25.0)
nossa coordenada Y. Aqui está o que parece plotado:
A primeira pessoa a usar a saída de seu código com as coordenadas acima como entrada para criar um diagrama com quadrados reais recebe um tapinha nas costas!
(1, 2)
, não(1, 1)
.Respostas:
Mathematica, 473 bytes
Antes de jogar golfe:
Explicação :
Esse problema de otimização não é difícil de descrever no Mathematica. Dada uma lista de pontos
p
de comprimenton
,x[i]
ey[i]
:v=Array[{x[#],y[#]}&,n]
,f=Total[Norm/@(p-v)]
,c=Flatten[v]∈Integers&&And@@(Or@@Thread[#1!=#2]&@@@Subsets[v,{2}])
.E,
NMinimize[{f,cons},v,MaxIterations->Infinity]
vai dar o resultado. Infelizmente, porém, esse esquema simples parece muito complicado para convergir.Para contornar o problema da complexidade, duas técnicas são adotadas:
If[#1==#2,1*^4,0]&
é usada para evitar colisões entre pontos.Começamos com um palpite inicial, arredondando os pontos. Quando as otimizações são feitas uma a uma, espera-se que as colisões sejam resolvidas e um arranjo otimizado é estabelecido.
A solução final é pelo menos boa, se não ótima. (Eu acredito
:P
)Resultado :
O resultado de Apenas por diversão é mostrado abaixo. Pontos verdes escuros são as entradas, quadrados cinza são as saídas e linhas pretas mostram os deslocamentos.
A soma dos deslocamentos é 19.4595 . E a solução é
fonte
Python 3, 877 bytes
Isto não é uma implementação correta. Ele falha no segundo dos "outros casos de teste", produzindo uma solução com uma distância total de 13,5325, onde a solução fornecida precisa apenas de 13,2433. Para complicar ainda mais, o fato de minha implementação de golfe não corresponder à não-golfada que escrevi primeiro ...
No entanto, ninguém mais respondeu, e este é um desafio muito interessante para deixar passar. Além disso, tenho uma imagem gerada a partir dos dados dos EUA, então é isso.
O algoritmo é algo como isto:
Não tenho absolutamente nenhuma prova de otimização para qualquer parte desse algoritmo, apenas uma forte suspeita de que ele fornecerá resultados "muito bons". Eu acho que é isso que chamamos de "algoritmo heurístico" nos meus dias de uni ...!
E o resultado da execução nos dados dos EUA (graças a uma função de utilitário que transforma os resultados em SVG):
Isso é um pouco pior do que o código não destruído produzido; a única diferença visível é que o quadrado superior direito está um mais à esquerda no melhor.
fonte
MATLAB,
316 343326 bytesEste é um trabalho em andamento - não é rápido, mas é curto. Parece passar na maioria dos casos de teste. Atualmente, a única entrada divertida do mapa está em execução, mas continua em 10 minutos, então ...
E em um formato um pouco mais legível:
Espera-se que o formato de entrada seja um array MATLAB, como:
O que é bem parecido com o formato da pergunta, que permite alguma margem de manobra.
A saída está no mesmo formato que a entrada, uma matriz em que qualquer índice corresponde ao mesmo ponto na entrada e na saída.
Hmm, 8 horas e ainda em execução no mapa 1 ... esta solução é garantida para encontrar o melhor, mas o faz por força bruta, por isso leva muito tempo.
Eu vim com outra solução que é muito mais rápida, mas como a outra resposta não consegue encontrar o melhor em um dos casos de teste. Curiosamente, o mapa que recebo para minha outra solução (não publicada) é mostrado abaixo. Atinge uma distância total de 20,72.
fonte