एक ग्राफ पर तनाव, भाग I: एक लहराती स्ट्रिंग


21

आइए डोमेन [-3,3] पर एक फंक्शन (x) = sin ()x) + 0.5 sin ( 3 ] x) प्लॉट करें । हम इसे एक बोर्ड पर पड़े ढीले तार के रूप में व्याख्या कर सकते हैं। अब आइए पदों (x 1 , y 1 ) से (x n , y n ) , जहां x i ) (-3,3) और y i -1 [-1,1] में n कीलों को ड्राइव करें । कल्पना करें कि स्ट्रिंग के अंत में दो सुराख़ हैं , जो कि पदों पर है (-3,0) और (3,0)। अब हम स्ट्रिंग के सिरों को ले जा सकते हैं और जब तक स्ट्रिंग तना हुआ नहीं है तब तक आंखों के माध्यम से खींच सकते हैं। यह हमारे ग्राफ को एक टुकड़े-टुकड़े रैखिक फ़ंक्शन में ख़राब कर देगा।

कुछ चित्र मदद कर सकते हैं। 8 नाखून (-2.8, -0.7), (-2.5, -0.9), (-1.2, .2), (-0.5, .8), (0.5, .4), (1.2, -0.9) पर लें। (1.5, -0.6), (1.8, -0.8) । निम्नलिखित तीन भूखंड ऊपर वर्णित प्रक्रिया दिखाते हैं:

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

बड़े संस्करण के लिए: राइट-क्लिक करें -> नए टैब में खोलें

और यहाँ स्ट्रिंग को कसने का एक एनीमेशन है अगर आपको इसे देखने में कुछ कठिनाई हो रही है:

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

चुनौती

"नाखून" (जो जरूरी पृथक नहीं किया जा रहा है) की एक सूची को देखते हुए, उन नाखून और तना हुआ स्ट्रिंग साजिश अगर यह ऊपर समारोह के आकार से शुरू होता है

आप एक प्रोग्राम या फ़ंक्शन लिख सकते हैं और STDIN, ARGV या फ़ंक्शन तर्क के माध्यम से इनपुट ले सकते हैं। आप या तो स्क्रीन पर परिणाम प्रदर्शित कर सकते हैं या किसी फ़ाइल में एक छवि सहेज सकते हैं।

यदि परिणाम को रेखापुंज किया जाता है, तो इसे कम से कम 300 पिक्सेल चौड़ा और 100 पिक्सेल लंबा होना चाहिए। (-3, -1.1) से (3,1.1) तक की समन्वय सीमा को छवि की क्षैतिज और ऊर्ध्वाधर सीमा का कम से कम 75% कवर करना चाहिए। X और y की लंबाई के पैमानों को समान नहीं होना चाहिए। आपको नाखून (कम से कम 3x3 पिक्सेल का उपयोग करके) और स्ट्रिंग (कम से कम 1 पिक्सेल चौड़ा) दिखाने की आवश्यकता है। आप कुल्हाड़ियों को शामिल कर सकते हैं या नहीं।

रंग आपकी पसंद हैं, लेकिन आपको कम से कम दो अलग-अलग रंगों की आवश्यकता है: एक पृष्ठभूमि के लिए और एक नाखून और स्ट्रिंग के लिए (हालांकि वे अलग-अलग रंग हो सकते हैं)।

आप मान सकते हैं कि सभी नाखून से कम से कम 10 -5 यूनिट दूर हैं (ताकि आपको फ्लोटिंग-पॉइंट अशुद्धि के बारे में चिंता करने की आवश्यकता न हो)।

यह कोड गोल्फ है, इसलिए सबसे छोटा उत्तर (बाइट्स में) जीतता है।

और ज्यादा उदाहरण

यहां दो और (सरल) उदाहरण दिए गए हैं:

{{-2.5, 1}, {-1.5, -1}, {-0.5, 1}, {0.5, -1}, {1.5, 1}, {2.5, -1}}

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

(स्ट्रिंग एक्स- एक्सिस के साथ मेल खाता है ।)

{{-2.7, -0.5}, {-2.3, -0.5}, {-1.7, 0.5}, {-1.3, 0.5}, {-0.7, -0.5}, {-0.3, -0.5}, {0.5, 1}, {1.5, -1}, {2.5, 1}}

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

एक और चुनौती चाहते हैं?

यहाँ भाग II है!


क्या हम मान सकते हैं कि नाखून बाएं से दाएं हलके हैं?
एलएल

@ सभी आह, अच्छी पकड़ है। चूंकि मैंने इसे शुरू करने के लिए निर्दिष्ट नहीं किया है, नहीं। मैं स्पष्ट कर दूंगा।
मार्टिन एंडर

जवाबों:


8

अजगर + पाइकाइरो, 727 708 608, पाइलैब, 383

from pylab import*
def f(N):
 def P(u,w,N):
    T=lambda v,p:(C(v-u,p-u)>0)==(C(w-v,p-v)>0)==(C(u-w,p-w)>0);M=[(i,n)for i,n in enumerate(N)if T(V([n[0],sin(pi*n[0])+sin(3*pi*n[0])/2]),n)]
    if M:i,n=max(M,key=lambda n:C(n[1]-u,w-u)**2);M=P(u,n,N[:i])+[n]+P(n,w,N[i+1:])
    return M
 V=array;C=cross;a=V([3,0]);plot(*zip(*([-a]+P(-a,a,map(V,sorted(N)))+[a])));N and scatter(*zip(*N));show()

उदाहरण

f([(-2.8,-0.7),(-2.5,-0.9),(-1.2,0.2),(-0.5,0.8),(0.5,0.4),(1.2,-0.9),(1.5, -0.6),(1.8, -0.8)])

उदाहरण 1

यह काम किस प्रकार करता है

मान लीजिए हम जानते हैं कि तना हुआ स्ट्रिंग दो अंक के माध्यम से गुजरता एक और बी (हम हमेशा ए = (-3, 0) और बी = (3, 0) से शुरू कर सकते हैं ।) जैसा कि हम स्ट्रिंग को खींचते हैं, यह "लेना" चाहता है। और बी के बीच सबसे छोटा रास्ता संभव है, अर्थात्, आदर्श रूप से, खंड एबी । हालांकि, यदि फ़ंक्शन ( पाप ...x + ... ) और एबी द्वारा बंधे क्षेत्र में कोई नाखून हैं , तो उनमें से कम से कम एक को स्ट्रिंग को ब्लॉक करना होगा। विशेष रूप से, उक्त क्षेत्र के भीतर एबी से सबसे दूर स्थित कील ( तार) को स्ट्रिंग को ब्लॉक करना होगा। इसलिए, यदि सी यह नाखून है, तो हम जानते हैं कि तना हुआ तार गुजरना चाहिएसी , के अलावा एक और बी । अब हम सेगमेंट AC और के लिए प्रक्रिया दोहरा सकते हैं
सीबी के , और इस तरह से जारी रख सकते हैं जब तक कि अंत में अधिक हस्तक्षेप करने वाले नाखून न हों। आकृति 1

यह प्रत्येक चरण में एक रैखिक स्कैन के साथ एक द्विआधारी विभाजन-और-जीत एल्गोरिथ्म है, इसलिए इसमें ओ (एन लॉग एन) की सबसे अच्छी स्थिति जटिलता और ओ (एन 2 ) की सबसे खराब स्थिति जटिलता है ।


यदि अंकों की सूची खाली है तो यह त्रुटी है। लेकिन उस के अलावा अन्य स्पष्ट रूप से निराशाजनक है!
feersum

@ फेरेसम अच्छा कैच। फिक्स्ड।
एल

3

पायथन + पायलैब, 576 बाइट्स

कलन विधि:

मैंने इस समस्या की व्याख्या की (-3, 0) से (3, 0) तक का सबसे छोटा रास्ता खोजने के लिए , जैसे कि वर्टिकल लाइन सेगमेंट, जो रास्ते पर एक बिंदु को f (x) पर एक बिंदु से जोड़ता है, कभी भी एक कील को पार नहीं करता है।

प्रत्येक x पर जहाँ कम से कम एक कील मौजूद होती है, उस x पर नाखूनों द्वारा दी गई सबसे कम ऊपरी और सबसे बड़ी निचली सीमा को खोजें । इन सीमाओं द्वारा दिए गए बिंदुओं पर विचार करें और एक ग्राफ पर वर्टिश होने के लिए शुरुआती और अंत के अंक। दो कोने के बीच यूक्लिडियन दूरी द्वारा दिए गए वजन के साथ एक किनारा जोड़ें यदि उनके बीच की रेखा खंड प्रत्येक हस्तक्षेप करने वाले x समन्वय के लिए ऊपरी और निचले सीमा के भीतर आती है। इस ग्राफ पर सबसे छोटा रास्ता खोजें।

27 यादृच्छिक बिंदुओं के साथ उदाहरण:

(-0.367534, -0.722751), (-0.710649, -0.701412), (1.593101, -0.484983), (1.771199, 0.681435), (-1.878764, -0.491436), (-0.061414, 0.628570), (-0.326483, -0.512950), (0.877878, 0.858527), (1.256189, -0.300032), (1.528120, -0.606809), (-1.343850, -0.497832), (1.078216, 0.232089), (0.930588, -0.053422), (-2.024330, -0.296681), (-2.286014, 0.661657), (-0.009816, 0.170528), (2.758464, 0.099447), (-0.957686, 0.834387), (0.511607, -0.428322), (-1.657128, 0.514400), (1.507602, 0.507458), (-1.469429, -0.239108), (0.035742, 0.135643), (1.194460, -0.848291), (2.345420, -0.892100), (2.755749, 0.061595), (0.283293, 0.558334), 

लंगड़ा उदाहरण

golfed

क्या इंडेंटेशन के कई रिक्त स्थान के रूप में प्रकट होता है for j in R(i&~1)लूप वास्तव में एक टैब होना चाहिए।

from pylab import*
P=((3,0),(-3,0))+input()
X=sorted(set(zip(*P)[0]))
l=len(X)*2
if l>4:scatter(*zip(*P[2:]))
f=lambda x:sin(pi*x)+sin(3*pi*x)/2
B=[[max([-9]+[p[1]for p in P if x==p[0]and p[1]<f(x)]),min([9]+[p[1]for p in P if x==p[0]and p[1]>f(x)])]for x in X]
b=zeros(l);b[2:]=inf
v=list(b)
R=range
for i in R(l):
 for j in R(i&~1):
    A=B[j/2][j&1];D,d=B[i/2][i&1]-A,X[i/2]-X[j/2];K=1;c=b[j]+norm((d,D))
    for k in R(j/2+1,i/2):C=A+D/d*(X[k]-X[j/2]);K&=C<B[k][1];K&=C>B[k][0]
    if(c<b[i])&K:b[i]=c;v[i]=j,(X[j/2],A)
l-=2
s=P[:1]
while l/2:l,p=v[l];s+=(p,)
plot(*zip(*s))
show()

Ungolfed

from pylab import*
P = input()
Xn,Yn = zip(*P)
X = set(Xn+(3,-3))
f = lambda x:sin(pi*x)+sin(3*pi*x)/2
ylb = {x: max([-9]+[p[1] for p in P if p[0] == x and p[1] < f(x)]) for x in X}
yub = {x: min([9]+[p[1] for p in P if p[0] == x and p[1] > f(x)]) for x in X}
ylb[-3] = yub[3] = ylb[3] = 0
X = sorted(X)
l = len(X)
best = zeros((l,2))
best[1:] = inf
prev = [ [0,0] for i in range(l) ]
for i in range(l): # calculate min path to X[i] lb or ub
  for ib in 0,1:
    for j in range(i): # point to come from
      for jb in 0,1:
          Y2, Y1 = (ylb, yub)[ib][X[i]], (ylb, yub)[jb][X[j]]
          dy,dx = Y2 - Y1, X[i] - X[j]
          if all([Y1 + dy/dx*(x - X[j]) < yub[x] and Y1 + dy/dx*(x - X[j]) > ylb[x] for x in X[j+1:i]]):
             c = best[j][jb] + (dy**2+dx**2)**.5
             if c < best[i][ib]:
                 best[i][ib] = c
                 prev[i][ib] = j, jb, (X[j], Y1)
j, jb = l-1,0
pts = [(3,0)]
while j:
    j, jb, p = prev[j][jb]
    pts += [p]
plot(*zip(*pts))
scatter(Xn,Yn)
show()

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