4

I studied this link and coded accordingly but getting Wrong Answer for the example explained in the link, During solving the equation, I subtracted equation 2 from equation 1 and equation 3 from equation 2 and then proceed further. Please check link for clarification.

My code is:

include<stdio.h>
int is_formCircle(float a1,float b1,float a2,float b2,float a3,float b3) {
  float p1=a2-a1;
  float p2=a3-a2;
  float p3=b2-b1;
  float p4=b3-b2;
  float alpha=(a1+a2)*(a1-a2) + (b1+b2)*(b1-b2);
  float beta =(a2+a3)*(a2-a3) + (b2+b3)*(b2-b3);
  float y1=p1*beta - p2*alpha;
  float y2=p2*p3 - p1*p4;
  if(y2==0 || y1==0) return 1;
  float y=y1/y2;
  float x1 = 2*p4*y + beta;
  float x2 = 2*p2;
  float x = x1/x2;
  printf("x=%f  y=%f\n",x,y);
  return 0;
}
int main() {
 float a1,a2,a3,a4,b1,b2,b3,b4;
 a1=4.0;
 b1=1.0;
 a2=-3.0;
 b2=7.0;
 a3=5.0;
 b3=-2.0;
 is_formCircle(a1,b1,a2,b2,a3,b3);
 return 0;
}

MY another Code:

#include<stdio.h>
int is_formCircle(float a1,float b1,float a2,float b2,float a3,float b3) {                  
  float mid1,mid2,mid3,mid4,m1,m2,D,Dx,Dy,x,y;
  mid1 = a1+(a2-a1)/2;
  mid2 = b1+(b2-b1)/2;
  mid3 = a2+(a3-a2)/2;
  mid4 = b2+(b3-b2)/2;
  m1=(b2-b1)/(a2-a1);
  m2=(b3-b2)/(a3-a2);
  m1=-1*m1;
  m2=-1*m2;
  D=m2-m1;
  Dx=mid2-(m1*mid1) + (mid3*m2) - mid4;
  Dy=(m1*(mid3*m2-mid4))-(m2*(mid1*m1-mid2));
  x=Dx/D;
  y=Dy/D;
  printf("%f %f",x,y);    
  return 0;
}
int main() {
 float a1,a2,a3,b1,b2,b3;      
 a1=4.0;
 b1=1.0;
 a2=-3.0;
 b2=7.0;
 a3=5.0;
 b3=-2.0;
 is_formCircle(a1,b1,a2,b2,a3,b3);      
 return 0;
}

Why my code giving Wrong Answer?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
avinashse
  • 1,440
  • 4
  • 30
  • 55
  • 1
    Readable code, please. How could you debug this even if it is a contest? – zw324 Jul 09 '13 at 13:56
  • 6
    `typedef double f;` **YUCK!** There's no excuse for that. – Daniel Fischer Jul 09 '13 at 13:56
  • Where do you submit the task to? – Boris Strandjev Jul 09 '13 at 13:57
  • @BorisStrandjev I am not submitting this code anywhere but I have to use this thing in another part of my code. I have choose values from the example in the link where answers are h=-13/2(x in my code) and k=-25/2(y in my code) but I am not getting that value. – avinashse Jul 09 '13 at 14:05
  • @DanielFischer I was using `typedef float f` but I thought float might be creating problem so I changed it to double – avinashse Jul 09 '13 at 14:06
  • @avinashse: I hope you are getting that doing typedef is affecting the readability of your code.That is what he is saying.Not about the precision. – Aravind Jul 09 '13 at 14:07
  • 1
    @avinashse `typedef float f;` isn't better. The types have names for a reason. Use them. – Daniel Fischer Jul 09 '13 at 14:08
  • 1
    @Aravind Sorry for the readability,I used that typedef if I have to change datatype so i just have to change in one line, id its creating inconvenience then sorry :( – avinashse Jul 09 '13 at 14:09
  • @DanielFischer Several years ago I wrote some code that I expected to need to run with different floating point types, including extended precision on some systems and interval arithmetic. I wrote it using a typedef for the floating point type, and only had to change one line in one header file to switch types. Very convenient. I did use something more meaningful than "f". – Patricia Shanahan Jul 09 '13 at 22:37
  • @PatriciaShanahan Yes, `typedef double float_type;` (or `real`, if you like) is okay, you give the type another meaningful name. `typedef whatever a;` is different. – Daniel Fischer Jul 09 '13 at 22:42

2 Answers2

4

The solution that was given in the link is a "blind" solution, i.e., you know the equation, boom solve it.

However, if you understand more deeply what is behind the scene, you will be able to:

  1. Write a more readable, reliable, flexible code.
  2. Debug easily.

What happen when you substract equation 1 from equation 2? You actually try to find the equation of the straight line describing those points which are equidistant from the point 1 and the point 2. Then, you do the same with point 2 and 3. Finally, you find the intersection between these to lines, which gives you the center of the circle.

How do you describe the straight line of the points equidistant to the point 1 and 2? You take the point that is in the middle of the two, and go in the direction perpendicular to the direction between point 1 and 2.

If this is not absolutly clear, take a paper and draw an example: put points 1,2 and 3, find the two lines and find the intersection.

Now that you understood everything, reshape your code with two functions, on that find the line equidistant between two points, another one which compute the intersection between two lines...


After your edit, the code looked better, although it was not simple to understand. I think that the mistake is when you solve for the intersection of the two lines, do not forget that you are under parametric form:

Dx = (mid4-mid2) - m2*(mid3-mid1);

lambda=Dx/D;

x = mid1 + lambda*m1;
y = mid2 + lambda*1.0;

Checked graphically using Matlab.

Dr_Sam
  • 1,818
  • 18
  • 24
  • Thanks for the reply.. I edited my code and perhaps did same thing what you have said, found mid points of two points and slope for perpendicular bisector of the line joining that two point and then form the equation for that perpendicular bisector which is next solved to find the center of the circle. – avinashse Jul 09 '13 at 14:46
  • thank you for the reply, I am having one query.what I am doing is I have to check forth point is lying inside,outside or on the circle, For e.g, let there be for point A,B,C,D . I am finding the center of circle A,B,C and then calculating the radius(R) and then calculating |AD|. If (|AD| > R) point D is outside the circle, so Is there any other fast way to do it..? – avinashse Jul 10 '13 at 06:00
  • @avinashse Beware that you should compute |KD| where K is the center of the circle, not |AD|. Otherwise, that looks fine. You can also test |KD|^2 > R^2 so that you do not need a square root, but that's not a big optimization. – Dr_Sam Jul 10 '13 at 06:28
  • ohh yes it should be KD..sorry my mistake, I want to ask is this the only way to find whether a point is inside a circle, if suppose there are 30 points and I have to check for each three points how many points are on or inside the circle then will this be an optimal way to solve. i.e., there will be 30C3 = 4060 circles can be formed and for each circle I have to check for other 27 points which are not included in circle formation whether they are inside the circle,if inside then increase the count. Is there any other fast way to do this ? – avinashse Jul 10 '13 at 08:16
  • @avinashse Hmmm difficult question. I don't see any better way / shortcut that could be taken. Is this related to a particular problem or is it just a test case? – Dr_Sam Jul 10 '13 at 09:13
4

I have to say, if you're following the link you listed, it would've helped to keep the variable names the same. We could understand the algorithm much better seeing x1, y1, x2, y2, x3, y3 instead of p1, p2, p3, p4, alpha and beta. In fact, I don't see much in your algorithm that matches the link. I'm not trying to be as harsh as the comments were (and if you're worried about switching float to double, that was a perfectly good case for a typedef), but debugging algorithms is easiest when you don't have to convert variable names.

I would recommend simply using what they give you for h and k in the link, which is namely done by calculating determinants of 3x3 matrices. You can find lots of references for that.

I'd make two functions, as follows:

float calculateH(float x1, float y1, float x2, float y2, float x3, float y3) {
    float numerator = (x2*x2+y2*y2)*y3 - (x3*x3+y3*y3)*y2 - 
                      ((x1*x1+y1*y1)*y3 - (x3*x3+y3*y3)*y1) +
                      (x1*x1+y1*y1)*y2 - (x2*x2+y2*y2)*y1;
    float denominator = (x2*y3-x3*y2) -
                        (x1*y3-x3*y1) +
                        (x1*y2-x2*y1);
    denominator *= 2;
    return numerator / denominator;
}
float calculateK(float x1, float y1, float x2, float y2, float x3, float y3) {
    float numerator = x2*(x3*x3+y3*y3) - x3*(x2*x2+y2*y2) -
                      (x1*(x3*x3+y3*y3) - x3*(x1*x1+y1*y1)) +
                      x1*(x2*x2+y2*y2) - x2*(x1*x1+y1*y1);
    float denominator = (x2*y3-x3*y2) -
                        (x1*y3-x3*y1) +
                        (x1*y2-x2*y1);
    denominator *= 2;
    return numerator / denominator;
}

Then your is_formCircle would simply be:

float is_formCircle(float x1, float y1, float x2, float y2, float x3, float y3) {
    float h = calculateH(x1, y1, x2, y2, x3, y3);
    float k = calculateK(x1, y1, x2, y2, x3, y3);
    printf("x=%f  y=%f\n",h,k);
}

There are tons of ways to optimize this, and there's a chance I typoed any of the determinant calculations, but it should get you going.

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
  • Thank You.. I did same thing using paper and pen and formulize the thing in my code but not working but this is working perfectly.. – avinashse Jul 09 '13 at 15:16
  • 1
    You're welcome. I notice that your code is actually a boolean check, to see if you can form a circle from the three points. The answer (as you can guess from Dr_Sam's explanation) is always "yes" - unless the three points are colinear. If they are, in this calculation, the determinant in the denominator will evaluate to 0. – Scott Mermelstein Jul 09 '13 at 15:32
  • Yes I thought about this, three points will always form circumcircle unless they are collinear, what I am doing is I have to check forth point is lying inside,outside or on the circle, For e.g, let there be for point A,B,C,D . I am finding the center of circle A,B,C and then calculating the radius(R) and then calculating |AD|. If (|AD| > R) point D is outside the circle, so Is there any fast way to do it..? – avinashse Jul 10 '13 at 05:58
  • 1
    @avinashse That's a much more interesting problem, and you should probably pose it as another question - not that I'm hunting reputation, but since this question is answered, very few people will pay attention to it. (It might go better on math.stackexchange.com.) Offhand, I have an answer that will be relatively fast, but I'm not sure if it's sufficient. Simply go through your 4060 combinations of triplets, and figure out the distances between them. I don't have a proof for it, but would expect you want the circle ABC such that |AB| + |BC| is maximized. That should include the most points. – Scott Mermelstein Jul 10 '13 at 14:41
  • Will there by any precision problem when using (numerator/denominator) ?? – avinashse Jul 11 '13 at 11:07
  • @avinashse I'll probably annoy anyone who's paying attention, but my answer is: depending on your application's needs, most likely there's no problem. There are some who say that `float` is horrible all the time, but it's good for about 6-8 significant figures. In most cases, that's sufficient. This is where that `typedef double f` you started with would come in handy - if you see the precision isn't sufficient, change all your floats to doubles. – Scott Mermelstein Jul 11 '13 at 14:17