Well, then I have no idea what my error is. Here's my convoluted code and reasoning about what it's supposed to do.
Here's the general idea of my code:
First I look for non-positive values, and if there are any, return "bad" which means to print invalid input.
Then I check that the angles don't sum to past pi, and the sides don't contradict the triangle inequality, if so I return bad;
then I look to see if I know all the sides, if so I call the SSS method, it calculates all the unknown angles (and checks if the input values contradict them). Thus I either know to return bad or return the actual values.
The rest of the code is similar. I look to see if I can use SAS next and then ASA (AAS is taken care of by ASA, since two angles give the third, so I don't need a function for that).
Since there are three possible angles to use for SAS I rotate the triangle three times (the for loop) and the pn array is used to do the rotation. I do a similar thing for ASA and SSA. I'm pretty sure this works right, since I've tested each of the three configurations on each of those. This way in the SAS method I can assume that a,alpha, and b are set correctly by the input (similarly for the other methods).
I'm less confident in my SSA method, it determines if there's no, one, or multiple solutions (by returning 0, 1, or 6 respectively). And I use
http://www.andrews.edu/~calkins/math/we ... 07.htm#AAA for the general reasoning behind this method.
I'm guessing the problem is with precision somewhere, or a corner case that I just haven't stumbled upon.
Code: Select all
/*Parts removed*/
//returns true if a is strictly less than b
bool lesser(long double a,long double b);
//returns true if a is less than or equal to b
bool lessequal(long double a,long double b);
//returns true if the input number is -1
bool used(long double d);
//returns true if a is equal to b, with precision .000 000 01
bool close(long double a,long double b);
//returns true if there's something wrong with the angles
bool anglesum(long double& alpha,long double& beta,long double& gamma){
int u=0;
if(used(alpha)) u++;
if(used(beta)) u++;
if(used(gamma)) u++;
if(u<2) return false;
if(u==3) return !close(alpha+beta+gamma,pi);
if(!used(alpha)){
if(lessequal(pi,beta+gamma)) return true;
alpha=pi-beta-gamma;
}
if(!used(beta)){
if(lessequal(pi,alpha+gamma)) return true;
beta=pi-alpha-gamma;
}
if(!used(gamma)){
if(lessequal(pi,alpha+beta)) return true;
gamma=pi-beta-alpha;
}
return false;
}
//returns true if there's something wrong with the sides
bool sidesum(long double& a,long double& b,long double& c){
int u=0;
if(used(a)) u++;
if(used(b)) u++;
if(used(c)) u++;
if(u<3) return false;
if(lessequal(a+b,c)) return true;
if(lessequal(c+b,a)) return true;
if(lessequal(a+c,b)) return true;
return false;
}
//called only if you know three sides of a triangle
//returns true if there's a contradiction
//otherwise sets all the angles
bool sss(long double& a,long double& alpha,long double& b,long double& beta,long double& c,long double& gamma){
long double nalpha=acos((a*a-b*b-c*c)/(-2*b*c));
if(used(alpha) && !close(alpha,nalpha))
return true;
alpha=nalpha;
long double nbeta=acos((b*b-a*a-c*c)/(-2*a*c));
if(used(beta) && !close(beta,nbeta))
return true;
beta=nbeta;
long double ngamma=acos((c*c-a*a-b*b)/(-2*a*b));
if(used(gamma) && !close(gamma,ngamma))
return true;
gamma=ngamma;
return false;
}
//called only if you know two sides and the angle between
//returns true if there's a contradiction
//otherwise sets all the other fields
bool sas(long double& c,long double& alpha,long double& b,long double& gamma,long double& a,long double& beta);
//called only if you know two angles(and therefore the third) and a side
//returns true if there's a contradiction
//otherwise sets all the other fields
bool asa(long double& gamma,long double& a,long double& beta,long double& c,long double& alpha,long double& b);
//called only if you know two sides and an angle not between them
//returns 0 if there's a contradiction
//returns 1 if there are two triangles
//otherwise sets all the other fields and returns 6
int ssa(long double& a,long double& b,long double& alpha,long double& beta,long double& c,long double& gamma);
//returns an empty vector on invalid inputs
//returns a singleton on multiple solutions
//returns all the data if it can be found
vector<long double> solve(vector<long double> v){
vector<long double> bad;
// if any of the sides or angles are out of range, invalid input
for(int i=0;i<v.size();i+=2)
if(side(v[i]))
return bad;
for(int i=1;i<v.size();i+=2)
if(angle(v[i]))
return bad;
if(anglesum(v[1],v[3],v[5])) return bad;
if(sidesum(v[0],v[2],v[4])) return bad;
//side side side
if(used(v[0]) && used(v[2]) && used(v[4])){
if(sss(v[0],v[1],v[2],v[3],v[4],v[5]))
return bad;
return v;
}
//the fields of the triangle, clockwise (0=a, 1=alpha,2=b,3=beta,4=c,5=gamma)
int pn[]={0,3,4,1,2,5};
//side angle side
for(int k=0;k<6;k+=2){
if(used(v[pn[k%6]]) && used(v[pn[(1+k)%6]]) && used(v[pn[(2+k)%6]])){
if(sas(v[pn[k%6]],v[pn[(k+1)%6]],v[pn[(k+2)%6]],v[pn[(k+3)%6]],v[pn[(k+4)%6]],v[pn[(k+5)%6]]))
return bad;
return v;
}
}
//angle side angle
for(int k=1;k<6;k+=2){
if(used(v[pn[k%6]]) && used(v[pn[(1+k)%6]]) && used(v[pn[(2+k)%6]])){
if(asa(v[pn[k%6]],v[pn[(k+1)%6]],v[pn[(k+2)%6]],v[pn[(k+3)%6]],v[pn[(k+4)%6]],v[pn[(k+5)%6]]))
return bad;
return v;
}
}
//side side angle
//look at 3 possibilities
for(int k=0;k<6;k+=2){
if(used(v[pn[k%6]]) && used(v[pn[(4+k)%6]]) && used(v[pn[(3+k)%6]])){
int t=ssa(v[pn[k%6]],v[pn[(k+4)%6]],v[pn[(k+3)%6]],v[pn[(k+1)%6]],v[pn[(k+2)%6]],v[pn[(k+5)%6]]);
if(t==0) return bad;
if(t==1) return vector<long double>(1);
return v;
}
}
//take the reflection and look at the other 3
for(int k=0;k<6;k+=2){
if(used(v[pn[k%6]]) && used(v[pn[(2+k)%6]]) && used(v[pn[(3+k)%6]])){
int t=ssa(v[pn[k%6]],v[pn[(k+2)%6]],v[pn[(k+3)%6]],v[pn[(k+5)%6]],v[pn[(k+4)%6]],v[pn[(k+1)%6]]);
if(t==0) return bad;
if(t==1) return vector<long double>(1);
return v;
}
}
return bad;
}