Problem:
Strange Key
Professor Tsukuba invented a mysterious jewelry box that can be opened
with a special gold key whose shape is very strange. It is composed
of gold bars joined at their ends.  Each gold bar
has the same length and is placed parallel to one of the three
orthogonal axes in a three dimensional space, 
i.e., x-axis, y-axis and z-axis.
The locking mechanism of the jewelry box
is truly mysterious, but the shape of the key is known.
To identify the key of the jewelry box, he gave a way to describe 
its shape.
The description 
indicates a list of connected paths that completely defines the shape
of the key: the gold bars of the key are arranged along the paths and 
joined at their ends.
Except for the first path, 
each path must start from an end point of a gold bar on a previously
defined path.
Each path is represented by a sequence of elements, each of which is one
of six symbols (+x, -x, +y, -y, +z and -z) or a positive integer.
Each symbol indicates the direction from an end point to the other end
point of a gold bar along the path.  Since each gold bar is
parallel to one of the three orthogonal axes, the 6 symbols are enough to
indicate the direction.  Note that a description of a path has
direction but the gold bars themselves have no direction.
An end point of a gold bar can have a label, which is a positive integer.
The labeled point may be referred to as the beginnings of other paths.
In a key description, the first occurrence of a positive integer 
defines a label of a point and each subsequent occurrence of the same
positive integer indicates the beginning of a new path at the point.
An example of a key composed of 13 gold bars is depicted 
in Figure 1.
The following sequence of lines
19
      1 +x 1 +y +z 3 +z 
      3 +y -z +x +y -z -x +z 2 +z  
      2 +y
is a description of the key in Figure 1.
Note that newlines have the same role as space characters in the
description, so that
"19 1 +x 1 +y +z 3 +z 3 +y -z +x +y -z -x +z
2 +z 2 +y"
has the same meaning.
The meaning of this description is quite simple.
The first integer "19" means the number of
the following elements in this description.
Each element is one of the 6 symbols or a positive integer.
The integer "1" at the head of the second line 
is a label attached to the starting point of the first path.
Without loss of generality, 
it can be assumed that the starting point of the first path is the
origin, i.e., (0,0,0), and that the length of each gold bar is 1.
The next element "+x" indicates that the first gold bar
is parallel to the x-axis, 
so that the other end point of the gold bar is at (1,0,0).
These two elements "1" and "+x" indicates
the first path consisting of only one gold bar.
The third element of the second line in the description is the positive
integer "1", meaning that the point with the label "1", i.e., the
origin (0,0,0) is the beginning of a new path.
The following elements "+y", "+z", "3", and "+z" indicate the second
path consisting of three gold bars. No
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define op operator
#define pb push_back

struct poi {
    int x, y, z;

    poi op-(poi p) {
        return {x - p.x, y - p.y, z - p.z};
    }

    poi op+(poi p) {
        return {x + p.x, y + p.y, z + p.z};
    }

    bool op<(poi p) const {
        return tie(x, y, z) < tie(p.x, p.y, p.z);
    }

    vector <poi> rot() {
        int a[3] = {x, y, z};
        vector <poi> v;
        int p[3] = {0, 1, 2};
        do {
            int inv = (p[0] > p[1]) + (p[0] > p[2]) + (p[1] > p[2]);
            int x = a[p[0]], y = a[p[1]], z = a[p[2]];
            if (inv & 1) {
                v.pb({-x, y, z});
                v.pb({x, -y, z});
                v.pb({x, y, -z});
                v.pb({-x, -y, -z});
            } else {
                v.pb({x, y, z});
                v.pb({x, -y, -z});
                v.pb({-x, y, -z});
                v.pb({-x, -y, z});
            }
        } while (next_permutation(p, p + 3));
        return v;
    }
};

const int N = 1001;
bool v[N];
poi save[N];
vector <pair<poi, poi>> segs[2];

vector <pair<poi, poi>> read(int n) {
    poi p = {0, 0, 0};
    memset(v, 0, sizeof v);
    vector <pair<poi, poi>> r;
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        if (s[0] == '+' || s[0] == '-') {
            poi q;
            if (s[1] == 'x')
                q = {1, 0, 0};
            else if (s[1] == 'y')
                q = {0, 1, 0};
            else
                q = {0, 0, 1};
            if (s[0] == '+')
                q = p + q;
            else
                q = p - q;
            r.pb({p, q});
            p = q;
        } else {
            int x = stoi(s);
            if (v[x])
                p = save[x];
            else {
                v[x] = 1;
                save[x] = p;
            }
        }
    }
    return r;
}

set <poi> st;

bool check(poi p) {
    bool v[24];
    memset(v, true, sizeof v);
    for (auto seg: segs[1]) {
        auto a = (seg.first - p).rot();
        auto b = (seg.second - p).rot();
        for (int i = 0; i < 24; i++) {
            if (v[i] && !st.count(a[i] + b[i]))
                v[i] = false;
        }
        if (!count(v, v + 24, true))
            return false;
    }
    return count(v, v + 24, true);
}

int main() {
    ios::sync_with_stdio(false);
    int n, m;
    while (cin >> n) {
        if (n == 0) break;
        segs[0] = read(n);
        cin >> m;
        segs[1] = read(m);

        st.clear();
        for (auto seg: segs[0]) {
            poi p = seg.first - segs[0][0].first;
            poi q = seg.second - segs[0][0].first;
            st.insert(p + q);
        }

        bool f = false;
        for (auto seg: segs[1])
            f |= check(seg.first) || check(seg.second);
        cout << (f ? "SAME" : "DIFFERENT") << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3420
final_rank: 11

code_snippet: #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <sstream>
#include <queue>
#include <map>
using namespace std;
#define R register
#define _max(a,b)  ((a)>(b)?(a):(b))
#define _min(a,b)  ((a)<(b)?(a):(b))
#define _abs(a)    ((a)> 0 ?(a):-(a))
typedef long long ll;
typedef pair<int, int> pil;
const int MX = 100;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-6;
ll _r() {
    ll x = 0, f = 1;
    char c = getchar();
    while (c > '9' || c < '0') { if (c == '-')f = -1; c = getchar(); }
    while (c >= '0' && c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return f == -1 ? -x : x;
}
int n = 0, cnt = 0;
struct Node {
    int x, y, z;
    Node() {
        z = y = x = 0;
    }
    Node(int a, int b, int c) {
        x = a, y = b, z = c;
    }
    Node operator + (const Node& a)const {
        Node c;
        c.x = x + a.x;
        c.y = y + a.y;
        c.z = z + a.z;
        return c;
    }
    Node operator - (const Node& a)const {
        Node c;
        c.x = x - a.x;
        c.y = y - a.y;
        c.z = z - a.z;
        return c;
    }
    Node operator += (const Node& a) {
        return *this = (*this) + a;
    }
    Node operator -= (const Node& a) {
        return *this = (*this) - a;
    }
    bool operator < (const Node& a)const {
        if (x == a.x) {
            if (y == a.y) {
                return z < a.z;
            }
            return y < a.y;
        }
        return x < a.x;
    }
}save[1000], road[1000];

int used[1000] = { 0 }, ccnt = 1;
Node change[2000][3];
map< pair< Node, Node >, int> vis;
bool Init() {
    vis.clear();
    memset(used, 0, sizeof(used));
    cnt = 1;

    save[1].x = save[1].y = save[1].z = 0;
    road[1] = save[1];
    cin >> n;
    if (n == 0)
        return 1;
    return 0;
}
inline int to_num(string& x) {
    int res = 0;
    for (int i = 0; i < x.length(); i++) {
        res = (res << 3) + (res << 1) + (x[i] ^ 48);
    }
    return res;
}
string que[1000];
void solve() {
    Node u, v;
    u = save[1];
    //used[1] = 1;
    string ope;
    for (R int i = 0; i < n; i++) {
        cin >> ope;
        if (ope[0] == '-') {
            v = u;
            if (ope[1] == 'x')
                v.x--;
            else if (ope[1] == 'y')
                v.y--;
            else
                v.z--;
            vis[make_pair(u, v)] = 1;
            vis[make_pair(v, u)] = 1;
            road[++cnt] = v;
            u = v;
        }
        else if (ope[0] == '+') {
            v = u;
            if (ope[1] == 'x')
                v.x++;
            else if (ope[1] == 'y')
                v.y++;
            else
                v.z++;
            vis[make_pair(u, v)] = 1;
            vis[make_pair(v, u)] = 1;
            road[++cnt] = v;
            u = v;
        }
        else {
            int st = to_num(ope);
            if (used[st]) {
                u = save[st];
            }
            else {
                save[st] = u;
                used[st] = 1;
            }
        }
    }


    int check = 0, flag = 0;
    cin >> check;
    for (R int i = 0; i < check; i++) {
        cin >> que[i];
    }
    int fin = 0;
    for (R int mood = 0; mood <= 27 && fin == 0; mood++) {
        for (R int st = 1; st <= cnt && fin == 0; st++) {
            memset(used, 0, sizeof(used));
            flag = 0;
            u = road[st];
            save[1] = u;
            //used[1] = 1;
            for (R int i = 0; i < check && flag == 0; i++) {
                que[i] = que[i];
                if (que[i][0] == '-') {
                    v = u;
                    if (que[i][1] == 'x')
                        v -= change[mood][0];
                    else if (que[i][1] == 'y')
                        v -= change[mood][1];
                    else
                        v -= change[mood][2];
                    if (vis[make_pair(u, v)] == 1)
                        u = v;
                    else
                        flag = 1;
                }
                else if (que[i][0] == '+') {
                    v = u;
                    if (que[i][1] == 'x')
                        v += change[mood][0];
                    else if (que[i][1] == 'y')
                        v += change[mood][1];
                    else
                        v += change[mood][2];
                    if (vis[make_pair(u, v)] == 1)
                        u = v;
                    else
                        flag = 1;
                }
                else {
                    int num = to_num(que[i]);
                    if (used[num]) {
                        u = save[num];
                    }
                    else {
                        save[num] = u;
                        used[num] = 1;
                    }
                }
            }
            if (flag == 0) {
                fin = 1;
            }

        }
    }
    if (fin)
        cout << "SAME" << endl;
    else
        cout << "DIFFERENT" << endl;
}
void start() {
    change[0][0] = Node(1, 0, 0); change[0][1] = Node(0, 0, -1); change[0][2] = Node(0, 1, 0);
    change[1][0] = Node(1, 0, 0); change[1][1] = Node(0, -1, 0); change[1][2] = Node(0, 0, -1);
    change[2][0] = Node(1, 0, 0); change[2][1] = Node(0, 0, 1); change[2][2] = Node(0, -1, 0);
    change[3][0] = Node(1, 0, 0); change[3][1] = Node(0, 1, 0); change[3][2] = Node(0, 0, 1);
    change[4][0] = Node(0, 0, 1); change[4][1] = Node(1, 0, 0); change[4][2] = Node(0, 1, 0);
    change[5][0] = Node(0, 0, 1); change[5][1] = Node(0, -1, 0); change[5][2] = Node(1, 0, 0);
    change[6][0] = Node(0, 0, 1); change[6][1] = Node(-1, 0, 0); change[6][2] = Node(0, -1, 0);
    change[7][0] = Node(0, 0, 1); change[7][1] = Node(0, 1, 0); change[7][2] = Node(-1, 0, 0);
    change[8][0] = Node(0, 1, 0); change[8][1] = Node(1, 0, 0); change[8][2] = Node(0, 0, -1);
    change[9][0] = Node(0, 1, 0); change[9][1] = Node(0, 0, 1); change[9][2] = Node(1, 0, 0);
    change[10][0] = Node(0, 1, 0); change[10][1] = Node(-1, 0, 0); change[10][2] = Node(0, 0, 1);
    change[11][0] = Node(0, 1, 0); change[11][1] = Node(0, 0, -1); change[11][2] = Node(-1, 0, 0);
    change[12][0] = Node(-1, 0, 0); change[12][1] = Node(0, 1, 0); change[12][2] = Node(0, 0, -1);
    change[13][0] = Node(-1, 0, 0); change[13][1] = Node(0, 0, 1); change[13][2] = Node(0, 1, 0);
    change[14][0] = Node(-1, 0, 0); change[14][1] = Node(0, -1, 0); change[14][2] = Node(0, 0, 1);
    change[15][0] = Node(-1, 0, 0); change[15][1] = Node(0, 0, -1); change[15][2] = Node(0, -1, 0);
    change[16][0] = Node(0, 0, -1); change[16][1] = Node(0, 1, 0); change[16][2] = Node(1, 0, 0);
    change[17][0] = Node(0, 0, -1); change[17][1] = Node(-1, 0, 0); change[17][2] = Node(0, 1, 0);
    change[18][0] = Node(0, 0, -1); change[18][1] = Node(0, -1, 0); change[18][2] = Node(-1, 0, 0);
    change[19][0] = Node(0, 0, -1); change[19][1] = Node(1, 0, 0); change[19][2] = Node(0, -1, 0);
    change[20][0] = Node(0, -1, 0); change[20][1] = Node(0, 0, -1); change[20][2] = Node(1, 0, 0);
    change[21][0] = Node(0, -1, 0); change[21][1] = Node(-1, 0, 0); change[21][2] = Node(0, 0, -1);
    change[22][0] = Node(0, -1, 0); change[22][1] = Node(0, 0, 1); change[22][2] = Node(-1, 0, 0);
    change[23][0] = Node(0, -1, 0); change[23][1] = Node(1, 0, 0); change[23][2] = Node(0, 0, 1);
    change[24][0] = Node(1, 0, 0); change[24][1] = Node(0, 0, -1); change[24][2] = Node(0, 1, 0);
    change[25][0] = Node(1, 0, 0); change[25][1] = Node(0, -1, 0); change[25][2] = Node(0, 0, -1);
    change[26][0] = Node(1, 0, 0); change[26][1] = Node(0, 0, 1); change[26][2] = Node(0, -1, 0);
    change[27][0] = Node(1, 0, 0); change[27][1] = Node(0, 1, 0); change[27][2] = Node(0, 0, 1);
}
int main() {
    ios::sync_with_stdio(false);
    //freopen("data.in", "r", stdin);
    //int t = _r();
    start();
    while (1) {
        if (Init())
            break;
        solve();
    }


    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3248
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define op operator
#define pb push_back

struct poi {
	int x, y, z;
	poi op -(poi p) {
		return {x - p.x, y - p.y, z - p.z};
	}
	poi op +(poi p) {
		return {x + p.x, y + p.y, z + p.z};
	}
	bool op <(poi p) const {
		return tie(x, y, z) < tie(p.x, p.y, p.z);
	}
	vector <poi> rot() {
		int a[3] = {x, y, z};
		vector <poi> v;
		int p[3] = {0, 1, 2};
		do {
			int inv = (p[0] > p[1]) + (p[0] > p[2]) + (p[1] > p[2]);
			int x = a[p[0]], y = a[p[1]], z = a[p[2]];
			if(inv & 1) {
				v.pb({-x, y, z});
				v.pb({x, -y, z});
				v.pb({x, y, -z});
				v.pb({-x, -y, -z});
			} else {
				v.pb({x, y, z});
				v.pb({x, -y, -z});
				v.pb({-x, y, -z});
				v.pb({-x, -y, z});
			}
		}while(next_permutation(p, p + 3));
		return v;
	}
};

const int N = 1001;
bool v[N];
poi save[N];
vector <pair <poi, poi>> segs[2];

vector <pair <poi, poi>> read(int n) {
	poi p = {0, 0, 0};
	memset(v, 0, sizeof v);
	vector <pair <poi, poi>> r;
	for(int i = 0; i < n; i ++) {
		string s; cin >> s;
		if(s[0] == '+' || s[0] == '-') {
			poi q;
			if(s[1] == 'x')
				q = {1, 0, 0};
			else if(s[1] == 'y')
				q = {0, 1, 0};
			else
				q = {0, 0, 1};
			if(s[0] == '+')
				q = p + q;
			else
				q = p - q;
			r.pb({p, q});
			p = q;
		} else {
			int x = stoi(s);
			if(v[x])
				p = save[x];
			else {
				v[x] = 1;
				save[x] = p;
			}
		}
	}
	return r;
}

set <poi> st;
bool check(poi p) {
	bool v[24];
	memset(v, true, sizeof v);
	for(auto seg : segs[1]) {
		auto a = (seg.first - p).rot();
		auto b = (seg.second - p).rot();
		for(int i = 0; i < 24; i ++) {
			if(v[i] && !st.count(a[i] + b[i]))
				v[i] = false;
		}
		if(!count(v, v + 24, true))
			return false;
	}
	return count(v, v + 24, true);
}

int main() {
	ios :: sync_with_stdio(false);
	int n, m;
	while(cin >> n) {
		if(n == 0) break;
		segs[0] = read(n);
		cin >> m;
		segs[1] = read(m);

		st.clear();
		for(auto seg : segs[0]) {
			poi p = seg.first - segs[0][0].first;
			poi q = seg.second - segs[0][0].first;
			st.insert(p + q);
		}

		bool f = false;
		for(auto seg : segs[1])
			f |= check(seg.first) || check(seg.second);
		cout << (f ? "SAME" : "DIFFERENT") << '\n';
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3116
final_rank: 9

code_snippet: #include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <memory>
#include <cstring>
#include <cassert>
#include <numeric>
#include <sstream>
#include <complex>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <tuple>
#include <cctype>
#include <unordered_map>
#include <unordered_set>
using namespace std;

#define REP2(i, m, n) for (int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(S) (S).begin(), (S).end()

template <typename T, typename E>
ostream &operator<<(std::ostream &os, const std::pair<T, E> &p){
  return os << "(" << p.first << ", " << p.second << ")";
}

typedef tuple<int, int, int> Point3D;

Point3D operator-(const Point3D &p1, const Point3D &p2){
  return make_tuple(get<0>(p1) - get<0>(p2),
                    get<1>(p1) - get<1>(p2),
                    get<2>(p1) - get<2>(p2));
}

Point3D operator+(const Point3D &p1, const Point3D &p2){
  return make_tuple(get<0>(p1) + get<0>(p2),
                    get<1>(p1) + get<1>(p2),
                    get<2>(p1) + get<2>(p2));
}

struct Key {
  map<int, Point3D> P;
  map<Point3D, int> I;
  map<int, vector<int> > E; 
  
  void load(int n){
    map<string, Point3D> L;
    string s;
    int x = 0, y = 0, z = 0, nx, ny, nz;
    
    P[0] = make_tuple(0, 0, 0);
    I[make_tuple(0, 0, 0)] = 0;
    
    while (n--){
      cin >> s;
      tie(nx, ny, nz) = make_tuple(x, y, z);
      if (s.back() == 'x'){
        nx = (s[0] == '-' ? x - 1 : x + 1);
      } else if (s.back() == 'y'){
        ny = (s[0] == '-' ? y - 1 : y + 1);
      } else if (s.back() == 'z'){
        nz = (s[0] == '-' ? z - 1 : z + 1);
      } else {
        if (L.count(s) == 0) L[s] = make_tuple(x, y, z);
        else tie(x, y, z) = L[s];
        continue;
      }

      if (I.count(make_tuple(nx, ny, nz)) == 0){
        int id = I.size();
        I[make_tuple(nx, ny, nz)] = id;
        P[id] = make_tuple(nx, ny, nz);
      }

      int u = I[make_tuple(x, y, z)];
      int v = I[make_tuple(nx, ny, nz)];
      E[u].push_back(v);
      E[v].push_back(u);
      tie(x, y, z) = make_tuple(nx, ny, nz);
    }
  }

  void rotate_x(){
    map<Point3D, int> NI;
    for (auto &p : P){
      int x, y, z;
      tie(x, y, z) = p.second;
      p.second = make_tuple(x, -z, y);
      NI[p.second] = p.first;
    }
    I = NI;
  };
  void rotate_y(){
    map<Point3D, int> NI;
    for (auto &p : P){
      int x, y, z;
      tie(x, y, z) = p.second;
      p.second = make_tuple(-z, y, x);
      NI[p.second] = p.first;
    }
    I = NI;
  };
  
  void rotate_z(){
    map<Point3D, int> NI;
    for (auto &p : P){
      int x, y, z;
      tie(x, y, z) = p.second;
      p.second = make_tuple(-y, x, z);
      NI[p.second] = p.first;
    }
    I = NI;
  }
};


bool check(Key key1, Key key2){
  auto P1 = key1.P;
  auto P2 = key2.P;
  if (P1.size() != P2.size()) return false;

  int n = P1.size();
  REP(i, n){
    Point3D d = P2[i] - P1[0];
    
    bool ok = true;
    REP(j, n){
      if (key2.I.count(P1[j] + d) == 0) ok = false;
      if (key1.I.count(P2[j] - d) == 0) ok = false;
    }

    if (ok){
      REP(j, n) if (ok){
        for (int k : key1.E[j]){
          int nj = key2.I[P1[j] + d];
          int nk = key2.I[P1[k] + d];
          if (find(ALL(key2.E[nj]), nk) == key2.E[nj].end()) ok = false;
        }
      }
      REP(j, n) if (ok){
        for (int k : key2.E[j]){
          int nj = key1.I[P2[j] - d];
          int nk = key1.I[P2[k] - d];
          if (find(ALL(key1.E[nj]), nk) == key1.E[nj].end()) ok = false;
        }
      }
    }
    if (ok) return true;
  }
  return false;
}

bool same(Key key1, Key key2){
  REP(z_, 4){
    REP(y_, 4){
      REP(x_, 4){
        if (check(key1, key2)) return true;
        key1.rotate_x();
      }
      key1.rotate_y();
    }
    key1.rotate_z();
  }
  return false;
}
  

int main(int argc, char *argv[])
{
  int n;
  while (cin >> n && n){
    Key key1;
    Key key2;
    key1.load(n);
    cin >> n;
    key2.load(n);
    cout << (same(key1, key2) ? "SAME" : "DIFFERENT") << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 1524
final_rank: 12

code_snippet: #include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define REP(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) REP(i, 0, n)
#define ALL(x) begin(x), end(x)

struct point {
	int x, y, z;
	explicit point(int x_ = 0, int y_ = 0, int z_ = 0):x(x_), y(y_), z(z_) {}

	point operator+(const point &p) const {
		return point(x + p.x, y + p.y, z + p.z);
	}

	point operator-(const point &p) const {
		return point(x - p.x, y - p.y, z - p.z);
	}

	point operator-() const {
		return point(-x, -y, -z);
	}

	bool operator<(const point &p) const {
		if(x != p.x) return x < p.x;
		if(y != p.y) return y < p.y;
		return z < p.z;
	}

	bool operator==(const point &p) const {
		return x == p.x && y == p.y && z == p.z;
	}
};

struct segment {
	point a, b;
	segment(const point &a_, const point &b_):a(a_), b(b_) {
		if(b < a) swap(a, b);
	}

	bool operator<(const segment &s) const {
		if(!(a == s.a)) return a < s.a;
		return b < s.b;
	}

	bool operator==(const segment&s) const {
		return a == s.a && b == s.b;
	}
};

point rotate_x(const point &p) {
	return point(p.x, p.z, -p.y);
}

point rotate_y(const point &p) {
	return point(p.z, p.y, -p.x);
}

point rotate_z(const point &p) {
	return point(p.y, -p.x, p.z);
}

bool input(set<segment> &segs) {
	int n;
	cin >> n;

	if(n == 0) return false;
	segs.clear();

	point move_d[128];
	move_d['x'] = point(1, 0, 0);
	move_d['y'] = point(0, 1, 0);
	move_d['z'] = point(0, 0, 1);

	point current(0, 0, 0);
	map<int, point> label;

	rep(i, n) {
		string s;
		cin >> s;

		if(isdigit(s[0])) { // label
			const int idx = stoi(s);
			if(!label.count(idx)) {
				label[idx] = current;
			}
			else {
				current = label[idx];
			}
		}
		else { // move
			point d = move_d[s[1]];
			if(s[0] == '-') d = -d;
			const point next = current + d;
			segs.insert(segment(current, next));
			current = move(next);
		}
	}

	return true;
}

bool match(const set<segment> &a, const set<segment> &b) {
	if(a.size() != b.size()) return false;
	auto it_a = a.cbegin();
	auto it_b = b.cbegin();

	const point offset = a.cbegin()->a - b.cbegin()->a;

	while(it_a != a.end()) {
		const segment &s_a = *it_a;
		const segment s_b(it_b->a + offset, it_b->b + offset);
		if(!(s_a == s_b)) return false;

		++it_a;
		++it_b;
	}

	return true;

}

set<segment> rotate_points(const set<segment> &segs, const function<point(const point&)> &convert) {
	set<segment> res;
	for(const auto &seg : segs) {
		res.insert(segment(convert(seg.a), convert(seg.b)));
	}
	return res;
}

bool valid(const set<segment> &a, set<segment> b) {
	rep(loop_x, 4) {
		b = rotate_points(b, rotate_x);
		rep(loop_y, 4) {
			b = rotate_points(b, rotate_y);
			rep(loop_z, 4) {
				b = rotate_points(b, rotate_z);
				if(match(a, b)) return true;
			}
		}
	}

	return false;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	set<segment> a, b;
	while(input(a)) {
		assert(input(b));
		cout << (valid(a, b) ? "SAME" : "DIFFERENT") << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 30
memory_kb: 1264
final_rank: 7

code_snippet: #include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define dump(a) (cerr << #a << " = " << (a) << endl)
#define REP(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) REP(i, 0, n)
#define ALL(x) begin(x), end(x)

struct point {
  int x, y, z;
  explicit point(int x_ = 0, int y_ = 0, int z_ = 0):x(x_), y(y_), z(z_) {}

  point operator+(const point &p) const {
	return point(x + p.x, y + p.y, z + p.z);
  }

  point operator-(const point &p) const {
	return point(x - p.x, y - p.y, z - p.z);
  }

  point operator-() const {
	return point(-x, -y, -z);
  }

  bool operator<(const point &p) const {
	if(x != p.x) return x < p.x;
	if(y != p.y) return y < p.y;
	return z < p.z;
  }

  bool operator==(const point &p) const {
	return x == p.x && y == p.y && z == p.z;
  }
};

ostream &operator<<(ostream &os, const point &p) {
  return os << '(' << p.x << ", " << p.y << ", " << p.z << ')';
}

struct segment {
  point a, b;
  segment(const point &a_, const point &b_):a(a_), b(b_) {
	if(b < a) swap(a, b);
  }

  bool operator<(const segment &s) const {
	if(a < s.a || s.a < a) return a < s.a;
	return b < s.b;
  }

  bool operator==(const segment&s) const {
	return a == s.a && b == s.b;
  }
};

point rotate_x(const point &p) {
  return point(p.x, p.z, -p.y);
}

point rotate_y(const point &p) {
  return point(p.z, p.y, -p.x);
}

point rotate_z(const point &p) {
  return point(p.y, -p.x, p.z);
}

bool input(set<segment> &segs) {
  int n;
  cin >> n;

  if(n == 0) return false;

  point move_d[128];
  move_d['x'] = point(1, 0, 0);
  move_d['y'] = point(0, 1, 0);
  move_d['z'] = point(0, 0, 1);
  
  const point move_x(1, 0, 0), move_y(0, 1, 0), move_z(0, 0, 1);

  point current(0, 0, 0);
  map<int, point> label;

  rep(i, n) {
	string s;
	cin >> s;

	if(isdigit(s[0])) { // label
	  const int idx = stoi(s);
	  if(!label.count(idx)) {
		label[idx] = current;
	  }
	  else {
		current = label[idx];
	  }
	}
	else { // move
	  point d = move_d[s[1]];
	  if(s[0] == '-') d = -d;
	  const point next = current + d;
	  segs.insert(segment(current, next));
	  current = move(next);
	}
  }

   return true;
}

bool match(const set<segment> &a, const set<segment> &b) {
  if(a.size() != b.size()) return false;
  auto it_a = a.cbegin();
  auto it_b = b.cbegin();

  const point offset = a.cbegin()->a - b.cbegin()->a;

  while(it_a != a.end()) {
	const segment &s_a = *it_a;
	const segment s_b(it_b->a + offset, it_b->b + offset);
	if(!(s_a == s_b)) return false;

	++it_a;
	++it_b;
  }

  return true;

}

set<segment> rotate_points(const set<segment> &segs, const function<point(const point&)> &convert) {
  set<segment> res;
  for(const auto &seg : segs) {
	res.insert(segment(convert(seg.a), convert(seg.b)));
  }
  return res;
}

bool valid(const set<segment> &a, set<segment> b) {
  rep(loop_x, 4) {
	b = rotate_points(b, rotate_x);
	rep(loop_y, 4) {
	  b = rotate_points(b, rotate_y);
	  rep(loop_z, 4) {
		b = rotate_points(b, rotate_z);
		if(match(a, b)) return true;
	  }
	}
  }

  return false;
}

int main() {
  set<segment> a, b;
  while(input(a)) {
	assert(input(b));
	cout << (valid(a, b) ? "SAME" : "DIFFERENT") << endl;
	a.clear();
	b.clear();
  }

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1252
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct P {
  int x, y, z;
  P() : x(0), y(0), z(0) {}
  P(int x, int y, int z) : x(x), y(y), z(z) {}
  bool operator < (const P &p) const {
    if(x != p.x) return x < p.x;
    if(y != p.y) return y < p.y;
    return z < p.z;
  }
  bool operator == (const P &p) const {
    return x == p.x && y == p.y && z == p.z;
  }
  P operator + (const P &p) const {
    return P(x+p.x, y+p.y, z+p.z);
  }
  P& operator += (const P &p) {
    return ( *this = *this + p );
  }
  P operator - (const P &p) const {
    return P(x-p.x, y-p.y, z-p.z);
  }
  P& operator -= (const P &p) {
    return ( *this = *this - p );
  }
};

typedef pair<P,P> Seg;
typedef vector<Seg> Key;

const int INF = 1<<28;

void rotate(int &x, int &y) {
  int t = x;
  x = -y;
  y = t;
}

Key rotate(Key k, int dir) {
  int n = k.size();
  for(int i = 0; i < n; ++i) {
    pair<int,int> p;
    if(dir == 0) {
      rotate(k[i].first.x, k[i].first.y);
      rotate(k[i].second.x, k[i].second.y);
    } else if(dir == 1) {
      rotate(k[i].first.y, k[i].first.z);
      rotate(k[i].second.y, k[i].second.z);
    } else if(dir == 2) {
      rotate(k[i].first.z, k[i].first.x);
      rotate(k[i].second.z, k[i].second.x);
    }
  }
  return k;
}

Key normalize(Key k) {
  int n = k.size();
  for(int i = 0; i < n; ++i) {
    if(k[i].second < k[i].first) swap(k[i].first, k[i].second);
  }
  P mini(INF,INF,INF);
  for(int i = 0; i < n; ++i) {
    mini.x = min(mini.x, min(k[i].first.x, k[i].second.x));
    mini.y = min(mini.y, min(k[i].first.y, k[i].second.y));
    mini.z = min(mini.z, min(k[i].first.z, k[i].second.z));
  }
  for(int i = 0; i < n; ++i) {
    k[i].first -= mini;
    k[i].second -= mini;
  }
  sort(k.begin(), k.end());
  return k;
}

Key getKey() {
  int q;
  cin >> q;
  if(!q) return Key();
  Key k;
  P p(0,0,0);
  P label[100];
  fill(label, label+100, P(INF,INF,INF));
  while(q--) {
    string s;
    cin >> s;
    P pre = p;
    if(0) {
    } else if(s == "+x") {
      ++p.x;
    } else if(s == "-x") {
      --p.x;
    } else if(s == "+y") {
      ++p.y;
    } else if(s == "-y") {
      --p.y;
    } else if(s == "+z") {
      ++p.z;
    } else if(s == "-z") {
      --p.z;
    } else {
      int id = atoi(s.c_str());
      if(label[id].x == INF) {
        label[id] = p;
      } else {
        p = label[id];
      }
      pre.x = INF;
    }
    if(pre.x != INF) {
      k.push_back(Seg(pre,p));
    }
  }
  return k;
}

bool equals(Key a, Key b) {
  a = normalize(a);
  for(int i = 0; i < 6; ++i) {
    for(int j = 0; j < 4; ++j) {
      b = normalize(b);
      if(a == b) return true;
      b = rotate(b, 0);
    }
    if(i < 3) {
      b = rotate(b, 1);
    } else if(i == 3) {
      b = rotate(b, 2);
    } else if(i == 4) {
      b = rotate(b, 2);
      b = rotate(b, 2);
    }
  }
  return false;
}

int main() {
  while(1) {
    Key a = getKey();
    if(!a.size()) break;
    Key b = getKey();
    /*
    cout << "A" << endl;
    for(int i = 0; i < a.size(); ++i) {
      cout << "(" << a[i].first.x << "," << a[i].first.y << "," << a[i].first.z << "),";
      cout << "(" << a[i].second.x << "," << a[i].second.y << "," << a[i].second.z << ")" << endl;
    }
    cout << "B" << endl;
    for(int i = 0; i < b.size(); ++i) {
      cout << "(" << b[i].first.x << "," << b[i].first.y << "," << b[i].first.z << "),";
      cout << "(" << b[i].second.x << "," << b[i].second.y << "," << b[i].second.z << ")" << endl;
    }
    */
    if(equals(a,b)) cout << "SAME" << endl;
    else cout << "DIFFERENT" << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1252
final_rank: 4

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
struct P{
  int x, y, z;
  P() : x(0), y(0), z(0) {}
  P(int x, int y, int z) : x(x), y(y), z(z) {}
  bool operator < (const P& p) const {
    if(x != p.x) return x < p.x;
    if(y != p.y) return y < p.y;
    return z < p.z;
  }
  bool operator == (const P& p) const {
    return x == p.x && y == p.y && z == p.z;
  }
  P operator - (const P& p) const {
    return P(x - p.x, y - p.y, z - p.z);
  }
};
typedef pair<P, P> L;
vector<L> input(){
  int N; cin >> N;
  P label[100] = {};
  bool used[100] = {};
  P cur;
  vector<L> res;
  while(N--){
    string s;
    cin >> s;
    if(isdigit(s[0])){
      int l = atoi(s.c_str());
      if(used[l]){
        cur = label[l];
      }else{
        label[l] = cur;
        used[l] = true;
      }
    }else{
      int dif = (s[0] == '+' ? 1 : -1);
      P next = cur;
      if(s[1] == 'x'){
        next.x += dif;
      }else if(s[1] == 'y'){
        next.y += dif;
      }else if(s[1] == 'z'){
        next.z += dif;
      }else{
        assert(false);
      }
      res.push_back(L(cur, next));
      cur = next;
    }
  }
  return res;
}
void update(P& p, P q){
  p.x = min(p.x, q.x);
  p.y = min(p.y, q.y);
  p.z = min(p.z, q.z);
}
vector<L> normalize(const vector<L>& s){
  P min_p = s[0].first;
  REP(i, s.size()){
    update(min_p, s[i].first);
    update(min_p, s[i].second);
  }
  vector<L> res;
  REP(i, s.size()){
    res.push_back(L(s[i].first - min_p, s[i].second - min_p));
    if(res[i].second < res[i].first) swap(res[i].first, res[i].second);
  }
  sort(res.begin(), res.end());
  return res;
}
void rotate_x(vector<L>& s){
  REP(i, s.size()){
    s[i].first = P(s[i].first.x, -s[i].first.z, s[i].first.y);
    s[i].second = P(s[i].second.x, -s[i].second.z, s[i].second.y);
  }
}
void rotate_y(vector<L>& s){
  REP(i, s.size()){
    s[i].first = P(s[i].first.z, s[i].first.y, -s[i].first.x);
    s[i].second = P(s[i].second.z, s[i].second.y, -s[i].second.x);
  }
}
void rotate_z(vector<L>& s){
  REP(i, s.size()){
    s[i].first = P(-s[i].first.y, s[i].first.x, s[i].first.z);
    s[i].second = P(-s[i].second.y, s[i].second.x, s[i].second.z);
  }
}
int main(){
  while(true){
    vector<L> k1 = input();
    if(k1.empty()) break;
    vector<L> k2 = input();
    k2 = normalize(k2);

    bool is_equal = false;
    for(int k = 0; k < 6; k++){
      if(k % 2 == 0) rotate_x(k1);
      else rotate_y(k1);
      for(int i = 0; i < 4; i++){
        rotate_z(k1);
        k1 = normalize(k1);
        if(k1 == k2){
          is_equal = true;
          //goto OUTPUT;
        }
      }
    }

OUTPUT:
    if(is_equal) cout << "SAME" << endl;
    else cout << "DIFFERENT" << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1236
final_rank: 5

code_snippet: #include<map>
#include<cctype>
#include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

struct point{
	int x,y,z;
	point operator+(const point &a)const{ return (point){x+a.x,y+a.y,z+a.z}; }
	point operator-(const point &a)const{ return (point){x-a.x,y-a.y,z-a.z}; }
	bool operator==(const point &a)const{ return x==a.x && y==a.y && z==a.z; }
};

struct edge{
	point u,v;
	bool operator==(const edge &e)const{ return u==e.u && v==e.v || u==e.v && v==e.u; }
};

struct key{
	int n;
	edge E[300];
};

key getkey(){
	key K={};
	point p={0,0,0};
	map<int,point> f;
	int n; scanf("%d",&n);
	while(n--){
		char s[8]; scanf("%s",s);

		if(isdigit(s[0])){
			int a; sscanf(s,"%d",&a);
			if(f.count(a)) p=f[a];
			else           f[a]=p;
		}
		else{
			point q=p;
			if(s[0]=='+' && s[1]=='x') q.x++;
			if(s[0]=='-' && s[1]=='x') q.x--;
			if(s[0]=='+' && s[1]=='y') q.y++;
			if(s[0]=='-' && s[1]=='y') q.y--;
			if(s[0]=='+' && s[1]=='z') q.z++;
			if(s[0]=='-' && s[1]=='z') q.z--;
			K.E[K.n++]=(edge){p,q};
			p=q;
		}
	}

	return K;
}

struct matrix{
	int a[3][3];

	point operator*(const point &p)const{
		int x=a[0][0]*p.x+a[0][1]*p.y+a[0][2]*p.z;
		int y=a[1][0]*p.x+a[1][1]*p.y+a[1][2]*p.z;
		int z=a[2][0]*p.x+a[2][1]*p.y+a[2][2]*p.z;
		return (point){x,y,z};
	}

	matrix operator*(const matrix &A)const{
		matrix B={};
		rep(i,3) rep(j,3) rep(k,3) B.a[i][j]+=a[i][k]*A.a[k][j];
		return B;
	}

	bool operator==(const matrix &A)const{
		rep(i,3) rep(j,3) if(a[i][j]!=A.a[i][j]) return false;
		return true;
	}
};

vector<matrix> R;

bool issame(const key &K1,const key &K2){
	if(K1.n!=K2.n) return false;

	point shift1=K1.E[0].u;
	point dir1=K1.E[0].v-shift1;
	rep(i,K2.n){
		point shift2,dir2;
		rep(t,2){
			if(t==0) shift2=K2.E[i].u, dir2=K2.E[i].v-shift2;
			if(t==1) shift2=K2.E[i].v, dir2=K2.E[i].u-shift2;

			rep(j,R.size()) if(R[j]*dir1==dir2) {
				bool ok=true;
				rep(k,K1.n){
					edge e=K1.E[k];
					e=(edge){e.u-shift1,e.v-shift1};
					e=(edge){R[j]*e.u,R[j]*e.v};
					e=(edge){e.u+shift2,e.v+shift2};
					if(count(K2.E,K2.E+K2.n,e)!=1){ ok=false; break; }
				}
				if(ok) return true;
			}
		}
	}
	return false;
}

int main(){
	matrix I,X,Y,Z;
	I.a[0][0]= 1; I.a[0][1]= 0; I.a[0][2]= 0;
	I.a[1][0]= 0; I.a[1][1]= 1; I.a[1][2]= 0;
	I.a[2][0]= 0; I.a[2][1]= 0; I.a[2][2]= 1;
	X.a[0][0]= 1; X.a[0][1]= 0; X.a[0][2]= 0;
	X.a[1][0]= 0; X.a[1][1]= 0; X.a[1][2]=-1;
	X.a[2][0]= 0; X.a[2][1]= 1; X.a[2][2]= 0;
	Y.a[0][0]= 0; Y.a[0][1]= 0; Y.a[0][2]=-1;
	Y.a[1][0]= 0; Y.a[1][1]= 1; Y.a[1][2]= 0;
	Y.a[2][0]= 1; Y.a[2][1]= 0; Y.a[2][2]= 0;
	Z.a[0][0]= 0; Z.a[0][1]=-1; Z.a[0][2]= 0;
	Z.a[1][0]= 1; Z.a[1][1]= 0; Z.a[1][2]= 0;
	Z.a[2][0]= 0; Z.a[2][1]= 0; Z.a[2][2]= 1;

	R.push_back(I);
	while(1){
		bool change=false;
		rep(i,R.size()){
			rep(j,3){
				matrix A=(j==0?X*R[i]:j==1?Y*R[i]:Z*R[i]);
				if(count(R.begin(),R.end(),A)==0){ R.push_back(A); change=true; }
			}
		}
		if(!change) break;
	}

	while(1){
		key K1=getkey(); if(K1.n==0) break;
		key K2=getkey();

		puts(issame(K1,K2)?"SAME":"DIFFERENT");
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 820
final_rank: 2

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>

#define INF 1001

using namespace std;

struct point{
	int x,y,z;
	point():x(0),y(0),z(0){}
	bool operator <(const point &t)const{
		if( x < t.x ){
			return true;
		}else if( x == t.x ){
			if( y < t.y ){
				return true;
			}else if( y == t.y ){
				if( z < t.z ){
					return true;
				}
			}
		}
		return false;
	}
	void rot90arndX(){ int tz = z; z = -y; y = tz; }
	void rot90arndY(){ int tz = z; z = x; x = -tz; }
	void rot90arndZ(){ int tx = x; x = y; y = -tx; }
};

struct strange_key{
	vector<point> vp;

	void rot90arndX(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndX();
		}
	}
	void rot90arndY(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndY();
		}
	}
	void rot90arndZ(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndZ();
		}
	}

	bool Same(strange_key &t){
		if( vp.size() != t.vp.size() )
			return false;

		for(int a = 0; a < 4; ++a){
			for(int b = 0; b < 4; ++b){
				for(int c = 0; c < 4; ++c){
					bool bSame = true;
					sort( vp.begin(), vp.end() );
					sort( t.vp.begin(), t.vp.end() );
					
					int dx = vp[0].x - t.vp[0].x;
					int dy = vp[0].y - t.vp[0].y;
					int dz = vp[0].z - t.vp[0].z;
					
					for(unsigned int l = 1; l < vp.size() && bSame; ++l){
						if( dx != vp[l].x - t.vp[l].x )
							bSame = false;
						if( dy != vp[l].y - t.vp[l].y )
							bSame = false;
						if( dz != vp[l].z - t.vp[l].z )
							bSame = false;
					}
					if( bSame )
						return true;

					rot90arndX();
				}
				rot90arndY();
			}
			rot90arndZ();
		}
		return false;
	}
};

void input_strange_key( istream &is, int n, strange_key &in ){
	if( is ){
		point now;
		bool val[51]={false,};
		vector<point> pos_mem(51);
		
		val[0]=true;
		for(int i = 0; i < n; ++i){
			string s;
			
			cin >> s;
			if( s[0] != '+' && s[0] != '-' ){
				int mem = atoi( s.c_str() );
				if( val[ mem ] ){
					now = pos_mem[ mem ];
				}else{
					pos_mem[ mem ] = now;
					val[ mem ] = true;
				}
			}else{
				int progress = ( s[0] == '+' ? 2 : -2 );
				point next = now;
				switch( s[1] ){
					case 'x':
						now.x += progress / 2;
						in.vp.push_back( now );
						now.x += progress / 2;
						break;
					case 'y':
						now.y += progress / 2;
						in.vp.push_back( now );
						now.y += progress / 2;
						break;
					case 'z':
						now.z += progress / 2;
						in.vp.push_back( now );
						now.z += progress / 2;
						break;
				}
			}
		}
	}
}

int main(){
	while( true ){
		int n1,n2;
		strange_key a, b;

		cin>>n1;
		if( n1 == 0 )
			break;
		input_strange_key( cin, n1, a );
		cin>>n2;
		input_strange_key( cin, n2, b );

		if( a.Same( b ) )
			cout << "SAME\n";
		else
			cout << "DIFFERENT\n";

	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include<iostream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>

#define INF 1001

using namespace std;

struct point{
	int x,y,z;
	point():x(0),y(0),z(0){}
	point(int x, int y, int z):x(x),y(y),z(z){}
	bool operator ==(const point &t)const{
		if( x == t.x && y == t.y && z == t.z )
			return true;
		return false;
	}
	bool operator <(const point &t)const{
		if( x < t.x ){
			return true;
		}else if( x == t.x ){
			if( y < t.y ){
				return true;
			}else if( y == t.y ){
				if( z < t.z ){
					return true;
				}
			}
		}
		return false;
	}
	void rot90arndX(){
		int tz = z; z = -y; y = tz;
	}
	void rot90arndY(){
		int tz = z; z = x; x = -tz;
	}
	void rot90arndZ(){
		int tx = x; x = y; y = -tx;
	}
	void set(int x, int y, int z){
		this->x = x; this->y = y; this->z = z;
	}
};

ostream &operator << (ostream &os, const point &t){
	os << '(' << t.x << ',' << t.y << ',' << t.z << ')';
	return os;
}

struct strange_key{
	vector<point> vp;
	vector<point> vcube;

	void rot90arndX(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndX();
		}
		for(unsigned int i = 0; i < vcube.size(); ++i){
			vcube[i].rot90arndX();
		}
	}
	void rot90arndY(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndY();
		}
		for(unsigned int i = 0; i < vcube.size(); ++i){
			vcube[i].rot90arndY();
		}
	}
	void rot90arndZ(){
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].rot90arndZ();
		}
		for(unsigned int i = 0; i < vcube.size(); ++i){
			vcube[i].rot90arndZ();
		}
	}
	void MoveToOrigin(int base){
		int dx = vcube[ base ].x;
		int dy = vcube[ base ].y;
		int dz = vcube[ base ].z;
		
		for(unsigned int i = 0; i < vcube.size(); ++i){
			vcube[i].x -= dx;
			vcube[i].y -= dy;
			vcube[i].z -= dz;
		}
		for(unsigned int i = 0; i < vp.size(); ++i){
			vp[i].x -= dx;
			vp[i].y -= dy;
			vp[i].z -= dz;
		}
	}
	bool Same(strange_key &t){
		if( vp.size() != t.vp.size() )
			return false;

		for(int a = 0; a < 4; ++a){
			for(int b = 0; b < 4; ++b){
				for(int c = 0; c < 4; ++c){
					for(unsigned int l = 0; l < vcube.size(); ++l){
						this->MoveToOrigin( l );
						for(unsigned int m = 0; m < vcube.size(); ++m){
							bool bSame = true;
							t.MoveToOrigin( m );
							
							sort( vp.begin(), vp.end() );
							sort( t.vp.begin(), t.vp.end() );

							for(unsigned int n = 0; n < vp.size(); ++n){
								if( !(vp[n] == t.vp[n]) ){
									bSame = false;
									break;
								}
							}
							
							/*
							cout << "Key Expression:";
							for(set<point>::iterator it = sp.begin(); it != sp.end(); ++it){
								cout << *it << ' ';
							}
							cout << "\nKey Expression:";
							for(set<point>::iterator it = t.sp.begin(); it != t.sp.end(); ++it){
								cout << *it << ' ';
							}
							cout << "\n--------------------\n";
							*/

							if( bSame )
								return true;
						}
					}
					rot90arndX();
				}
				rot90arndY();
			}
			rot90arndZ();
		}
		return false;
	}
};

void input_strange_key( istream &is, int n, strange_key &in ){
	if( is ){
		point now;
		bool val[51]={false,};
		vector<point> pos_mem(51);
		int minx=INF, maxx=-INF, miny=INF, maxy=-INF, minz=INF, maxz=-INF;
		
		val[0]=true;
		for(int i = 0; i < n; ++i){
			string s;
			
			cin >> s;
			if( s[0] != '+' && s[0] != '-' ){
				int mem = atoi( s.c_str() );
				if( val[ mem ] ){
					now = pos_mem[ mem ];
				}else{
					pos_mem[ mem ] = now;
					val[ mem ] = true;
				}
			}else{
				int progress = ( s[0] == '+' ? 2 : -2 );
				point next = now;
				switch( s[1] ){
					case 'x':
						now.x += progress / 2;
						in.vp.push_back( now );
						now.x += progress / 2;
						break;
					case 'y':
						now.y += progress / 2;
						in.vp.push_back( now );
						now.y += progress / 2;
						break;
					case 'z':
						now.z += progress / 2;
						in.vp.push_back( now );
						now.z += progress / 2;
						break;
				}
			}
			minx = std::min( minx, now.x ); maxx = std::max( maxx, now.x );
			miny = std::min( miny, now.y ); maxy = std::max( maxy, now.y );
			minz = std::min( minz, now.z ); maxz = std::max( maxz, now.z );
		}
		in.vcube.push_back( point( minx, miny, minz ) );
		in.vcube.push_back( point( minx, miny, maxz ) );
		in.vcube.push_back( point( minx, maxy, minz ) );
		in.vcube.push_back( point( minx, maxy, maxz ) );
		in.vcube.push_back( point( maxx, miny, minz ) );
		in.vcube.push_back( point( maxx, miny, maxz ) );
		in.vcube.push_back( point( maxx, maxy, minz ) );
		in.vcube.push_back( point( maxx, maxy, maxz ) );
	}
}


ostream &operator << (ostream &os, const strange_key &t){
	os << "Key Expression:\n";
	for(unsigned int i = 0; i < t.vp.size(); ++i){
		if( i != 0 )
			os << ' ';
		os << t.vp[i];
	}
	return os;
}

int main(){
	while( true ){
		int n1,n2;
		strange_key a, b;

		cin>>n1;
		if( n1 == 0 )
			break;
		input_strange_key( cin, n1, a );
		cin>>n2;
		input_strange_key( cin, n2, b );

		if( a.Same( b ) )
			cout << "SAME\n";
		else
			cout << "DIFFERENT\n";

	}
	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 928
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
#define rep(i, n) for ( int i = 0; i < (int)n; i++)

class Point{
    public:
    int x, y, z;
    Point(int x=0, int y=0, int z=0):x(x), y(y), z(z){}
    bool operator < ( const Point &p) const{
	if ( x != p.x ) return x < p.x;
	if ( y != p.y ) return y < p.y;
	if ( z != p.z ) return z < p.z;
	return false;
    }
    bool operator == ( const Point &p ) const {
	return x == p.x && y == p.y && z == p.z;
    }
};

class Edge{
    public:
    Point p[2];
    Edge(){}
    Edge(Point p1, Point p2){
	p[0] = p1; p[1] = p2; sort(p, p+2);
    }
    bool operator < ( const Edge &e ) const{
	if ( !(p[0] == e.p[0]) ) return p[0] < e.p[0];
	if ( !(p[1] == e.p[1]) ) return p[1] < e.p[1];
	return false;
    }
};

class Key{
    public:
    set<Edge> E;
    vector<Edge> EV;
    Key(){}
    void make( int n ){
	string com;
	E.clear();
	Point pre = Point(0, 0, 0);
	bool V[60];
	rep(i, 60) V[i] = false;
	Point L[60];
	rep(i, n){
	    cin >> com;
	    Point cur = pre;
	    if ( isdigit(com[0])){
		int p = atoi(com.c_str());
		if ( V[p] ){
		    pre = L[p];
		} else {
		    V[p] = true;
		    L[p] = pre;
		}
	    } else {
		if ( com == "+x" ) cur.x++;
		else if ( com == "-x" ) cur.x--;
		else if ( com == "+y" ) cur.y++;
		else if ( com == "-y" ) cur.y--;
		else if ( com == "+z" ) cur.z++;
		else if ( com == "-z" ) cur.z--;
		E.insert(Edge(pre, cur));
		pre = cur;
	    }
	}
	for ( set<Edge>::iterator it = E.begin(); it != E.end(); it++ ) EV.push_back(*it);
    }
    Point move(){
	Point p = (1000, 1000, 1000);
	for ( int i = 0; i < EV.size(); i++ ) sort(EV[i].p, EV[i].p+2);
	sort( EV.begin(), EV.end() );
	p = EV[0].p[0];

	for ( int i = 0; i < EV.size(); i++ ){
	    for ( int j = 0; j < 2; j++ ){
		EV[i].p[j].x -= p.x;
		EV[i].p[j].y -= p.y;
		EV[i].p[j].z -= p.z;
	    }
	}
    }

    void roll_x(){
	for ( int i = 0; i < EV.size(); i++ ){
	    for ( int j = 0; j < 2; j++ ){
		int tmp = EV[i].p[j].y;
		EV[i].p[j].y = EV[i].p[j].z*(-1);
		EV[i].p[j].z = tmp;
	    }
	}
    }
    void roll_y(){
	for ( int i = 0; i < EV.size(); i++ ){
	    for ( int j = 0; j < 2; j++ ){
		int tmp = EV[i].p[j].x;
		EV[i].p[j].x = EV[i].p[j].z*(-1);
		EV[i].p[j].z = tmp;
	    }
	}
    }
    void roll_z(){
	for ( int i = 0; i < EV.size(); i++ ){
	    for ( int j = 0; j < 2; j++ ){
		int tmp = EV[i].p[j].x;
		EV[i].p[j].x = EV[i].p[j].y;
		EV[i].p[j].y = tmp*(-1);
	    }
	}
    }
};

bool equals(Key key1, Key key2 ){
    for ( int i = 0; i < key1.EV.size(); i++ ) sort( key1.EV[i].p, key1.EV[i].p+2);
    sort(key1.EV.begin(), key1.EV.end());
    for ( int i = 0; i < key1.EV.size(); i++ ){
	for ( int j = 0; j < 2; j++ ){
	    if ( !(key1.EV[i].p[j] == key2.EV[i].p[j]) ) return false;
	}
    }
    return true;
}

bool check(Key key1, Key key2){
    if ( key1.EV.size() != key2.EV.size() ) return false;
    for ( int i = 0; i < key2.EV.size(); i++ ) sort( key2.EV[i].p, key2.EV[i].p+2);
    sort(key2.EV.begin(), key2.EV.end());
    key2.move();
    Key target;
    
    rep(i, 6){
	rep(j, 4){
	    target = key1;
	    target.move();
	    if ( equals(target, key2) ) return true;	    
	    key1.roll_z();
	}
	if ( i % 2 == 0 ) key1.roll_y();
	else key1.roll_x();
    }

    return false;
}

main(){
    int n;
    while(1){
	Key key1, key2;
	cin >> n;
	if ( n == 0 ) break;
	key1.make(n);
	cin >> n;
	key2.make(n);
	if ( check(key1, key2) ) cout << "SAME" << endl;
	else cout << "DIFFERENT" << endl;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 1040
final_rank: 3