Tess L. Ation ran into a little problem last week when she demonstrated the beta version of her new drawing software. On the screen she had an elegant demonstration design that illustrated every feature of her program; it had taken her hours to produce it. She was just putting the finishing touches on it as a group of potential investors entered the room to see the demonstration.
The presentation went well. Near the end, Tess clicked on a control panel button and told her audience, ``This is the `snap to grid' control. It forces control points, such as vertices, to jump to the nearest grid point. Here, let me show you," and she placed three bright red dots on the screen. Each one appeared at the grid point nearest to where she clicked. (``Luckily all control points in my demo design were already at integer coordinates. But I will have to remember to delete these three red dots before I save my diagram," she thought to herself.) ``Now I'll step into the next room and get out of your way so you can discuss the system among yourselves and get a closer look at the screen, but please don't touch anything, since I haven't saved that file yet."
A few minutes later, the group joined Tess. One of the visitors stepped up to Tess and said, ``I hope you don't mind, but I wanted to try it myself. Don't worry, I just played with the x-scale and y-scale controls a little bit." The next person said, ``Sorry if this is a problem, but I really wanted to get a feel for the speed of display, so I just played around with the translation tool." And a third person said, ``I couldn't resist just one tiny test: I rotated the image just so I could see all of the vertices snap to the nearest grid points after the rotation."
The person who played with the rotation tool remembered going first, but the other two could not recall their order. The three remembered only a few details of the changes. The x- and y-scaling factors had been (possibly negative) nonzero integers; the center of scaling was the origin (0, 0). The x- and y-translation amounts had been integers. Rotation had been specified by a point with integer coordinates (x, y) on the perimeter of a square of width 20 centered at the origin (hence, -10x, y
10 and the absolute value of xor y or both was 10). The tool rotated the drawing around the origin such that the positive x-axis would pass through (x, y) afterwards. Snapping took place after this rotation (coordinates with a fractional part of 0.5 were rounded away from zero).
After they left, Tess looked at her design -- it was completely changed! She had not yet implemented the ``undo" feature, and she had not saved the diagram prior to giving the demonstration. However, the three identical red dots were still there (transformed to other integer grid locations, of course), and Tess could remember the integer coordinates where she had originally placed them. Obviously, someone else might have altered the drawing without saying anything to her, but she could write a program to see if it was possible to reconstruct the sequence of alterations. Can you too?
Input
The input contains several test cases. Each test case consists of six pairs of integers xi and yi ( -500xi, yi
500 for 1
i
6), three pairs per input line. The first three pairs represent the distinct initial locations of the three red dots. The last three pairs represent the distinct final locations of the three dots. The indexing of the pairs in each group of three is not significant: for example, (x1, y1) could have been mapped to any of (x4, y4), (x5, y5) or (x6, y6).
The last test case is followed by a line with six zeros.
Output
For each test case, display its case number followed by one of the following three messages:
- ``equivalent solutions" to indicate that there are one or more valid transformations, and of them have the same effect on the whole drawing (no matter what the whole drawing looks like).
- ``inconsistent solutions" to indicate that there are several valid transformations, but in general not all of them map the entire drawing in the same way (some drawing is mapped differently by two valid transformations).
- ``no solution" to indicate that neither of the first two cases occurs.
A valid transformation is a combination of rotation, translation and scaling (or rotation, scaling and translation) which satisfies the restrictions described above and maps the initial set of red dots to the final set (occupying all three final locations).
Follow the format of the sample output.
Sample Input
3 0 4 0 1 4 -2 -4 -1 3 3 -4 0 1 1 1 2 1 1 2 2 2 3 2 1 0 2 0 3 0 3 3 1 1 2 2 1 0 2 0 3 0 3 2 1 1 2 2 2 3 0 6 1 2 2 3 0 6 1 2 0 0 0 0 0 0
Sample Output
Case 1: equivalent solutions Case 2: inconsistent solutions Case 3: no solution Case 4: inconsistent solutions Case 5: equivalent solutions
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<string>
#include<math.h>
#include<vector>
using namespace std;
#define MP make_pair
#define PB push_back
#define key1 first.first
#define key2 first.second
#define key3 second.first
#define key4 second.second
int abs(int x)
{
return x<0?-x:x;
}
struct Matrix
{
double v[3][3];
}RotMatrix;
struct Vector
{
double X,Y;
}pf[4],_p[4];
struct Vector_int
{
int X,Y;
}p[4],q[4];
int ax,ay;
vector<pair<pair<int,int>, pair<int,int>>> Trans;
bool used[10000],line;
Vector operator * (Vector A,Matrix B)
{
double xx=A.X*B.v[1][1] + A.Y*B.v[1][2];
double yy=A.X*B.v[2][1] + A.Y*B.v[2][2];
Vector Ret;
Ret.X==xx;Ret.Y==yy;return Ret;
}
int snap(double num)
{
if(num>=0)
return (int)(num+0.5);
else
return -snap(0.0-num);
}
void Check(int _id1,int _id2,int _id3,int Rot_x,int Rot_y)
{
pf[_id1]=_p[1];pf[_id2]=_p[2];pf[_id3]=_p[3];
double costh=Rot_x/sqrt(double(Rot_x*Rot_x+Rot_y*Rot_y));
double sinth=Rot_y/sqrt(double(Rot_x*Rot_x+Rot_y*Rot_y));
RotMatrix.v[1][1]=costh;
RotMatrix.v[1][2]=-sinth;
RotMatrix.v[2][1]=sinth;
RotMatrix.v[2][2]=costh;
pf[1]=pf[1]*RotMatrix;
pf[2]=pf[2]*RotMatrix;
pf[3]=pf[3]*RotMatrix;
p[1].X=snap(pf[1].X);p[1].Y=snap(pf[1].Y);
p[2].X=snap(pf[2].X);p[2].Y=snap(pf[2].Y);
p[3].X=snap(pf[3].X);p[3].Y=snap(pf[3].Y);
ax=0;
if(q[1].X-q[2].X!=0&&p[1].X-p[2].X!=0)
{
if(abs(q[1].X-q[2].X)%abs(p[1].X-p[2].X)==0)
{
if(ax==0)
ax=(q[1].X-q[2].X)/(p[1].X-p[2].X);
else if((q[1].X-q[2].X)/(p[1].X-p[2].X)!=ax)
return;
}
else
return;
}
else if(q[1].X-q[2].X!=0||p[1].X-p[2].X!=0)
return;
if(q[1].X-q[3].X!=0&&p[1].X-p[3].X!=0)
{
if(abs(q[1].X-q[3].X)%abs(p[1].X-p[3].X)==0)
{
if(ax==0)
ax=(q[1].X-q[3].X)/(p[1].X-p[3].X);
else if((q[1].X-q[3].X)/(p[1].X-p[3].X)!=ax)
return;
}
else
return;
}
else if(q[1].X-q[3].X!=0||p[1].X-p[3].X!=0)
return;
if(q[2].X-q[3].X!=0&&p[2].X-p[3].X!=0)
{
if(abs(q[2].X-q[3].X)%abs(p[2].X-p[3].X)==0)
{
if(ax==0)
ax=(q[2].X-q[3].X)/(p[2].X-p[3].X);
else if((q[2].X-q[3].X)/(p[2].X-p[3].X)!=ax)
return;
}
else
return;
}
else if(q[2].X-q[3].X!=0||p[2].X-p[3].X!=0)
return;
ay=0;
if(q[1].Y-q[2].Y!=0&&p[1].Y-p[2].Y!=0)
{
if(abs(q[1].Y-q[2].Y)%abs(p[1].Y-p[2].Y)==0)
{
if(ay==0)
ay=(q[1].Y-q[2].Y)/(p[1].Y-p[2].Y);
else if((q[1].Y-q[2].Y)/(p[1].Y-p[2].Y)!=ay)
return;
}
else
return;
}
else if(q[1].Y-q[2].Y!=0||p[1].Y-p[2].Y!=0)
return;
if(q[1].Y-q[3].Y!=0&&p[1].Y-p[3].Y!=0)
{
if(abs(q[1].Y-q[3].Y)%abs(p[1].Y-p[3].Y)==0)
{
if(ay==0)
ay=(q[1].Y-q[3].Y)/(p[1].Y-p[3].Y);
else if((q[1].Y-q[3].Y)/(p[1].Y-p[3].Y)!=ay)
return;
}
else
return;
}
else if(q[1].Y-q[3].Y!=0||p[1].Y-p[3].Y!=0)
return;
if(q[2].Y-q[3].Y!=0&&p[2].Y-p[3].Y!=0)
{
if(abs(q[2].Y-q[3].Y)%abs(p[2].Y-p[3].Y)==0)
{
if(ay==0)
ay=(q[2].Y-q[3].Y)/(p[2].Y-p[3].Y);
else if((q[2].Y-q[3].Y)/(p[2].Y-p[3].Y)!=ay)
return;
}
else
return;
}
else if(q[2].Y-q[3].Y!=0||p[2].Y-p[3].Y!=0)
return;
if(ax==0||ay==0)
line=true;
Trans.PB(MP(MP(Rot_x,Rot_y),MP(ax,ay)));
}
void Affine(int _id1,int _id2,int _id3)
{
for(int x=-9;x<=9;x++)
{
Check(_id1,_id2,_id3,x,+10);
Check(_id1,_id2,_id3,x,-10);
}
for(int y=-10;y<=10;y++)
{
Check(_id1,_id2,_id3,+10,y);
Check(_id1,_id2,_id3,-10,y);
}
}
void Solve()
{
line=false;
Trans.clear();
Affine(1,2,3);
Affine(1,3,2);
Affine(2,1,3);
Affine(2,3,1);
Affine(3,1,2);
Affine(3,2,1);
if(Trans.size()==0)
{
cout<<"no solution\n";
return;
}
int ans=0;
for(int i=0;i<Trans.size();i++)
used[i]=false;
for(int i=0;i<Trans.size();i++)
if(!used[i])
{
ans++;
for(int j=i+1;j<Trans.size();j++)
{
if(Trans[i].key1 + Trans[j].key1==0&&
Trans[i].key2 + Trans[j].key2==0&&
Trans[i].key3 + Trans[j].key3==0&&
Trans[i].key4 + Trans[j].key4==0)
used[j]=true;
}
}
if(ans==1&&!line)
cout<<"equivalent solutions\n";
else
cout<<"inconsistent solutions\n";
}
int main()
{
int Case=0;
while(cin>>_p[1].X>>_p[1].Y>>_p[2].X>>_p[2].Y>>_p[3].X>>_p[3].Y &&(_p[1].X||_p[1].Y||_p[2].X||_p[2].Y||_p[3].X||_p[3].Y))
{
cin>>q[1].X>>q[1].Y>>q[2].X>>q[2].Y>>q[3].X>>q[3].Y;
cout<<"Case "<<++Case<<": ";
Solve();
}
return 0;
}