चौकोर खूंटे में चौकोर खूंटे लगाना


20

मुझे न्यूयॉर्क टाइम्स के इस ग्राफिक के डिजाइन से इंटिग्रेट किया गया था, जिसमें प्रत्येक अमेरिकी राज्य को एक ग्रिड में एक वर्ग द्वारा दर्शाया गया है। मुझे आश्चर्य हुआ कि क्या उन्होंने वर्गों को हाथ से रखा था या वास्तव में वर्गों के अनुकूल स्थान (कुछ परिभाषा के तहत) को सन्निहित राज्यों की स्थिति का प्रतिनिधित्व करने के लिए मिला था।

गन बैकग्राउंड चेक ग्राफिक न्यूयॉर्क टाइम्स से

आपका कोड राज्यों (या अन्य मनमानी-आयामी आकृतियों) का प्रतिनिधित्व करने के लिए वर्गों को बेहतर ढंग से रखने की चुनौती का एक छोटा सा हिस्सा लेने जा रहा है। विशेष रूप से, यह मानने वाला है कि हमारे पास पहले से ही सभी भौगोलिक केंद्र या आकृतियों के केन्द्रक हैं। एक सुविधाजनक प्रारूप, और यह है कि इस तरह से आरेख में डेटा का इष्टतम प्रतिनिधित्व वह है जिसमें आकृतियों के केन्द्रक से लेकर वर्गों के केंद्रों तक कुल दूरी है जो उनका प्रतिनिधित्व करते हैं, न्यूनतम है, जिसमें प्रत्येक में सबसे अधिक एक वर्ग है। संभव स्थिति।

आपका कोड किसी भी सुविधाजनक प्रारूप में फ़्लोटिंग-पॉइंट 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

सिर्फ मनोरंजन के लिए:

यहाँ हमारे इनपुट प्रारूप में सन्निहित संयुक्त राज्य अमेरिका के भौगोलिक केंद्रों का प्रतिनिधित्व है, जो कि टाइम्स द्वारा प्रयुक्त पैमाने पर है:

[(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)
टिम पेडरिक

अच्छी पकड़, धन्यवाद!
ल्यूक

क्या आप प्रत्येक परीक्षण मामले में सभी दूरियों की कुल संख्या को भी पोस्ट कर सकते हैं? यह निश्चित रूप से एक समस्या है, और यह हमें सत्यापित करने की अनुमति देगा कि क्या वैकल्पिक समाधान वास्तव में भी इष्टतम है।
त्रुटिपूर्ण

पुनश्च: क्या आपने वास्तव में परीक्षण किया है कि दिया गया नक्शा वास्तविक रूप से आपकी अनुकूलन समस्या का एक वैध परिणाम है? क्योंकि सहज रूप से मुझे नहीं लगता कि यह है।
flawr

मैं कुल दूरी जोड़ सकता हूं। टाइम्स द्वारा उपयोग किया जाने वाला मानचित्र लगभग निश्चित रूप से इष्टतम नहीं है।
ल्यूक

जवाबों:


3

गणितज्ञ, 473 बाइट्स

f@p_:=(s=Flatten@Round@p;v=Array[{x@#,y@#}&,n=Length@p];
  Do[w=Flatten[{g@#,h@#}&/@(b=Flatten@Position[p,x_/;Norm[x-p[[i]]]<=2,{1}])];f=Total[Norm/@(p-v)]+Total[If[#1==#2,1*^4,0]&@@@v~Subsets~{2}]/.Flatten[{x@#->g@#,y@#->h@#}&@@@w]/.Thread[Flatten@v->s];
    c=w∈Integers&&And@@MapThread[Max[#-2,0]<=#2<=Min[#+2,100]&,{Flatten@p[[b]],w}];s=Flatten@ReplacePart[s~Partition~2,Thread[b->Partition[w/.Last@Quiet@NMinimize[{f,c},w,MaxIterations->300],2]]]
    ,{i,n}]~Do~{2};s~Partition~2)

गोल्फ से पहले:

f[p_]:=(n=Length@p;s=Flatten@Round@p;v=Array[{x[#],y[#]}&,n];
  Do[
    v2=Flatten[{x2[#],y2[#]}&/@(b=Flatten@Position[p,x_/;Norm[x-p[[i]]]<=2,{1}])];
    f2=Total[Norm/@(p-v)]+Total[If[#1==#2,1*^4,0]&@@@Subsets[v,{2}]]/.Flatten[{x[#]->x2[#],y[#]->y2[#]}&@@@v2]/.Thread[Flatten@v->s];
    c2=v2∈Integers&&And@@MapThread[Max[#-2,0]<=#2<=Min[#+2,100]&,{Flatten@p[[b]],v2}];
    s=Flatten@ReplacePart[s~Partition~2,Thread[b->Partition[v2/.Last@Quiet@NMinimize[{f2,c2},v2,MaxIterations->300],2]]];
    ,{i,n}]~Do~{2};
  s~Partition~2)

स्पष्टीकरण :

इस अनुकूलन समस्या का गणित में वर्णन करना मुश्किल नहीं है। 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)


परिणाम :

जस्ट फॉर फन का परिणाम नीचे दिखाया गया है। गहरे हरे बिंदु इनपुट हैं, ग्रे वर्ग आउटपुट हैं, और काली रेखाएं विस्थापन को दर्शाती हैं।

यहां छवि विवरण दर्ज करें

विस्थापन का योग 19.4595 है । और समाधान है

{{15,3},{5,4},{13,4},{2,5},{8,6},{21,6},{20,5},{19,5},{17,1},{17,3},{4,8},{14,6},{15,6},{13,7},{11,5},{16,5},{13,2},{22,8},{19,6},{21,7},{16,8},{12,9},{14,3},{13,5},{6,9},{10,7},{3,6},{22,7},{20,6},{8,4},{20,7},{18,4},{10,9},{17,6},{11,4},{2,8},{19,7},{22,6},{18,3},{10,8},{15,4},{10,3},{5,6},{21,8},{18,5},{2,9},{18,6},{14,8},{7,7}}

हा! मैं तो जैसे पिछले एक चित्र बनाने के बारे में सोच रहा था। बहुत बढ़िया।
टिम पैडरिक

अच्छा कार्य। सहज रूप से, अमेरिका के नक्शे के लिए आपका समाधान मेरे लिए इष्टतम लगता है।
ल्यूक

2

पायथन 3, 877 बाइट्स

यह सही क्रियान्वयन नहीं है। यह "आगे के परीक्षण मामलों" के दूसरे पर विफल रहता है, 13.5325 की कुल दूरी के साथ एक समाधान का निर्माण करता है, जहां समाधान केवल 13.2433 की आवश्यकता होती है। इसके अतिरिक्त जटिल तथ्य यह है कि मेरा गोल्फ का कार्यान्वयन मेरे द्वारा पहले लिखे गए अनगुल्ड मेल से मेल नहीं खाता है ...

हालाँकि, किसी और ने जवाब नहीं दिया है, और यह बहुत दिलचस्प है कि पर्ची को अतीत में जाने देना एक चुनौती है। इसके अलावा, मेरे पास यूएसए डेटा से उत्पन्न एक तस्वीर है, इसलिए वहां ऐसा है।

एल्गोरिथ्म कुछ इस तरह है:

  1. निकटतम पूर्णांक निर्देशांक के सभी बिंदुओं को पुश करें (इसके बाद "स्क्वायर" कहा जाता है)।
  2. सबसे बड़ी संख्या के साथ वर्ग का पता लगाएं।
  3. उन बिंदुओं में से सबसे कम लागत वाले पुनर्वितरण का पता लगाएं, जो कि पहले से ही चरण 2 में संसाधित किए गए किसी भी वर्ग को छोड़कर।
    • पुनर्वितरण प्रति वर्ग एक बिंदु तक सीमित है, जब तक कि यह पर्याप्त वर्ग प्रदान नहीं करेगा (हालांकि तब भी, केवल एक बिंदु इस वर्ग पर रहेगा )।
  4. चरण 2 से दोहराएं जब तक कि किसी वर्ग में एक से अधिक बिंदु न हों।
  5. प्रत्येक मूल बिंदुओं का पता लगाएँ, क्रम में और उनके वर्गों को क्रम में आउटपुट करते हैं।

मेरे पास इस एल्गोरिथम के किसी भी भाग के लिए इष्टतमता का कोई सबूत नहीं है, बस एक मजबूत संदेह है कि यह "बहुत अच्छा" परिणाम प्रदान करेगा। मुझे लगता है कि हमने अपने यूनी दिनों में एक "हेयोरिस्टिक एल्गोरिथम" कहा है ...!

l=len
I,G,M=-1,101,150
d=lambda x,y,X,Y:abs(x-X+1j*(y-Y))
N=(0,0),(I,0),(0,I),(1,0),(0,1),(I,I),(1,I),(1,1),(I,I)
n=lambda p,e:[(x,y)for(x,y)in(map(sum,zip(*i))for i in zip([p]*9,N))if(x,y)not in e and I<x<G and I<y<G]
def f(p):
 g={};F=[];O=[I]*l(p)
 for P in p:
  z=*map(round,P),
  if z in g:g[z]+=[P]
  else:g[z]=[P]
 while l(g)<l(p):
  L,*P=0,
  for G in g:
   if l(g[G])>l(P):L,P=G,g[G]
  o=n(L,F);h=l(o)<l(P);c=[[d(*q,*r)for r in o]for q in P];r={}
  while l(r)<l(c):
   A=B=C=M;R=S=0
   while R<l(c):
    if R not in r:
     z=min(c[R])
     if z<A:B,A=R,z;C=c[R].index(A)
    R+=1
   while S<l(c):
    if S==B:
     v=0
     while v<l(c[S]):
      if v!=C:c[S][v]=M
      v+=1
    elif C<1or not h:c[S][C]=M
    S+=1
   r[B]=C
  for q in r:
   x,y=P[q],o[r[q]]
   if y==L or y not in g:g[y]=[x]
   else:g[y]+=[x]
  F+=[L]
 for G in g:
  O[p.index(g[G][0])]=G
 return O

और इसे यूएसए डेटा पर चलाने का परिणाम (उपयोगिता फ़ंक्शन के लिए धन्यवाद जो एसवीजी में परिणाम बदल जाता है): सन्निहित संयुक्त राज्य अमेरिका का एक योजनाबद्ध नक्शा

यह उत्पादित अनगोल्ड कोड की तुलना में थोड़ा खराब है; एकमात्र दृश्य अंतर यह है कि शीर्ष-दाएं वर्ग सबसे बेहतर एक में बाईं ओर एक है।


आपको पीठ पर एक पॅट मिलता है! ऐसा लगता है कि मुझे इस लुक को टाइम्स से आरेख की तरह बनाने के लिए देशांतर के स्केलिंग पर काम करने की आवश्यकता है।
ल्यूक

जिज्ञासा से बाहर, यूएसए के नक्शे के लिए आपको कुल कितनी दूरी मिलती है?
टॉम कारपेंटर

मुझे शायद खुद से वह सवाल पूछना चाहिए था ... क्योंकि यह सिर्फ मुझे दिखा रहा है कि मेरा गोल्फ का क्रियान्वयन मेरे विचार से भी बदतर है। मेरा मूल, असंगठित संस्करण इसे 20.9164 में मिला, लेकिन मैंने जो संस्करण पोस्ट किया, उसने मुझे 20.9987 दिया। * sigh *
टिम पेडरिक

1

MATLAB, 316 343 326 बाइट्स

यह एक कार्य प्रगति पर है - यह तेज़ नहीं है, लेकिन यह कम है। यह अधिकांश परीक्षण मामलों को पारित करने के लिए लगता है। वर्तमान में नक्शे के केवल मजेदार इनपुट के लिए एक चल रहा है, लेकिन यह अभी भी 10 मिनट के बाद चल रहा है, इसलिए ...

function p=s(a)
c=ceil(a');a=a(:,1)+j*a(:,2);[~,p]=r(a,c,[],Inf);p=[real(p),imag(p)];end
function [o,p]=r(a,c,p,o)
if ~numel(c)
o=sum(abs(p-a));else
x=c(1)+(-1:1);y=c(2)+(-1:1);P=p;
for X=1:3
for Y=1:3
Q=x(X)+j*y(Y);if(x(X)>=0)&(y(Y)>=0)&all(Q~=P)
[O,Q]=r(a,c(:,2:end),[P;Q],o);
if(O<o) o=O;p=Q;disp(o);end
end;end;end;end;end

और कुछ अधिक पठनीय प्रारूप में:

function p=squaremap(a)
%Input format: [2.0, 2.1;2.0, 2.2;2.1, 2.0;2.0, 1.9;1.9, 2.0]

    c=ceil(a'); %Convert each point to the next highest integer centre
    a=a(:,1)+j*a(:,2); %Convert each 2D point into a complex number
    [~,p]=r(a,c,[],Inf); %Recurse!
    p=[real(p),imag(p)];
end

function [o,p]=r(a,c,p,o)
    if ~numel(c) %If we are as deep as we can go
        o=sum(abs(p-a)); %See what our overall distance is
    else
        x=c(1)+(-1:1);y=c(2)+(-1:1); %For each point we try 9 points, essentially a 3x3 square
        P=p;
        for X=1:3;
            for Y=1:3
                %For each point
                Q=x(X)+j*y(Y); %Covert to a complex number
                if(x(X)>=0)&(y(Y)>=0)&all(Q~=P) %If the point is not negative and has not already been used this iteration
                    [O,Q]=r(a,c(:,2:end),[P;Q],o); %Otherwise iterate further
                    if(O<o) o=O;p=Q;end %Keep updating the smallest path and list of points we have found
                end
            end
        end
    end
end

इनपुट प्रारूप एक MATLAB सरणी होने की उम्मीद है, जैसे:

[2.0, 2.1;2.0, 2.2;2.1, 2.0;2.0, 1.9;1.9, 2.0]

जो प्रश्न में प्रारूप के काफी करीब है, जो कुछ लेवे की अनुमति देता है।

आउटपुट इनपुट के समान प्रारूप में है, एक ऐसा सरणी जहां कोई भी दिया गया सूचकांक इनपुट और आउटपुट दोनों में समान बिंदु से मेल खाता है।


हम्म, 8 घंटे और अभी भी एक नक्शे पर चल रहा है ... यह समाधान सबसे इष्टतम खोजने की गारंटी है, लेकिन यह जानवर बल के माध्यम से करता है, इसलिए बहुत लंबा समय लगता है।

मैं एक और समाधान के साथ आया हूं, जो बहुत तेज है, लेकिन दूसरे उत्तर की तरह परीक्षण के मामलों में सबसे इष्टतम खोजने में विफल रहता है। दिलचस्प बात यह है कि मुझे अपने अन्य समाधान के लिए जो नक्शा मिलता है (पोस्ट नहीं किया गया है) नीचे दिखाया गया है। यह 20.72 की कुल दूरी प्राप्त करता है।

नक्शा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.