원뿔 섹션 식별


13

2 차원 평면에 5 개의 별개의 점이 주어지면 점으로 구성된 원뿔형 섹션의 유형을 결정하십시오. 출력 중 하나 여야한다 circle, hyperbola, ellipse, 또는 parabola.

규칙

  • 점은 일반적인 선형 위치에있을 것입니다. 즉, 3 개의 점이 동일 선상에 있지 않으므로 점을 통과하는 원뿔이 고유합니다.
  • 5 점의 좌표는 -10에서 10 사이의 10 진수입니다.
  • 10 진수 / float 값의 정밀도는 사용자 언어의 고유 float / decimal 유형의 정밀도 여야합니다. 언어 / 데이터 유형이 임의의 정밀도 인 경우 소수점 다음 12 자리를 최대 필수 정밀도로 사용할 수 있습니다 (예 :) 1.0000000000005 == 1.000000000000.
  • 결과의 대문자는 중요하지 않습니다.
  • ellipse원뿔 섹션이 실제로 원일 때의 출력 은 허용되지 않습니다. 모든 원은 타원이지만 가장 구체적인 원을 출력해야합니다.

부동 소수점 부정확성과 정밀도 :

부동 소수점 부정확성 문제가 발생하지 않도록 가능한 한 간단하게하려고합니다. 데이터 유형이 float / double 대신 "magical infinite precision value"이면 모든 것이 완벽하게 작동합니다. 그러나 "마법의 무한 정밀도 값"은 존재하지 않으므로 값이 무한정이라고 가정하고 부동 소수점 부정확의 결과로 발생하는 문제는 버그가 아닌 기능입니다.

테스트 사례

(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)를
허용합니까?

1
테스트 사례 4가 맞습니까? desmos : desmos.com/calculator/fmwrjau8fd
Maltysen

2
또한 3도 잘못 보입니다 : desmos.com/calculator/tkx1wrkotd
Maltysen

1
나는이 같은 대답에 FP 정확도 문제, 그리고 리드를 understimating 생각 codegolf.stackexchange.com/a/77815/21348
edc65

답변:


2

Matlab, 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)))}

Suever의 제안 덕분에 바이트를 절약했습니다.

로 입력을 [x1 y1;x2 y2;x3 y3; etc]받습니다. 이것은 Vandermonde 행렬을 사용하고 항상 단일 벡터가 될 null 공간의 기초를 찾습니다. 그런 다음 판별자를 계산하고이를 사용하여 문자열을 얻는 데 사용되는 1과 4 사이의 색인을 만듭니다.

언 골프 드 :

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, 음수 (1)이면 -1, 0 (포물선)이면 0을 제공합니다. max(...)감산 한 멀리는 원형 인 경우. Matlab 배열은 1- 인덱싱되므로 3을 추가하여 값 1, 2, 3, 4를 제공하고이를 사용하여 원뿔 섹션 이름 배열을 인덱싱하십시오.


1
비교하기보다는 다음과 max() == 0같이 단순화 할 수 있습니다.~max()
Suever

1
또한 ones(length(p),1)당신 대신에1+p(:,1)*0
Suever

건배, 그 max()일은 나에게 어리석은 일이었다. 나는 전에 거기에서 비교를 했었고, 게으르게되었다! 그것을 얻는 방법 ones도 매우 좋습니다.
David

14

자바 스크립트 (ES6), 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)

참고 : 원뿔의 일반적인 형태는 , 5 점은 원뿔 결정 , 선형 방정식의 시스템 , 행렬식

직교 평면에서 원뿔의 일반 방정식은 다음과 같습니다.

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

A 또는 B 또는 C가 0과 같지 않은 경우 (그렇지 않으면 직선 임)

A ... F는 6 개의 미지수입니다. 5 쌍의 (x, y)를 사용하면 5 개의 방정식으로 선형 시스템을 구축 할 수 있으며 스케일링은 1 차원을 제거합니다. 즉, 0이 아닌 경우 A, B 또는 C 중 하나를 1로 설정할 수 있습니다 (그리고 우리는 적어도 하나가 0이 아님을 알고 있습니다).

나는 3 개의 시스템을 구축하고 해결하려고 시도합니다. 해결할 수 없다면 B = 1, C입니다 (더 나은 방법이있을 수 있지만 그 당시에는 최선입니다)

A, B, C의 값을 가짐으로써 판별자를보고 원뿔을 분류 할 수 있습니다 d=B*B-4*A*C

  • d == 0-> 포물선
  • d> 0-> 쌍곡선
  • d <0-> 타원, 특히 (A == C 및 B == 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
정말 좋습니다! 잘했습니다!
Alex A.

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"

나는 인쇄 결코 circleparabola때문에 t그리고 d[1]정확히 명중 결코 0, 영업 이익은 괜찮다고 말했다.


1

C, 500

내 JavaScript 답변은 C로 이식되었습니다. 단지 할 수 있는지 확인하십시오.

사용법 : 표준 입력에서 10 개의 값을 읽습니다.

에코 1 0 1 2 1 3 4 4 9 | 원뿔

산출:

포물선

테스트 (ideone)

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)]

온라인으로 사용해보십시오

이 함수의 반복 가능한 얻어 (x,y)3- 가능한 선형 시스템 (각각의 판별을 계산하려고 입력으로 쌍 A=1, B=1C=1), 및 판별의 값에 따라 원뿔 곡선의 형태로 출력한다 A, B, 및 C.

골프를 더해야 할지도 모르지만 지금은 현자와 녹슬고 졸려서 아침에 더 많은 운동을 할 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.