Circula a través de tres puntos

13

Dadas las coordenadas cartesianas de tres puntos en un plano, encuentra la ecuación del círculo a través de todos ellos. Los tres puntos no estarán en línea recta.

Cada línea de entrada a su programa contendrá las coordenadas xy yde tres puntos, en el orden A(x),A(y),B(x),B(y),C(x),C(y). Estas coordenadas serán números reales menos de 1,000,000 separados entre sí por el espacio.

La solución debe imprimirse como una ecuación del formulario (x-h)^2 + (y-k)^2 = r^2. Los valores para h, k, rse van a imprimir con tres dígitos después del punto decimal. Los signos más y menos en las ecuaciones deben cambiarse según sea necesario para evitar múltiples signos antes de un número.

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
fuente
¿Podemos usar ecuaciones polares o paramétricas en su lugar?
Peter Olson
@peter No. De esa manera será difícil compararlo con otras respuestas.
fR0DDY
¿Cuál debería ser la salida en caso de que no haya una solución única? ¿Qué limitaciones hay en la solidez numérica?
Peter Taylor
@ peter-taylor En el enunciado del problema se indica que "los tres puntos no estarán en línea recta".
fR0DDY
2
De acuerdo, son solo unos pocos caracteres, por lo que esta no es una queja porque mi solución podría ser un poco más corta, solo una pregunta honesta ... pero si el espacio en blanco está en la especificación de salida, ¿no debería ser obligatorio? De lo contrario, en un código de golf, ¿por qué alguien cumpliría con las especificaciones de salida?
Rebecca Chernoff

Respuestas:

6

Python, 176 189 caracteres

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

Hace todo su trabajo en el plano complejo. Voy a las matemáticas desde el final de esta página . -cEs el centro del círculo.

Keith Randall
fuente
@Joey: sí, mi mal. Fijo.
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");}}}

Esto encuentra las 2 líneas entre AB y BC. Luego encuentra dónde se intersecan las bisectas de esas 2 líneas. (Lo que acabo de notar es lo que @PeterTaylor mencionó en su comentario a @PeterOfTheCorn).

Rebecca Chernoff
fuente
2

Ruby, 192 caracteres.

$<.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]}

Ejemplos de uso:

$ 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
fuente
Alinear las asignaciones a x, yy ren la llamada a %debe ayudar, si es posible.
Lowjacker
@Joey: Lo siento, aparentemente me perdí eso al leer la pregunta. Lo arregló ahora.
Ventero
1

Wolfram Alpha (27)

Yo digo, use la herramienta adecuada para el trabajo.

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

Ejemplo aquí .

Peter Olson
fuente
66
¿Sin manejo de entrada? ¿No hay soporte para múltiples líneas de entrada? Yo diría que esto no califica.
Joey
0

Javascript (299)

La única forma en que podía pensar en resolver esto era resolviendo algebraicamente tres ecuaciones para tres incógnitas para encontrar h, k y 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+"²");

Ejemplo de E / S:

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²

El único error que veo es que si h o k es negativo, se genera en --lugar de +.

Peter Olson
fuente
2
Se puede hacer con brújula y borde recto. Toma dos puntos, dibuja la línea que los divide. Tome un par diferente de dos puntos, lo mismo. Encuentra la intersección. Si eso lleva a un código más corto, todavía tengo que investigar.
Peter Taylor
Esto maneja solo una línea de entrada, ¿verdad?
Joey
@ Joey, sí. ¿El problema requiere manejo de múltiples líneas?
Peter Olson
1
Citando la tarea: »Cada línea de entrada a su programa contendrá las coordenadas x e y de tres puntos ...«
Joey