Okrąg przez trzy punkty

13

Biorąc pod uwagę współrzędne kartezjańskie trzech punktów na płaszczyźnie, znajdź równanie koła przez wszystkie z nich. Trzy punkty nie będą na linii prostej.

Każdy wiersz danych wejściowych do programu będzie zawierać xi ywspółrzędne trzech punktów, w kolejności A(x),A(y),B(x),B(y),C(x),C(y). Te współrzędne będą liczbami rzeczywistymi mniejszymi niż 1 000 000 oddzielonymi od siebie spacją.

Rozwiązanie należy wydrukować jako równanie formularza (x-h)^2 + (y-k)^2 = r^2. Wartości h, k, rmają być drukowane z trzech cyfr po przecinku. Znaki plus i minus w równaniach należy zmieniać w razie potrzeby, aby uniknąć wielu znaków przed liczbą.

Sample Inputs

7.0 -5.0 -1.0 1.0 0.0 -6.0
1.0 7.0 8.0 6.0 7.0 -2.0

Sample Outputs

(x - 3.000)^2 + (y + 2.000)^2 = 5.000^2
(x - 3.921)^2 + (y - 2.447)^2 = 5.409^2
fR0DDY
źródło
Czy zamiast tego możemy zastosować równania biegunowe lub parametryczne?
Peter Olson
@peter Nie. W ten sposób trudno będzie porównać z innymi odpowiedziami.
fR0DDY 27.04.11
Co należy uzyskać w przypadku, gdy nie ma unikalnego rozwiązania? Jakie są ograniczenia dotyczące niezawodności numerycznej?
Peter Taylor
@ peter-taylor W opisie problemu podano, że „trzy punkty nie będą na linii prostej”.
fR0DDY
2
To prawda, że ​​to tylko kilka znaków, więc to nie jest racja, że ​​moje rozwiązanie może być kilka krótsze, tylko szczere pytanie ... ale jeśli w specyfikacji wyjściowej jest spacja, czy nie powinno to być obowiązkowe? W przeciwnym razie, w golfie kodowym, dlaczego ktokolwiek miałby spełniać specyfikację wyjściową?
Rebecca Chernoff,

Odpowiedzi:

6

Python, 176 189 znaków

import sys,re
for s in sys.stdin:x,y,z=eval(re.sub(r'(\S+) (\S+)',r'\1+\2j,',s));w=z-x;w/=y-x;c=(x-y)*(w-abs(w)**2)/2j/w.imag-x;print'(x%+.3f)^2+(y%+.3f)^2=%.3f^2'%(c.real,c.imag,abs(c+x))

Wykonuje całą swoją pracę w złożonej płaszczyźnie. Idę matematyki od dołu tej strony . -cjest środkiem koła.

Keith Randall
źródło
@Joey: tak, mój zły. Naprawiony.
Keith Randall
2

C # - 490

using System;class C{static void Main(){Func<string,double>p=s=>double.Parse(s);Func<double,string>t=s=>(s<0?"+ ":"- ")+Math.Abs(s).ToString("F3");foreach(var l in System.IO.File.ReadAllLines("i")){var v=l.Split();double a=p(v[0]),b=p(v[1]),c=p(v[2]),d=p(v[3]),e=p(v[4]),f=p(v[5]),m=(d-b)/(c-a),n=(f-d)/(e-c),x=(m*n*(b-f)+n*(a+c)-m*(c+e))/(2*(n-m)),y=-(x-(a+c)/2)/m+(b+d)/2,r=Math.Sqrt((x-a)*(x-a)+(y-b)*(y-b));Console.WriteLine("(x "+t(x)+")^2+(y "+t(y)+")^2 = "+r.ToString("F3")+"^2");}}}

Znajduje 2 linie między AB i BC. Następnie sprawdza, gdzie przecinają się przecięcia tych dwóch linii. (Właśnie zauważyłem, że @PeterTaylor wspomniał w swoim komentarzu do @PeterOfTheCorn.)

Rebecca Chernoff
źródło
2

Ruby, 192 znaki

$<.map{|l|a,b,c,d,e,f=l.split.map &:to_f
n=(f-d)/(e-c)
puts"(x%+.3f)^2+(y%+.3f)^2=%.3f^2"%[x=-(n*(a+c)+(n*(b-f)-(c+e))*m=(d-b)/(c-a))/2/n-=m,y=-(x+(a+c)/2)/m-(b+d)/2,((a+x)**2+(b+y)**2)**0.5]}

Przykłady użycia:

$ echo "7.0 -5.0 -1.0 1.0 0.0 -6.0
1.0 7.0 8.0 6.0 7.0 -2.0" | ruby circle.rb
(x-3.000)^2+(y+2.000)^2=5.000^2
(x-3.921)^2+(y-2.447)^2=5.409^2
Ventero
źródło
Inline do przypisania x, ya rw wywołaniu %powinno pomóc, jeśli to możliwe.
Lowjacker
@Joey: Przepraszam, najwyraźniej przegapiłem to podczas czytania pytania. Naprawiono to teraz.
Ventero,
1

Wolfram Alpha (27)

Mówię: użyj odpowiedniego narzędzia do pracy.

equation circle ([Input1],[Input2]),([Input3],[Input4]),([Input5],[Input6])

Przykład tutaj .

Peter Olson
źródło
6
Brak obsługi danych wejściowych? Brak obsługi wielu linii wejściowych? Powiedziałbym, że to się nie kwalifikuje.
Joey,
0

JavaScript (299)

Jedynym sposobem, w jaki mogłem pomyśleć o rozwiązaniu tego problemu, było rozwiązanie algebraiczne trzech równań dla trzech niewiadomych, aby znaleźć h, k i r.

p=prompt().split(' ');a=p[0],b=p[1],c=p[2],d=p[3],e=p[4],f=p[5];h=((a*a+b*b)*(f-d)+(c*c+d*d)*(b-f)+(e*e+f*f)*(d-b))/(a*(f-d)+c*(b-f)+e*(d-b))/2;k=((a*a+b*b)*(e-c)+(c*c+d*d)*(a-e)+(e*e+f*f)*(c-a))/(b*(e-c)+d*(a-e)+f*(c-a))/2;r=Math.sqrt((a-h)*(a-h)+(b-k)*(b-k));alert("(x-"+h+")²+(y-"+k+")²="+r+"²");

Przykład I / O:

7.0 -5.0 -1.0 1.0 0.0 -6.0 -> (x-3)²+(y--2)²=5²

1.0 7.0 8.0 6.0 7.0 -2.0 -> (x-3.9210526315789473)²+(y-2.4473684210526314)² =5.409159155551175²

Jedyny błąd, który widzę, to to, że jeśli h lub k jest ujemne, to wypisuje --zamiast +.

Peter Olson
źródło
2
Można to zrobić za pomocą kompasu i prostej krawędzi. Weź dwa punkty, narysuj linię, która je przecina. Weź inną parę dwóch punktów, to samo. Znajdź skrzyżowanie. Czy prowadzi to do skrócenia kodu, muszę to zbadać.
Peter Taylor
To obsługuje tylko jeden wiersz danych wejściowych, prawda?
Joey,
@Joey, tak. Czy problem wymaga obsługi wielu linii?
Peter Olson,
1
Cytując z zadania: »Każdy wiersz danych wejściowych do programu będzie zawierał współrzędne xiy trzech punktów ...«
Joey,