fp.cpp
#include <stdio.h>
#include <stdlib.h>
#include <set>
typedef struct POINT
{
int x;
int y;
}
POINT;
using namespace std;
typedef set<POINT> SET;
typedef SET::iterator IT;
POINT Base[12][5] =
{
//F
{
(POINT) {1, 0},
(POINT) {2, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {1, 2}
},
//I
{
(POINT) {0, 0},
(POINT) {0, 1},
(POINT) {0, 2},
(POINT) {0, 3},
(POINT) {0, 4}
},
//L
{
(POINT) {0, 0},
(POINT) {0, 1},
(POINT) {0, 2},
(POINT) {0, 3},
(POINT) {1, 3}
},
//N
{
(POINT) {1, 0},
(POINT) {1, 1},
(POINT) {0, 2},
(POINT) {1, 2},
(POINT) {0, 3}
},
//P
{
(POINT) {0, 0},
(POINT) {1, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {0, 2}
},
//T
{
(POINT) {0, 0},
(POINT) {1, 0},
(POINT) {2, 0},
(POINT) {1, 1},
(POINT) {1, 2}
},
//U
{
(POINT) {0, 0},
(POINT) {2, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {2, 1}
},
//V
{
(POINT) {0, 0},
(POINT) {0, 1},
(POINT) {0, 2},
(POINT) {1, 2},
(POINT) {2, 2}
},
//W
{
(POINT) {0, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {1, 2},
(POINT) {2, 2}
},
//X
{
(POINT) {1, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {2, 1},
(POINT) {1, 2}
},
//Y
{
(POINT) {1, 0},
(POINT) {0, 1},
(POINT) {1, 1},
(POINT) {1, 2},
(POINT) {1, 3}
},
//Z
{
(POINT) {0, 0},
(POINT) {1, 0},
(POINT) {1, 1},
(POINT) {1, 2},
(POINT) {2, 2}
}
};
int operator < (const POINT& P, const POINT& Q)
{
if(P.x < Q.x) return 1;
if(P.x > Q.x) return 0;
return P.y < Q.y;
}
POINT Pent[12][8][5];
int CharToIndex[300];
char IndexToChar[20] = "FILNPTUVWXYZ";
void InitializeOrientations()
{
for(int i = 0; i < 12; i++)
{
for(int j = 0; j < 8; j++)
{
for(int k = 0; k < 5; k++)
{
Pent[i][j][k].x = Base[i][k].x;
Pent[i][j][k].y = Base[i][k].y;
if(j >= 4)
{
Pent[i][j][k].x *= -1;
}
for(int d = 0; d < j % 4; d++)
{
int q = -Pent[i][j][k].x;
Pent[i][j][k].x = Pent[i][j][k].y;
Pent[i][j][k].y = q;
}
}
}
}
}
SET Adj[12][8];
void InitializeAdj()
{
for(int i = 0; i < 12; i++)
{
for(int j = 0; j < 8; j++)
{
for(int k = 0; k < 5; k++)
{
Adj[i][j].insert((POINT) {Pent[i][j][k].x + 0, Pent[i][j][k].y + 1});
Adj[i][j].insert((POINT) {Pent[i][j][k].x + 1, Pent[i][j][k].y + 0});
Adj[i][j].insert((POINT) {Pent[i][j][k].x + 0, Pent[i][j][k].y - 1});
Adj[i][j].insert((POINT) {Pent[i][j][k].x - 1, Pent[i][j][k].y + 0});
}
}
}
}
void FindMinFromSet(SET& set, int& xMin, int& yMin)
{
xMin = 20;
yMin = 20;
for(IT it = set.begin(); it != set.end(); it++)
{
if(it->x < xMin) xMin = it->x;
if(it->y < yMin) yMin = it->y;
}
}
void FindMinFromArray(POINT* array, int& xMin, int& yMin)
{
xMin = 20;
yMin = 20;
for(int i = 0; i < 5; i++)
{
if(array[i].x < xMin) xMin = array[i].x;
if(array[i].y < yMin) yMin = array[i].y;
}
}
int Inner(SET& set, int ci, int di)
{
/*int Table[10][10] = {{0}};
int xMin, yMin;
FindMinFromSet(set, xMin, yMin);
for(IT it = set.begin(); it != set.end(); it++)
{
Table[it->x - xMin][it->y - yMin] = 1;
printf("(%d, %d)\n", it->x, it->y);
}
for(int y = 0; y < 10; y++)
{
putchar(' ');
for(int x = 0; x < 10; x++)
{
putchar((Table[x][y]) ? '#' : '.');
}
putchar('\n');
}
putchar('\n');*/
for(int i = 0; i < 8; i++)
//orientation of c
{
for(int j = 0; j < 5; j++)
//going through points of c
{
for(IT it = set.begin(); it != set.end(); it++)
//going through the points of a, b
{
SET set2(set);
int xDiff = it->x - Pent[ci][i][j].x;
int yDiff = it->y - Pent[ci][i][j].y;
for(int k = 0; k < 5; k++)
{
if(!(set2.erase((POINT) {Pent[ci][i][k].x + xDiff, Pent[ci][i][k].y + yDiff})))
{
//printf("Could not find (%d, %d)\n", Pent[ci][i][k].x + xDiff, Pent[ci][i][k].y + yDiff);
goto FAIL;
}
else
{
//printf("Could find (%d, %d)\n", Pent[ci][i][k].x + xDiff, Pent[ci][i][k].y + yDiff);
}
}
int xMin, yMin;
FindMinFromSet(set2, xMin, yMin);
for(int d = 0; d < 8; d++)
//orientation of d
{
SET set3(set2);
int xMinD, yMinD;
FindMinFromArray(Pent[di][d], xMinD, yMinD);
xDiff = xMin - xMinD;
yDiff = yMin - yMinD;
for(int k = 0; k < 5; k++)
{
if(!(set3.erase((POINT) {Pent[di][d][k].x + xDiff, Pent[di][d][k].y + yDiff})))
{
//printf("Could not find 2 (%d, %d)\n", Pent[di][d][k].x + xDiff, Pent[di][d][k].y + yDiff);
goto INNER_FAIL;
}
}
return 1;
INNER_FAIL:;
}
FAIL:;
}
}
}
return 0;
}
int main()
{
for(int i = 0; i < 12; i++)
{
CharToIndex[(int) IndexToChar[i]] = i;
}
InitializeOrientations();
InitializeAdj();
/*for(int i = 0; i < 12; i++)
{
for(int q = 0; q < 8; q++)
{
int xMin = 10;
int yMin = 10;
for(int j = 0; j < 5; j++)
{
if(Pent[i][q][j].x < xMin) xMin = Pent[i][q][j].x;
if(Pent[i][q][j].y < yMin) yMin = Pent[i][q][j].y;
}
printf("Znak %c; orientace %d\n", IndexToChar[i], q);
int Table[5][5] = {{0}};
for(int j = 0; j < 5; j++)
{
Table[Pent[i][q][j].x - xMin][Pent[i][q][j].y - yMin] = 1;
}
for(int y = 0; y < 5; y++)
{
putchar(' ');
for(int x = 0; x < 5; x++)
{
putchar((Table[x][y]) ? '#' : '.');
}
putchar('\n');
}
putchar('\n');
}
}
return 0;*/
char a, b, c, d;
while(scanf(" %c%c %c%c", &a, &b, &c, &d) > 0)
{
int ai = CharToIndex[(int) a];
int bi = CharToIndex[(int) b];
int ci = CharToIndex[(int) c];
int di = CharToIndex[(int) d];
SET& aAdj = Adj[ai][0];
for(int i = 0; i < 8; i++)
//orientation of b
{
for(int j = 0; j < 5; j++)
//going through points of b
{
for(IT it = aAdj.begin(); it != aAdj.end(); it++)
//going through neighbors of a
{
int xDiff = it->x - Pent[bi][i][j].x;
int yDiff = it->y - Pent[bi][i][j].y;
SET set;
for(int k = 0; k < 5; k++)
{
set.insert(Pent[ai][0][k]);
}
for(int k = 0; k < 5; k++)
{
set.insert((POINT) {Pent[bi][i][k].x + xDiff, Pent[bi][i][k].y + yDiff});
}
if(set.size() == 10)
{
if(Inner(set, ci, di))
{
goto YES;
}
}
}
}
}
printf("NO\n");
continue;
YES: printf("YES\n");
}
return 0;
}