Conic सेक्शन को पहचानें


13

द्वि-आयामी विमान पर 5 अलग-अलग बिंदुओं को देखते हुए, अंकों द्वारा गठित शंकु अनुभाग का प्रकार निर्धारित करें। उत्पादन में से एक होगा circle, hyperbola, ellipse, या parabola

नियम

  • अंक सामान्य रैखिक स्थिति में होंगे, जिसका अर्थ है कि कोई भी तीन अंक आपस में नहीं मिलते हैं, और इस प्रकार उनके माध्यम से गुजरने वाला शंकु अद्वितीय होगा।
  • 5 बिंदुओं के निर्देशांक -10 और 10, समावेशी के बीच दशमलव संख्या होंगे।
  • दशमलव / फ्लोट मानों की सटीकता आपकी भाषा के मूल फ्लोट / दशमलव प्रकार की सटीकता होनी चाहिए। यदि आपकी भाषा / डेटा प्रकार मनमानी-सटीक है, तो आप दशमलव बिंदु के बाद अधिकतम आवश्यक परिशुद्धता के रूप में शून्य (जैसे 1.0000000000005 == 1.000000000000) की ओर बढ़ते हुए 12 अंकों का उपयोग कर सकते हैं ।
  • आउटपुट का कैपिटलाइज़ेशन मायने नहीं रखता।
  • शंकुधारी ellipseअनुभाग वास्तव में एक सर्कल में आउटपुट की अनुमति नहीं है। सभी मंडलियां दीर्घवृत्त हैं, लेकिन आपको सबसे विशिष्ट एक का उत्पादन करना होगा।

फ़्लोटिंग पॉइंट गलतियाँ और सटीकता पर:

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

परीक्षण के मामलों

(0, 0), (1, 5), (2, 3), (4, 8), (9, 2) => hyperbola
(1.2, 5.3), (4.1, 5.6), (9.1, 2.5), (0, 1), (4.2, 0) => ellipse
(5, 0), (4, 3), (3, 4), (0, 5), (0, -5) => circle
(1, 0), (0, 1), (2, 1), (3, 4), (4, 9) => parabola

2
फ़्लोट्स के लिए, आउटपुट की तरह, circleएक बहुत ही गोल दीर्घवृत्त से अलग करने के लिए फ्लोट समानता की जाँच करने की आवश्यकता होती है। हमें यहाँ क्या सटीकता चाहिए?
xnor

1
@Mego सभी भाषाओं के लिए समस्या के पूर्णांक संस्करण की अनुमति क्यों नहीं देता, लेकिन एक व्यापक श्रेणी के साथ, जैसे -10000 से 10000।
orlp

1
क्या आपको यकीन है कि टेस्ट केस चार सही है? desmos: desmos.com/calculator/fmwrjau8fd
माल्टीसेन

2
इसके अलावा, 3 गलत भी लगता है: desmos.com/calculator/tkx1wrkotd
Maltysen

1
मुझे लगता है कि आप एफपी सटीकता के साथ समस्याओं को समझ रहे हैं, और इस तरह जवाब देने की ओर जाता है कोडगुल्फ.स्टैकएक्सचेंज.com
a

जवाबों:


2

मतलाब, 154 बाइट्स

p=input();c=null([p.^2 prod(p,2) p 1+p(:,1)*0]),s={'circle' 'ellipse' 'parabola' 'hyperbola'};s{3+sign(c(3)^2-4*c(1)*c(2))-~max(abs(c(3)),abs(c(1)-c(2)))}

स्वेवर के सुझावों के लिए कुछ बाइट्स को सहेजा गया।

के रूप में इनपुट लेता है [x1 y1;x2 y2;x3 y3; etc]। इसने वैंडर्मोंडे मैट्रिक्स का उपयोग किया, और इसके रिक्त स्थान का आधार पाया, जो हमेशा एक ही वेक्टर होगा। फिर यह विभेदक की गणना करता है और इसका उपयोग 1 और 4 के बीच एक इंडेक्स बनाने के लिए करता है जिसका उपयोग स्ट्रिंग प्राप्त करने के लिए किया जाता है।

Ungolfed:

p=input();
c=null([p.^2 prod(p')' p ones(length(p),1)]);
s={'circle' 'ellipse' 'parabola' 'hyperbola'};
s{3+sign(c(3)^2-4*c(1)*c(2))-~max(abs(c(3)),abs(c(1)-c(2)))}

sign(...)हिस्सा है, विभेदक की गणना करता है 1 दे रही है अगर यह सकारात्मक (अतिशयोक्ति) है, -1 अगर यह की नकारात्मक (अंडाकार), और 0 अगर यह 0 (परवलय) है। max(...)घटाता 1 दूर करता है, तो यह एक चक्र है। मतलाब सरणियाँ एक-अनुक्रमित हैं, इसलिए 1, 2, 3, 4 मान देने के लिए 3 को जोड़ें, और उपयोग करें कि शंकु अनुभाग नामों की सरणी को अनुक्रमित करें।


1
तुलना करने के बजाय max() == 0आप सरल कर सकते हैं~max()
सूअर

1
इसके बजाय ones(length(p),1)आप कर सकते हैं1+p(:,1)*0
स्वेअर

चीयर्स, max()बात मुझे मूर्खतापूर्ण थी, मैंने पहले वहाँ तुलना की थी और स्पष्ट रूप से आलसी हो गया था! यह पाने का तरीका onesबहुत अच्छा है।
डेविड

14

जावास्क्रिप्ट (ईएस 6), 316 323 347

p=>[1,2,4].some(x=>(d=D(Q=[[x&1,x&2,x&4,0,0,0],...p.map(([x,y])=>[x*x,x*y,y*y,x,y,1])]))?[a,b,c]=Q.map((v,i)=>D(Q.map((r,j)=>(r=[...r],r[i]=x*!j,r)))/d):0,D=m=>m[1]?m[0].reduce((r,v,i)=>r+(i&1?-v:v)*D(m.slice(1).map(r=>r.filter((a,j)=>j-i))),0):m)&&(d=b*b-4*a*c)?d<0?!b&c==a?'Circle':'Ellipse':'Hyperbola':'Parabola'

मैट्रिक्स और नियतांक को संभालने के लिए बेहतर कोई भी भाषा बेहतर स्कोर करना चाहिए (APL, J, CJAM, Jelly)

संदर्भ: शंकु का सामान्य रूप , पांच बिंदु एक शंकु निर्धारित करते हैं , लीनियर समीकरणों की प्रणाली , निर्धारक

कार्तीय तल में, एक शंकु का सामान्य समीकरण होता है

A*x*x + B*x*y + C*y*y + D*x + E*y + F = 0 

A या B या C 0 के बराबर नहीं है (अन्यथा यह एक सीधी रेखा है)

ए ... एफ छह अज्ञात पाए जाने वाले हैं। (X, y) के पांच जोड़े के साथ हम पांच समीकरणों के साथ एक रैखिक प्रणाली का निर्माण कर सकते हैं, और स्केलिंग एक आयाम को हटा सकते हैं। यही है, हम A, B या C में से एक को सेट कर सकते हैं यदि यह 0 नहीं है (और हम जानते हैं कि कम से कम एक 0 नहीं है)।

मैं 3 सिस्टम को हल करने का प्रयास करता हूं: पहले ए = 1 की कोशिश कर रहा हूं। यदि सॉल्व नहीं है तो B = 1 है, तो C. (इससे बेहतर तरीका और क्या हो सकता है, लेकिन उस समय मेरा सर्वश्रेष्ठ है)

A, B, C के मान रखने से हम विभेदक को देखते हुए शंकु को वर्गीकृत कर सकते हैं d=B*B-4*A*C

  • d == ० -> परबोला
  • d> 0 -> हाइपरबोला
  • घ <0 -> दीर्घवृत्त, विशेष रूप से (ए == सी और बी == 0) -> चक्र

कम गोल्फ वाला

F=p=>(
  // Recursive function to find determinant of a square matrix
  D=m=>m[1]
    ?m[0].reduce((r,v,i)=>r+(i&1?-v:v)*D(m.slice(1).map(r=>r.filter((a,j)=>j-i))),0)
    :m,
  // Try 3 linear systems, coefficients in Q
  // Five equation made from the paramaters in p
  // And a first equation with coefficient like k,0,0,0,0,0,1 (example for A)  
  [1,2,4].some(
    x => (
      // matrix to calc the determinant, last coefficient is missing at this stage
      Q = [ 
        [x&1, x&2, x&4, 0,0,0] // first one is different
        // all other equations built from the params 
        ,...p.map( ([x,y]) => [x*x, x*y, y*y, x, y, 1] )
      ],
      d = D(Q), // here d is the determinant
      d && ( // if solvable  then d != 0
        // add missing last coefficient to Q
        // must be != 0 for the first row, must be 0 for the other
        Q.map( r=> (r.push(x), x=0) ),
        // solve the system (Cramer's rule), I get all values for A...F but I just care of a,b,c
        [a,b,c] = Q.map((v,i)=>D(Q.map(r=>(r=[...r],r[i]=r.pop(),r))) / d),
        d = b*b - 4*a*c, // now reuse d for discriminant
        d = d<0 ? !b&c==a ? 'Circle' : 'Ellipse' // now reuse d for end result
        : d ? 'Hyperbola' : 'Parabola'
      ) // exit .some if not 0
    ), d // .some exit with true, the result is in d
  )  
)

परीक्षा

F=p=>[1,2,4].some(x=>(d=D(Q=[[x&1,x&2,x&4,0,0,0],...p.map(([x,y])=>[x*x,x*y,y*y,x,y,1])]))?[a,b,c]=Q.map((v,i)=>D(Q.map((r,j)=>(r=[...r],r[i]=x*!j,r)))/d):0,D=m=>m[1]?m[0].reduce((r,v,i)=>r+(i&1?-v:v)*D(m.slice(1).map(r=>r.filter((a,j)=>j-i))),0):m)&&(d=b*b-4*a*c)?d<0?!b&c==a?'Circle':'Ellipse':'Hyperbola':'Parabola'

console.log=(...x)=>O.textContent+=x+'\n'

;[
 [[0, 0], [1, 5], [2, 3], [4, 8], [9, 2]]
,[[1.2, 5.3],[4.1, 5.6], [9.1, 2.5], [0, 1], [4.2, 0]]
,[[5, 0], [4, 3], [3, 4], [0, 5], [0, -5]]
,[[1, 0], [0, 1], [2, 1], [3, 4], [4, 9]]
].forEach(t=>console.log(t.join`|`+' => '+F(t)))
<pre id=O></pre>


2
यह वास्तव में अच्छा है! उत्कृष्ट कार्य!
एलेक्स ए।

2

पायथन - 234 बाइट्स

import numpy as n
x=input()
d=[n.linalg.det(n.delete(n.array([[i*i,i*j,j*j,i,j,1]for i,j in x]),k,1))for k in range(6)]
t=d[1]**2-4*d[0]*d[2]
print"hyperbola"if t>0else"parabola"if t==0else"circle"if d[1]==0and d[0]==d[2]else"ellipse"

मैं कभी नहीं प्रिंट circleया parabolaक्योंकि tऔर d[1]कभी नहीं मारा 0, लेकिन ओपी ने कहा कि ठीक था।


1

सी, 500

मेरे जावास्क्रिप्ट उत्तर को सी। में रखा गया है बस यह देखने के लिए कि क्या यह किया जा सकता है।

उपयोग: मानक इनपुट से 10 मान पढ़ें

गूंज 1 0 0 1 2 1 3 3 4 4 9 | शंकुधर

आउटपुट:

परवलय

परीक्षण (विचारधारा)

double D(m,k)double*m;{double t=0;for(int s=1,b=1,x=0;x<6;x++,b+=b)k&b||(t+=s*m[x]*(k+b>62?1:D(m+6,k+b)),s=-s);return t;}i,u,h;double m[36],*t=m+6,w[6],s[3],b,d;main(){for(;i++<5;*t++=d*d,*t++=d*b,*t++=b*b,*t++=d,*t++=b,*t++=1)scanf("%lf%lf",&d,&b);for(u=4;u;u/=2)for(m[0]=u&1,m[1]=u&2,m[2]=u&4,d=D(m,0),h=0;d&&h<3;h++){for(i=0;i<6;i++)w[i]=m[i*6+h],m[i*6+h]=i?0:u;s[h]=D(m,0)/d;for(;i--;)m[i*6+h]=w[i];}b=s[1];d=b*b-4*s[0]*s[2];puts(d?d<0?!b&(s[2]==s[0])?"Circle":"Ellipse":"Hyperbola":"Parabola");}

कम गोल्फ वाला

// Calc determinant of a matrix of side d
// In the golfed code, d is fix to 6
double D(m, d, k)
double*m;
{
    int s = 1, b = 1, x = 0;
    double t = 0;
    for (; x < d; x++, b += b)
        k&b || (
            t += s*m[x] *(k+b+1==1<<d? 1: D(  m + d, d, k + b)), s = -s
        );
    return t;
}

double m[36],d, *t = m + 6, w[6], s[3], a, b, c;
i,u,h;
main()
{
    for (; i++ < 5; )
    {
        scanf("%lf%lf", &a, &b);
        *t++ = a*a, *t++ = a*b, *t++ = b*b, *t++ = a, *t++ = b, *t++ = 1;
    }
    for (u = 4; u; u /= 2)
    {
        m[0] = u & 1, m[1] = u & 2, m[2] = u & 4;
        d = D(m, 6, 0);
        if (d) 
            for (h = 0; h < 3; h++)
            {
                for (i = 0; i < 6; i++)
                    w[i] = m[i * 6 + h],
                    m[i * 6 + h] = i ? 0 : u;
                s[h] = D(m, 6, 0)/d;
                for (; i--; )
                    m[i * 6 + h] = w[i];
            }
    }
    a = s[0], b = s[1], c = s[2];
    d = b*b - 4 * a * c;
    puts(d ? d < 0 ? !b&(c == a) ? "Circle" : "Ellipse" : "Hyperbola" : "Parabola");
}

1

ऋषि, 247 बाइट्स

def f(p):
 for i in[1,2,4]:
  z=[i&1,i&2,i&4,0,0,0]
  M=matrix([z]+[[x*x,x*y,y*y,x,y,1]for x,y in p])
  try:A,B,C=(M\vector(z))[:3]
  except:continue
  d=B*B-4*A*C
  return['parabola','hyperbola','circle','ellipse'][[d==0,d>0,d<0and B==0and A==C,d<0].index(1)]

इसे ऑनलाइन आज़माएं

इस समारोह का एक iterable लेता (x,y)इनपुट के रूप में जोड़े 3 संभव रैखिक प्रणालियों (में से प्रत्येक के विभेदक कंप्यूटिंग की कोशिश करता है, A=1, B=1, और C=1,) और शांकव खंड के प्रकार विभेदक, के मूल्यों पर आधारित आउटपुट A, B, और C

वहाँ शायद कुछ और गोल्फिंग किया जाना है, लेकिन मैं ऋषि के साथ जंग खा रहा हूं और अभी नींद आ रही है, इसलिए मैं इस पर सुबह काम करूंगा।

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