Círculo através de três pontos


13

Dadas as coordenadas cartesianas de três pontos em um plano, encontre a equação do círculo através de todas elas. Os três pontos não estarão em linha reta.

Cada linha de entrada para o seu programa conterá as coordenadas xe yde três pontos, na ordem A(x),A(y),B(x),B(y),C(x),C(y). Essas coordenadas serão números reais menores que 1.000.000 separados um do outro pelo espaço.

A solução deve ser impressa como uma equação do formulário (x-h)^2 + (y-k)^2 = r^2. Os valores para h, k, rdevem ser impressos com três dígitos após o ponto decimal. Os sinais de mais e menos nas equações devem ser alterados conforme necessário para evitar vários sinais antes de um 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

Podemos usar equações polares ou paramétricas?
27611 Peter Olson

@ Peter Não. Dessa forma, será difícil comparar com outras respostas.
FR0DDY

O que deve ser produzido no caso de não haver uma solução única? Que restrições existem na robustez numérica?
Peter Taylor

@ peter-taylor É indicado na declaração do problema que 'os três pontos não estarão em linha reta'.
FR0DDY

2
É verdade que são apenas alguns caracteres, portanto, não é um discurso retórico que minha solução possa ser um pouco mais curta, apenas uma pergunta honesta ... mas se houver espaço em branco na especificação de saída, não seria obrigatório? Caso contrário, em um código-golfe, por que alguém atenderia às especificações de saída?
Rebecca Chernoff

Respostas:


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

Faz todo o seu trabalho no plano complexo. Eu vou a matemática no final desta página . -cé o centro do círculo.


@ Joey: sim, meu mal. Fixo.
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");}}}

Ele encontra as 2 linhas entre AB e BC. Em seguida, ele encontra onde os bissetos dessas duas linhas se cruzam. (O que acabei de notar é o que @PeterTaylor mencionou em seu comentário a @PeterOfTheCorn.)


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

Exemplos 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

Inlining as atribuições para x, ye rna chamada para %deve ajudar, se possível.
Lowjacker

@ Joey: Desculpe, aparentemente perdeu isso ao ler a pergunta. Corrigido agora.
Ventero

1

Wolfram Alpha (27)

Eu digo, use a ferramenta adequada para o trabalho.

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

Exemplo aqui .


6
Sem manipulação de entrada? Não há suporte para várias linhas de entrada? Eu diria que isso não se qualifica.
Joey

0

Javascript (299)

A única maneira de pensar em resolver isso foi resolver algebricamente três equações para três incógnitas encontrarem h, ke er.

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+"²");

Exemplo 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²

O único bug que vejo é que, se h ou k for negativo, ele será exibido em --vez de +.


2
Isso pode ser feito com bússola e borda reta. Pegue dois pontos, desenhe a linha que os corta. Pegue um par diferente de dois pontos, o mesmo. Encontre o cruzamento. Se isso leva a um código mais curto, ainda tenho que investigar.
27411 Peter

Isso lida com apenas uma única linha de entrada, certo?
Joey

@ Joey, sim. O problema requer manipulação de várias linhas?
Peter Olson

1
Citando a tarefa: »Cada linha de entrada para o seu programa conterá as coordenadas xey de três pontos ...«
Joey
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.