Ich war fasziniert vom Design dieser Grafik der New York Times, in der jeder US-Bundesstaat durch ein Quadrat in einem Raster dargestellt wird. Ich fragte mich, ob sie die Quadrate von Hand platzierten oder tatsächlich eine optimale Platzierung der Quadrate (unter einer bestimmten Definition) fanden, um die Positionen der angrenzenden Zustände darzustellen.
Ihr Code wird einen kleinen Teil der Herausforderung annehmen, Quadrate optimal zu platzieren, um Zustände (oder andere beliebige zweidimensionale Formen) darzustellen. Insbesondere wird davon ausgegangen, dass wir bereits alle geografischen Zentren oder Schwerpunkte der Formen in haben ein praktisches Format, und dass die optimale Darstellung der Daten in einem Diagramm wie diesem derjenige ist, in dem der Gesamtabstand von den Schwerpunkten der Formen zu den Mittelpunkten der Quadrate, die sie darstellen, minimal ist, mit höchstens einem Quadrat in jedem mögliche Position.
Ihr Code erstellt eine Liste eindeutiger Gleitkomma-X- und -Y-Koordinatenpaare von 0,0 bis 100,0 (einschließlich) in einem beliebigen geeigneten Format und gibt die nicht negativen Ganzzahlkoordinaten der Einheitsquadrate in einem Raster aus, das für die Darstellung der Daten optimal platziert ist Ordnung bewahren. In Fällen, in denen mehrere Anordnungen von Quadraten optimal sind, können Sie eine der optimalen Anordnungen ausgeben. Es werden zwischen 1 und 100 Koordinatenpaare angegeben.
Dies ist Code Golf, der kürzeste Code gewinnt.
Beispiele:
Eingang: [(0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (1.0, 0.0)]
Das ist einfach. Die Zentren der Quadrate in unserem Raster liegen bei 0,0, 1,0, 2,0 usw., sodass diese Formen in diesem Muster bereits perfekt an den Zentren der Quadrate platziert sind:
21
03
Ihre Ausgabe sollte also genau diese Koordinaten haben, aber als ganze Zahlen in einem Format Ihrer Wahl:
[(0, 0), (1, 1), (0, 1), (1, 0)]
Eingang: [(2.0, 2.1), (2.0, 2.2), (2.1, 2.0), (2.0, 1.9), (1.9, 2.0)]
In diesem Fall befinden sich alle Formen in der Nähe der Mitte des Quadrats bei (2, 2), aber wir müssen sie wegschieben, da sich nicht zwei Quadrate an derselben Position befinden können. Durch Minimieren des Abstands vom Schwerpunkt einer Form zur Mitte des Quadrats, das sie darstellt, erhalten wir folgendes Muster:
1
402
3
So sollte Ihre Ausgabe sein [(2, 2), (2, 3), (3, 2), (2, 1), (1, 2)]
.
Testfälle:
[(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)]
Gesamtabstand von den Schwerpunkten der Formen zu den Mittelpunkten der Quadrate, die sie jeweils darstellen (bitte geben Sie mir Bescheid, wenn Sie Fehler entdecken!):
0.0
3.6
4.087011
13.243299
2.724791
1.144123
Nur zum Spaß:
Hier ist eine Darstellung der geografischen Zentren der angrenzenden Vereinigten Staaten in unserem Eingabeformat in etwa der von der Times verwendeten Größenordnung:
[(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)]
Um diese zu erhalten, habe ich die Koordinaten aus der zweiten Liste auf dieser Seite genommen und 0.4 * (125.0 - longitude)
für unsere X-Koordinate und 0.4 * (latitude - 25.0)
für unsere Y-Koordinate verwendet. So sieht das geplottet aus:
Die erste Person, die die Ausgabe ihres Codes mit den obigen Koordinaten als Eingabe verwendet, um ein Diagramm mit tatsächlichen Quadraten zu erstellen, bekommt einen Klaps auf die Rückseite!
(1, 2)
nicht sein(1, 1)
.Antworten:
Mathematica, 473 Bytes
Vor dem Golfen:
Erklärung :
Dieses Optimierungsproblem ist in Mathematica nicht schwer zu beschreiben. Eine Liste
p
von Längenpunkten gegebenn
,x[i]
undy[i]
:v=Array[{x[#],y[#]}&,n]
,f=Total[Norm/@(p-v)]
,c=Flatten[v]∈Integers&&And@@(Or@@Thread[#1!=#2]&@@@Subsets[v,{2}])
.Und
NMinimize[{f,cons},v,MaxIterations->Infinity]
wird das Ergebnis geben. Leider scheint ein solches direktes Schema zu kompliziert, um konvergieren zu können.Um das Problem der Komplexität zu umgehen, werden zwei Techniken angewendet:
If[#1==#2,1*^4,0]&
wird verwendet, um eine Kollision zwischen Punkten zu vermeiden.Wir beginnen mit einer ersten Vermutung, indem wir die Punkte abrunden. Wenn die Optimierungen einzeln durchgeführt werden, wird erwartet, dass Kollisionen aufgelöst werden, und es wird eine optimierte Anordnung hergestellt.
Die endgültige Lösung ist zumindest gut, wenn nicht optimal. (Ich glaube
:P
)Ergebnis :
Das Ergebnis von Just for fun ist unten dargestellt. Dunkelgrüne Punkte sind die Eingaben, graue Quadrate sind die Ausgaben und schwarze Linien zeigen die Verschiebungen.
Die Summe der Verschiebungen beträgt 19,4595 . Und die Lösung ist
quelle
Python 3, 877 Bytes
Dies ist keine korrekte Implementierung. Es schlägt im zweiten der "weiteren Testfälle" fehl und erzeugt eine Lösung mit einer Gesamtentfernung von 13,5325, wobei die bereitgestellte Lösung nur 13,2433 benötigt. Eine weitere Komplikation ist die Tatsache, dass meine Golf-Implementierung nicht mit der ungolften übereinstimmt, die ich zuerst geschrieben habe ...
Es hat jedoch noch niemand geantwortet, und dies ist eine zu interessante Herausforderung, als dass man sie hätte überspringen lassen können. Außerdem habe ich ein Bild aus den USA-Daten erstellt, also gibt es das.
Der Algorithmus sieht ungefähr so aus:
Ich habe absolut keinen Beweis für die Optimalität für irgendeinen Teil dieses Algorithmus, nur den starken Verdacht, dass er "ziemlich gute" Ergebnisse liefert. Ich denke, das haben wir in meinen Uni-Tagen einen "heuristischen Algorithmus" genannt ...!
Und das Ergebnis der Ausführung auf den USA-Daten (dank einer Dienstprogrammfunktion, die die Ergebnisse in SVG umwandelt):
Dies ist etwas schlimmer als der, den der ungolfed Code erzeugt hat; Der einzige sichtbare Unterschied besteht darin, dass das Quadrat ganz oben rechts im besseren weiter links liegt.
quelle
MATLAB,
316 343326 BytesDieser ist in Arbeit - er ist nicht schnell, aber er ist kurz. Es scheint die meisten Testfälle zu bestehen. Momentan läuft die nur zum Spaß eingegebene Karte, aber sie läuft noch nach 10 Minuten, also ...
Und in einem etwas besser lesbaren Format:
Es wird erwartet, dass das Eingabeformat ein MATLAB-Array ist, beispielsweise:
Welches ist ziemlich nah an dem Format in der Frage, die etwas Spielraum ermöglicht.
Die Ausgabe hat dasselbe Format wie die Eingabe. Dabei handelt es sich um ein Array, bei dem jeder angegebene Index sowohl in der Eingabe als auch in der Ausgabe demselben Punkt entspricht.
Hmm, 8 Stunden und noch läuft auf der Karte eine ... diese Lösung ist garantiert am optimalsten zu finden, aber es macht es mit brachialer Gewalt, also dauert es sehr lange.
Ich habe eine andere Lösung gefunden, die viel schneller ist, aber wie die andere Antwort nicht das Optimum in einem der Testfälle findet. Interessanterweise wird unten die Karte angezeigt, die ich für meine andere (nicht veröffentlichte) Lösung bekomme. Es erreicht eine Gesamtstrecke von 20,72.
quelle