#include #include #include #include using namespace std; #define FNAME "similar.txt" #define cin fin ifstream fin(FNAME); #define NEXT 0 #define PREV 1 #define HOR 0 #define VER 1 class Point { public: int x, y; }; int direction( Point &a, Point &b ) { return ( a.x == b.x )? VER : HOR; } class Polygon { public: vector ps; int itdirection; int size() { return ps.size(); } Point &operator [] ( int n ) { return ps[n]; } bool read() { char ch; int npoint; cin >> npoint; if ( npoint == 0 ) return false; // 直線上に無駄な頂点が存在することがある. よってそれを除去. vector pbuf(npoint); vector next(npoint), prev(npoint); int listHead = 0; for ( int i = 0; i < npoint; i++ ) { cin >> pbuf[i].x >> ch >> pbuf[i].y; next[i] = i + 1, prev[i] = i - 1; } next[npoint-1] = 0, prev[0] = npoint-1; int cursor = 0; while ( true ) { const int p = prev[cursor], n = next[cursor]; if ( direction(pbuf[p], pbuf[cursor]) == direction(pbuf[cursor], pbuf[n]) ) { next[p] = n; prev[n] = p; if ( cursor == listHead ) listHead = n; } if ( n < cursor ) break; cursor = n; } cursor = listHead; while ( true ) { ps.push_back(pbuf[cursor]); cursor = next[cursor]; if ( cursor == listHead ) break; } itdirection = NEXT; return true; } int getStart() { int result = 0; for ( int n = 0; n < ps.size(); n++ ) if ( ps[result].y < ps[n].y ) result = n; else if ( ps[result].y == ps[n].y && ps[result].x < ps[n].x ) result = n; return result; } int getNext( int n ) { if ( itdirection == NEXT ) return (n + 1) % ps.size(); else return (n - 1 + ps.size()) % ps.size(); } void reverse() { itdirection = (itdirection == NEXT)? PREV : NEXT; } void flip() { for ( int i = 0; i < ps.size(); i++ ) ps[i].y = -ps[i].y; } void rotate() { for ( int i = 0; i < ps.size(); i++ ) { const int tx = ps[i].x, ty = ps[i].y; ps[i].x = ty, ps[i].y = -tx; } } }; bool isSimilar( Polygon &P1, Polygon &P2 ) { int curr1 = P1.getStart(), curr2 = P2.getStart(); int next1 = P1.getNext(curr1), next2 = P2.getNext(curr2); if ( direction(P1[curr1], P1[next1]) != direction(P2[curr2], P2[next2]) ) P2.reverse(), next2 = P2.getNext(curr2); int prop1, prop2; if ( direction(P1[curr1], P1[next1]) == HOR ) prop1 = P1[curr1].x - P1[next1].x, prop2 = P2[curr2].x - P2[next2].x; else prop1 = P1[curr1].y - P1[next1].y, prop2 = P2[curr2].y - P2[next2].y; for ( int i = 0; i < P1.size(); i++ ) { next1 = P1.getNext(curr1); next2 = P2.getNext(curr2); const int dx1 = P1[next1].x - P1[curr1].x, dy1 = P1[next1].y - P1[curr1].y; const int dx2 = P2[next2].x - P2[curr2].x, dy2 = P2[next2].y - P2[curr2].y; if ( prop1*dx2 != prop2*dx1 ) return false; if ( prop1*dy2 != prop2*dy1 ) return false; curr1 = next1; curr2 = next2; } return true; } bool compute( Polygon &P1, Polygon &P2 ) { if ( P1.size() != P2.size() ) return false; for ( int i = 0; i < 4; i++ ) { if ( isSimilar(P1, P2) ) return true; P2.rotate(); } P2.flip(); for ( int i = 0; i < 4; i++ ) { if ( isSimilar(P1, P2) ) return true; P2.rotate(); } return false; } int main() { while ( true ) { Polygon P1, P2; if ( !P1.read() || !P2.read() ) break; if ( compute(P1, P2) ) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }