एक ग्राफ पर तनाव, भाग II: एक रबर बैंड


13

"पुलिंग फ़ंक्शंस टॉट" के बारे में दो चुनौतियों में से यह दूसरी है। यहाँ थोड़ा सरल भाग I है

आइए पदों (x 1 , y 1 ) से (x m , y m ) पर एक बोर्ड में m नाखूनों को चलाएं । एक रबर बैंड को उन लोगों के पहले और आखिरी हिस्से में बाँधें और दूसरे नाखूनों के चारों ओर खिंचाव दें, जैसे कि बैंड सभी नाखूनों को क्रम में ट्रेस करता है। ध्यान दें कि रबर बैंड अब 2 डी अंतरिक्ष में एक टुकड़ा-रेखीय रैखिक मानकीकृत फ़ंक्शन (x (t), y (t)) का वर्णन करता है।

अब पदों में (x 1 , y 1 ) से (x n , y n ) पर बोर्ड में एक और n नाखून चलाएं । अगर हम अब पहले और आखिरी एक (जो रबड़ के सिरों से बंधा हुआ है) को छोड़कर सभी मूल एम नाखूनों को हटा देते हैं , तो रबर बैंड छोटा हो जाएगा जब तक कि यह नए नाखूनों के चारों ओर झूठ बोल रहा हो, एक और टुकड़े-टुकड़े रैखिक कार्य करता है।

एक उदाहरण के रूप में, पदों (0, 0), (2, -1), (3/2, 4/3), (7/2, 1/3), (11/2) पर m = 12 प्रारंभिक नाखून लें 16/3), (1, 16/3), (0, 1), (7, -2), (3, 4), (8, 1), (3, -1), (11, 0) , और n = 10 आगे के पदों पर नाखून (1, 1), (3, 1), (4, 4), (1, 3), (2, 2), (5, -1), (5, 0) ), (6, 2), (7, 1), (6, 0) । निम्नलिखित तीन भूखंड ऊपर वर्णित प्रक्रिया दिखाते हैं:

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

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

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

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

चुनौती

"नाखूनों" की दो सूचियों को देखते हुए, पहली सूची में सभी नाखूनों को ट्रेस करने वाले आकार से शुरू होने पर, दूसरी सूची के चारों ओर टॉट रबर बैंड को प्लॉट करें।

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

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

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

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

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

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

यहाँ दो और उदाहरण हैं:

{{1, 1}, {3, 3}, {2, 4}, {1, 3}, {4, 0}, {3, -1}, {2, 0}, {4, 2}}
{{2, 1}, {3, 2}, {1, 2}, {4, 1}}

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

{{1, 1}, {3, 1}, {3, 3}, {1, 3}, {1, 5}, {3, 5}, {-1, 3}, {-1, 0}, {3, 4}, {5, 1}, {5, -1}, {7, -1}, {3, 7}, {7, 5}}
{{0, 0}, {0, 2}, {0, 4}, {0, 6}, {2, 0}, {2, 2}, {2, 4}, {2, 6}, {4, 0}, {4, 2}, {4, 4}, {4, 6}, {6, 0}, {6, 2}, {6, 4}, {6, 6}}

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

और यहां एक उदाहरण है जो शेष दो प्रारंभिक नाखूनों के महत्व को दर्शाता है। परिणाम होना चाहिए और नहीं एक :

{{0, 0}, {0, 1}, {-1, 1}, {-1, -1}, {1, -1}, {1, 0}}
{{-0.5, 0.5}}

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

इस उदाहरण को प्रदान करने के लिए एलई को धन्यवाद।


@laurencevs स्ट्रिंग एक एकल-मूल्यवान है, जो चीजों को काफी सरल करता है, क्योंकि इसमें एक स्पष्ट दिशा है जिसमें फ़ंक्शन और नाखून को संसाधित करना है। इस में लूप और ज़िगज़ैग हो सकते हैं, और फ़ंक्शन का रूप काफी भिन्न होता है (और चर), जिसका अर्थ है कि समाधान काफी भिन्न होना चाहिए।
मार्टिन एंडर

के उत्पादन में क्या है यह ?
एल

@ सभी आह, बहुत अच्छा परीक्षण मामला। मुझे लगता है कि स्थिरता के लिए, यह बी होना चाहिए , लेकिन मुझे वास्तव में उस बारे में सवाल स्पष्ट करने की आवश्यकता है। जल्द ही ऐसा करेंगे। धन्यवाद!
मार्टिन एंडर

जवाबों:


11

पायथन + माट्लोटलिब, 688

from pylab import*
C=cross
P,M=eval("map(array,input()),"*2)
P,N=[[P[0]]+L+[P[-1]]for L in P,M]
W=[.5]*len(P)
def T(a,c,b):
 I=[(H[0]**2,id(n),n)for n in N for H in[(C(n-a,b-a),C(n-b,c-b),C(n-c,a-c))]if(min(H)*max(H)>=0)*H[1]*H[2]]
 if I:d=max(I)[2];A=T(a,c,d);B=T(d,c,b);return[A[0]+[d]+B[0],A[1]+[sign(C(c-a,b-c))]+B[1]]
 return[[]]*2
try:
 while 1:
    i=[w%1*2or w==0for w in W[2:-2]].index(1);u,a,c,b,v=P[i:i+5];P[i+2:i+3],W[i+2:i+3]=t,_=T(a,c,b);t=[a]+t+[b]
    for p,q,j,k in(u,a,1,i+1),(v,b,-2,i+len(t)):x=C(q-p,c-q);y=C(q-p,t[j]-q);z=C(c-q,t[j]-q);d=sign(j*z);W[k]+=(x*y<=0)*(x*z<0 or y*z>0)*(x!=0 or d*W[k]<=0)*(y!=0 or d*W[k]>=0)*d
except:plot(*zip(*P))
if M:scatter(*zip(*M))
show()

STDIN से अंकों की दो सूचियाँ पढ़ता है।

उदाहरण

[(0, 0), (2, -1), (3.0/2, 4.0/3), (7.0/2, 1.0/3), (11.0/2, 16.0/3), (1, 16.0/3), (0, 1), (7, -2), (3, 4), (8, 1), (3, -1), (11, 0)]
[(1, 1), (3, 1), (4, 4), (1, 3), (2, 2), (5, -1), (5, 0), (6, 2), (7, 1), (6, 0)]

आकृति 1

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

समाधान की कुंजी छोटे, वृद्धिशील चरणों में काम करना है। यह पता लगाने की कोशिश करने के बजाय कि क्या होता है जब हम एक ही बार में सभी नाखूनों को हटा देते हैं, हम सिर्फ एक नाखून को हटाने के प्रत्यक्ष प्रभावों पर ध्यान केंद्रित करते हैं। फिर हम मनमाने क्रम में एक-एक करके नाखूनों को हटा सकते हैं।

वृद्धिशील रूप से काम करने का मतलब है कि हमें रबर बैंड के मध्यवर्ती स्थिति का ट्रैक रखना चाहिए। यहाँ मुश्किल हिस्सा है: केवल किस ट्रैक के माध्यम से बैंड चलता है, यह पर्याप्त नहीं है। नाखूनों को हटाने की प्रक्रिया के दौरान बैंड घाव हो सकता है और बाद में एक नाखून के चारों ओर घूम सकता है। इसलिए, जब बैंड एक कील के साथ बातचीत करता है तो हमें इस बात का ध्यान रखना चाहिए कि यह कितनी बार और किस दिशा में घूमता है। हम बैंड के साथ प्रत्येक नाखून के लिए एक मान निर्दिष्ट करके ऐसा करते हैं:

चित्र 2

ध्यान दें कि:

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

  • हम नाखूनों को शून्य के मान के साथ रखते हैं, अर्थात, ऐसे नाखून जिनका उपयोग किया जाता था, लेकिन अब बैंड को पकड़ कर रखने के बजाय उन्हें तुरंत हटा दिया जाता है। यदि हमने किया है, तो यह एक अनजाने श्रृंखला प्रतिक्रिया को ट्रिगर कर सकता है, जबकि हम प्रत्येक चरण के प्रभावों को स्थानीयकृत रखने की कोशिश कर रहे हैं। इसके बजाय, शून्य के मूल्य वाले नाखून को बड़ी प्रक्रिया के हिस्से के रूप में हटाने के लिए योग्य माना जाता है।

अब हम बता सकते हैं कि प्रत्येक चरण में क्या होता है:

  • हम बैंड के वर्तमान पथ से हटाने के लिए एक कील का चयन करते हैं। यदि नाखून नाखूनों के पहले सेट (एंडपॉइंट के लिए सहेजें) का हिस्सा है या यदि इसका मूल्य शून्य है तो हटाने के लिए पात्र है।

  • यह निश्चय करते हुए कि दो पड़ोसी नाखूनों को ठीक कर रहे हैं, हम यह पता लगाते हैं कि दूसरे सेट से कौन-सी कीलें निकली हैं या चयनित नाखूनों को हटाने के बाद बैंड की जोड़ी चलने वाली है (हम नाखूनों के बाकी नाखूनों से परेशान नहीं होते हैं पहला सेट, क्योंकि वे अंततः सभी को हटा दिया जाएगा।) हम इसे भाग I के समाधान के लिए इसी तरह से करते हैं । ये सभी नाखून बैंड के एक ही तरफ हैं, इसलिए हम सभी को 1 या -1 के मान पर निर्भर करते हैं।

  • हम बैंड के मार्ग में परिवर्तन (आसानी से मुश्किल भाग!) को प्रतिबिंबित करने के लिए दो पड़ोसी नाखूनों के मूल्य को अपडेट करते हैं!

इस प्रक्रिया को तब तक दोहराया जाता है जब तक कि हटाने के लिए अधिक नाखून न हों:

चित्र तीन

और यहाँ एक अधिक जटिल उदाहरण कई बार एक नाखून के चारों ओर लपेटते हुए बैंड को दिखाता है:

चित्र 4


गजब का! बस एक चीज: क्या वे ग्राफिक्स रैस्टराइज़्ड हैं या वे वेक्टर ग्राफिक्स हैं? पूर्व मामले में, मुझे आपको "x और y की लंबाई के पैमानों को समान करना होगा।" इसके अलावा, आप उन सभी ग्राफिक्स को बनाने के लिए क्या उपयोग कर रहे हैं जो आप अपने स्पष्टीकरण में उपयोग करते हैं। matplotlib, भी?
मार्टिन एंडर

धन्यवाद! Err ... चूँकि matplotlib चलो मैं जिस प्लॉट पर उड़ने जा रहा हूँ उस प्लॉट को स्केल करता हूँ मैं वेक्टर ग्राफिक्स के साथ जा रहा हूँ :) उदाहरण के लिए मैं आमतौर पर जप करता हूँ । यह थोड़ा विचित्र है लेकिन इससे काम हो जाता है।
एल

हाँ ठीक है, यदि आप इसे मनमाने ढंग से आकार बदल सकते हैं, तो यह ठीक है। लिंक के लिए धन्यवाद, मैं इसकी जाँच करूँगा!
मार्टिन एंडर

4

जावा - 1262 बाइट्स

मुझे पता है कि यह उतना गोल्फ नहीं है जितना यह हो सकता है।

हालाँकि, कोई भी व्यक्ति प्लेट में कदम नहीं रख रहा है और इस प्रश्न का उत्तर दे रहा है, इसलिए मैं लूंगा।

पहला, वर्ग "टी" - जो एक बिंदु वर्ग है - 57 बाइट्स

class T{double x,y;public T(double a,double b){x=a;y=b;}}

और मुख्य वर्ग - 1205 बाइट्स

import java.awt.Color;import java.awt.Graphics;import java.util.*;import javax.swing.*;class Q extends JPanel{void d(List<T>a,T[]z){JFrame t=new JFrame();int m=0;int g=0;for(T v:a){if(v.x>m)m=(int)v.x;if(v.y>g)g=(int)v.y;}for(T v:z){if(v.x>m)m=(int)v.x;if(v.y>g)g=(int)v.y;}t.setSize(m+20,g+20);t.setVisible(true);t.getContentPane().add(this);double r=9;while(r>1){r=0;for(int i=0;i<a.size()-1;i+=2){T p1=a.get(i),p2=new T((p1.x+a.get(i+1).x)/2,(p1.y+a.get(i+1).y)/2);a.add(i+1,p2);if(y(p1,p2)>r){r=y(p1,p2);}}}double w=15;List<T>q=new ArrayList<T>();while(w>3.7){w=0;q.clear();for(int e=0;e<a.size()-2;e++){T p1=a.get(e),u=a.get(e+1),p3=a.get(e+2),p2=new T((p1.x+p3.x)/2,(p1.y+p3.y)/2);w+=y(u,p2);int k=0;if(y(p1,a.get(e+1))<.5){a.remove(e);}for(T n:z){if(y(n,p2)<1){k=1;q.add(n);}}if(k==0){a.set(e+1,p2);}}}q.add(a.get(a.size()-1));q.add(1,a.get(0));p=z;o=q.toArray(new T[q.size()]);repaint();}T[]p;T[]o;double y(T a,T b){return Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));}public void paintComponent(Graphics g){if(o!=null){for(int i=0;i<o.length-1;i++){g.drawLine((int)o[i].x,(int)o[i].y,(int)o[i+1].x,(int)o[i+1].y);}g.setColor(Color.blue);for(T i:p){g.fillOval((int)i.x-3,(int)i.y-3,6,6);}}}}

उदाहरण:

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

चलाने के लिए, बिंदुओं की सूची और नाखूनों की एक सरणी (हां, मुझे पता है, अजीब) के साथ "डी" फ़ंक्शन को कॉल करें। यह क्या करता है:

  • बिंदुओं की एक सूची बनाता है जो लाइनों का प्रतिनिधित्व करता है - अर्थात, लाइनों के बीच के सभी बिंदु।
  • इन बिंदुओं पर बार-बार एक एल्गोरिथ्म दोहराता है ताकि प्रत्येक बिंदु उसके चारों ओर दो बिंदुओं का औसत हो।
  • जब अंक अधिक गतिमान नहीं लगते हैं, तो मैं किसी भी नाखूनों के बीच खींचता हूं जो वे छू रहे हैं।

मुझे यकीन नहीं है कि अगर पिक्सेल में कुल्हाड़ी ठीक है। यह हमेशा 75% से अधिक स्थान लेगा, यह वास्तव में वास्तव में छोटा हो सकता है।

यहाँ मैं क्या कर रहा हूँ, यह प्रदर्शित करने के लिए एक अच्छा एनीमेशन है:

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

आखिरकार, यह ऐसा हो जाता है, जिसमें बिंदु मुश्किल से चलते हैं। यह तब होता है जब मैं देखता हूं कि यह किस नाखून को छू रहा है:

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

यहाँ ungolfed, एनीमेशन कोड है:

import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Q extends JPanel{
    List<Point>points=new ArrayList<Point>();
    List<Point>n=new ArrayList<Point>();
    public Q() throws InterruptedException{
        double[][]rawPoints={{0, 0}, {2, -1}, {3/2, 4/3}, {7/2, 1/3}, {11/2, 16/3}, {1, 16/3}, {0, 1}, {7, -2}, {3, 4}, {8, 1}, {3, -1}, {11, 0}};
        double[][]rawNails={{1, 1}, {3, 1}, {4, 4}, {1, 3}, {2, 2}, {5, -1}, {5, 0}, {6, 2}, {7, 1}, {6, 0}};
        List<Point>p=new ArrayList<Point>(),nails = new ArrayList<Point>();
        double factor = 50;
        for(double[]rawP:rawPoints){p.add(new Point(rawP[0]*factor+100,rawP[1]*factor+100));}
        for(double[]rawN:rawNails){nails.add(new Point(rawN[0]*factor+100,rawN[1]*factor+100));}
        n=nails;
        JFrame frame=new JFrame();
        frame.setSize(700,500);
        frame.setVisible(true);
        frame.getContentPane().add(this);
        d(p,nails);
    }
    public static void main(String[]a) throws InterruptedException{
        new Q();
    }
    void d(List<Point>a,List<Point>nails) throws InterruptedException{
        //add midpoint every iteration until length of 1 is achieved
        //begin algorithm
        //stop points that are within a small amount of a nail
        double distance=20;
        while(distance>1){
            distance=0;
            for (int i=0;i<a.size()-1;i+=2){
                double fir=a.get(i).x;
                double sec=a.get(i).y;
                double c=(fir+a.get(i+1).x)/2;
                double d=(sec+a.get(i+1).y)/2;
                a.add(i+1,new Point(c,d));
                double dist=distBP(new Point(fir,sec),new Point(c,d));
                if(dist>distance){distance=dist;}
            }
        }
        for(Point p:a){a.set(a.indexOf(p), new Point(p.x,p.y));}
        //algorithm starts here:
        setEqual(a);
        repaint();
        invalidate();
        System.out.println(a);
        int count=0;
        while(true){
            count++;
            for(int index=0;index<a.size()-2;index++){
                double x2=(a.get(index).x+a.get(index+2).x)/2;
                double y2=(a.get(index).y+a.get(index+2).y)/2;
                int pointStable=0;
                if(distBP(a.get(index),a.get(index+1))<.5){a.remove(index);}
                for(Point n:nails){
                    if(distBP(n,new Point(x2,y2))<1){pointStable=1;}
                }
                if(pointStable==0){a.set(index+1, new Point(x2,y2));}
            }
            if(count%10==0){
            setEqual(a);
            invalidate();
            repaint();
            Thread.sleep(5);
            }
        }
        //System.out.println(a);
    }
    void setEqual(List<Point>a){
        points = new ArrayList<Point>();
        for(Point p:a){points.add(p);}
    }
    double distBP(Point a,Point b){
        return Math.sqrt(Math.pow(b.x-a.x, 2)+Math.pow(b.y-a.y, 2));
    }
    @Override
    public void paintComponent(Graphics g){
        g.setColor(Color.white);
        g.fillRect(0,0,getWidth(),getHeight());
        g.setColor(Color.black);
        for(Point p:points){
            g.drawRect((int)p.x, (int)p.y, 1, 1);
        }
        for(Point nail:n){
            g.drawOval((int)nail.x-2, (int)nail.y-2, 4, 4);
        }
    }
}

7
आपका उपयोगकर्ता नाम इस समस्या के अनुकूल है।
phosgene

एलई ने एक दिलचस्प बढ़त प्रदान की है जिसके बारे में मैंने नहीं सोचा था। मैंने युक्ति स्पष्ट की है और उस उदाहरण को जोड़ा है। आपका कोड उस उदाहरण पर कैसा प्रदर्शन करता है? चूंकि यह आपकी पोस्ट के बाद स्पष्ट किया गया था, आप अपने कोड को ठीक करने के लिए बाध्य नहीं हैं, यदि यह अद्यतन किए गए निर्देशों का पालन नहीं करता है, लेकिन मुझे लगा कि मैं आपको बता दूंगा।
मार्टिन एंडर

मैंने इसे ठीक करने के लिए कुछ बदलाव किए, लेकिन इससे मेरे कार्यक्रम में एक बग का पता चला (यदि आप इसे अंतिम उदाहरण के लिए इनपुट करने का प्रयास करते हैं, तो यह केवल एक पंक्ति दिखाता है)। मैं इसे ठीक करने का प्रयास करूंगा।
स्ट्रेच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.