fp.cpp
#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define DEBUG(x) cout << ">>> " << #x << " : " << x << endl;
#define REP(i,a) for (int i = 0; i < (a); ++i)
#define FOR(i,a,b) for (int i = (a); i <= (b); ++i)
#define FORD(i,a,b) for (int i = (a); i >= (b); --i)
inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
const int INF = 1<<29;
typedef long long ll;
inline int two(int n) { return 1 << n; }
inline int shift(int n, int b)
{
if (b >= 0) return n << b;
else return n >> (-b);
}
inline int last_bit(int n)
{
return n&(-n);
}
///////////////////////////////////////////////////////////////////////////
string pots[12][5] =
{
//F
{
".##..",
"##...",
".#...",
".....",
".....",
},
//I
{
"#....",
"#....",
"#....",
"#....",
"#....",
},
//L
{
"#....",
"#....",
"#....",
"##...",
".....",
},
// N
{
".#...",
".#...",
"##...",
"#....",
".....",
},
//P
{
"##...",
"##...",
"#....",
".....",
".....",
},
//T
{
"###..",
".#...",
".#...",
".....",
".....",
},
//U
{
"#.#..",
"###..",
".....",
".....",
".....",
},
//V
{
"#....",
"#....",
"###..",
".....",
".....",
},
//W
{
"#....",
"##...",
".##..",
".....",
".....",
},
//X
{
".#...",
"###..",
".#...",
".....",
".....",
},
//Y
{
".#...",
"##...",
".#...",
".#...",
".....",
},
//Z
{
"##...",
".#...",
".##..",
".....",
".....",
}
};
void flip(vector<string> & from, vector<string> & to)
{
REP(i, 5) REP(j, 5)
to[i][j] = from[i][4-j];
}
void rot(vector<string> & from, vector<string> & to)
{
REP(i, 5) REP(j, 5)
to[i][j] = from[4-j][i];
}
int shapes[12][8][5];
void init()
{
REP(i, 12)
{
vector<string> from(5), to(5, string(5, '.'));
REP(j, 5) from[j] = pots[i][j];
int ind = 0;
REP(f, 2)
{
REP(r, 4)
{
rot(from ,to);
from = to;
REP(j, 5)
{
shapes[i][ind][j] = 0;
REP(k, 5)
if (from[j][k] == '#')
shapes[i][ind][j] ^= two(k);
}
++ind;
}
flip(from, to);
from = to;
}
}
}
string letters = "FILNPTUVWXYZ";
char in[10];
int get_index(char c)
{
REP(i, letters.size())
if (c == letters[i])
return i;
return -1;
}
const int MAXX = 8, MAXY = 8, MASKY = (1<<MAXY)-1;
int board[MAXX], board2[MAXY];
bool can(int x, int y, int * shape, int * board, int * board2=NULL)
{
REP(i, 5)
{
if (!shape[i]) continue; // nothing
if (x+i < 0 || x+i >= MAXX) return false; // bad row
if (!shift(last_bit(shape[i]), y)) return false; // bad left col
int s = shift(shape[i], y);
if ((s&MASKY) != s) return false; // bad right col
if (board[x+i]&s) return false; // overlap
if (board2 != NULL && (board2[x+i]&s) != s) return false; // not matched
}
return true;
}
void place(int x, int y, int * shape, int * board)
{
REP(i, 5)
board[x+i] ^= shift(shape[i], y);
}
int a1, a2, b1, b2;
bool place1();
bool place2();
bool place3();
bool place4();
bool place1()
{
FOR(x, -4, MAXX-1) FOR(y, -4, MAXY-1)
if (can(x, y, shapes[a1][0], board))
{
place(x, y, shapes[a1][0], board);
if (place2()) return true;
place(x, y, shapes[a1][0], board);
}
return false;
}
bool place2()
{
FOR(x, -4, MAXX-1) FOR(y, -4, MAXY-1) REP(s, 8)
if (can(x, y, shapes[a2][s], board))
{
place(x, y, shapes[a2][s], board);
if (place3()) return true;
place(x, y, shapes[a2][s], board);
}
return false;
}
bool place3()
{
FOR(x, -4, MAXX-1) FOR(y, -4, MAXY-1) REP(s, 8)
if (can(x, y, shapes[b1][s], board2, board))
{
place(x, y, shapes[b1][s], board2);
if (place4()) return true;
place(x, y, shapes[b1][s], board2);
}
return false;
}
bool place4()
{
FOR(x, -4, MAXX-1) FOR(y, -4, MAXY-1) REP(s, 8)
if (can(x, y, shapes[b2][s], board2, board))
return true;
return false;
}
int main()
{
init();
while (gets(in))
{
memset(board, 0, sizeof(board));
memset(board2, 0, sizeof(board2));
a1 = get_index(in[0]), a2 = get_index(in[1]), b1 = get_index(in[3]), b2 = get_index(in[4]);
if (place1()) printf("YES\n");
else printf("NO\n");
}
return 0;
}