Я был заинтригован дизайном этой графики из New York Times, в которой каждый штат США представлен квадратом в сетке. Я задавался вопросом, помещали ли они квадраты вручную или фактически находили оптимальное расположение квадратов (согласно некоторому определению), чтобы представить положения смежных государств.
Ваш код будет выполнять небольшую часть задачи оптимального размещения квадратов для представления состояний (или других произвольных двумерных фигур). В частности, предполагается, что у нас уже есть все географические центры или центроиды фигур в удобный формат, и что оптимальным представлением данных на диаграмме, подобной этой, является тот, в котором общее расстояние от центроидов фигур до центров квадратов, которые их представляют, минимально, с максимум одним квадратом в каждом возможная позиция.
Ваш код возьмет список уникальных пар координат X и Y с плавающей точкой от 0,0 до 100,0 (включительно) в любом удобном формате и выведет неотрицательные целочисленные координаты единичных квадратов в сетке, оптимально размещенной для представления данных. Сохраняя порядок. В случаях, когда несколько расположений квадратов являются оптимальными, вы можете вывести любое из оптимальных расположений. Будет дано от 1 до 100 пар координат.
Это код гольф, самый короткий код выигрывает.
Примеры:
Входные данные: [(0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1.0, 0.0)]
Это легко. Центры квадратов в нашей сетке равны 0,0, 1,0, 2,0 и т. Д., Поэтому эти фигуры уже идеально расположены в центрах квадратов по этой схеме:
21
03
Таким образом, ваши выходные данные должны быть точно этими координатами, но в виде целых чисел в формате по вашему выбору:
[(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), но мы должны оттолкнуть их, потому что два квадрата не могут быть в одном и том же положении. Минимизация расстояния от центра тяжести фигуры до центра квадрата, который представляет ее, дает нам такую модель:
1
402
3
Так что ваш вывод должен быть [(2, 2), (2, 3), (3, 2), (2, 1), (1, 2)]
.
Тестовые случаи:
[(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)]
Общее расстояние от центроидов фигур до центров квадратов, которые представляют их в каждом случае (пожалуйста, дайте мне знать, если вы обнаружите какие-либо ошибки!):
0.0
3.6
4.087011
13.243299
2.724791
1.144123
Просто для удовольствия:
Вот представление географических центров смежных Соединенных Штатов в нашем формате ввода, примерно в масштабе, который использовала 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)]
Чтобы получить их, я взял координаты из второго списка на этой странице и использовал их 0.4 * (125.0 - longitude)
для нашей координаты X и 0.4 * (latitude - 25.0)
для нашей координаты Y. Вот как это выглядит на графике:
Первый человек, который использует выходные данные из своего кода с указанными выше координатами в качестве входных данных для создания диаграммы с реальными квадратами, получает похлопывание по спине!
(1, 2)
, а не(1, 1)
.Ответы:
Mathematica, 473 байта
Перед игрой в гольф:
Пояснение :
Эту проблему оптимизации нетрудно описать в Mathematica. Учитывая список точек
p
длиныn
,x[i]
иy[i]
:v=Array[{x[#],y[#]}&,n]
,f=Total[Norm/@(p-v)]
,c=Flatten[v]∈Integers&&And@@(Or@@Thread[#1!=#2]&@@@Subsets[v,{2}])
.И,
NMinimize[{f,cons},v,MaxIterations->Infinity]
даст результат. Но, к сожалению, такая прямолинейная схема кажется слишком сложной, чтобы сходиться.Чтобы обойти проблему сложности, приняты два метода:
If[#1==#2,1*^4,0]&
используется, чтобы избежать столкновения между точками.Мы начнем с первоначального предположения, округляя точки. Когда оптимизации выполняются одна за другой, ожидается, что конфликты будут разрешены, и будет создана оптимизированная схема.
Окончательное решение, по крайней мере, хорошо, если не оптимально. (Я верю
:P
)Результат :
Результат Just for fun показан ниже. Темно-зеленые точки - это входы, серые квадраты - это выходы, а черные линии показывают смещения.
Сумма смещений составляет 19,4595 . И решение
источник
Python 3, 877 байт
Это не правильная реализация. Он завершается неудачно во втором из «дополнительных тестовых случаев», в результате чего получается решение с общим расстоянием 13,5325, где предоставленное решение требует только 13,2433. Еще более сложным является тот факт, что моя игра в гольф не совпадает с той, которую я написал первой ...
Тем не менее, никто не ответил, и это слишком интересная задача, чтобы ускользнуть. Кроме того, у меня есть изображение, сгенерированное из данных США, так что вот оно.
Алгоритм выглядит примерно так:
У меня нет абсолютно никаких доказательств оптимальности для какой-либо части этого алгоритма, только сильное подозрение, что он даст «довольно хорошие» результаты. Я думаю, что это то, что мы называли «эвристическим алгоритмом» в мои дни ...!
И результат запуска его на данных США (благодаря служебной функции, которая превращает результаты в SVG):
Это немного хуже, чем тот, который выдает неопрятный код; единственное видимое отличие состоит в том, что крайний правый квадрат находится на один левее от лучшего.
источник
МАТЛАБ,
316 343326 байтЭто работа в процессе - она не быстрая, но короткая. Кажется, пройти большинство тестовых случаев. В настоящее время вводится только ради забавы ввод карты, но она продолжается через 10 минут, так что ...
И в несколько более читаемом формате:
Предполагается, что формат ввода будет массивом MATLAB, например:
Что довольно близко к формату в вопросе, что позволяет некоторую свободу действий.
Выходные данные имеют тот же формат, что и входные данные, массив, где любой заданный индекс соответствует одной и той же точке как на входе, так и на выходе.
Хм, 8 часов и все еще работает на карте один ... это решение гарантированно найдет самое оптимальное, но оно делает это с помощью грубой силы, поэтому занимает очень много времени.
Я придумал другое решение, которое намного быстрее, но, как и другой ответ, не находит наиболее оптимального в одном из тестовых случаев. Интересно, что карта, которую я получаю для моего другого решения (не опубликовано), показана ниже. Достигается общая дистанция 20,72.
источник