Problem:
Problem F:
Traveling Cube
On a small planet named Bandai, a landing party of the starship Tadamigawa discovered colorful
cubes traveling on flat areas of the planet surface, which the landing party named beds. A cube
appears at a certain position on a bed, travels on the bed for a while, and then disappears. After
a longtime observation, a science officer Lt. Alyssa Ogawa of Tadamigawa found the rule how a
cube travels on a bed.
A bed is a rectangular area tiled with squares of the same size.
One of the squares is colored red,
one colored green,
one colored blue,
one colored cyan,
one colored magenta,
one colored yellow,
one or more colored white, and
all others, if any, colored black.
Initially, a cube appears on one of the white squares. The cube’s faces are colored as follows.
top  red
          bottom  cyan
           north  green
           south  magenta
            east  blue
            west  yellow
The cube can roll around a side of the current square at a step and thus rolls on to an adjacent
square. When the cube rolls on to a chromatically colored (red, green, blue, cyan, magenta or
yellow) square, the top face of the cube after the roll should be colored the same. When the
cube rolls on to a white square, there is no such restriction. The cube should never roll on to a
black square.
Throughout the travel, the cube can visit each of the chromatically colored squares only once,
and any of the white squares arbitrarily many times. As already mentioned, the cube can never
visit any of the black squares. On visit to the final chromatically colored square, the cube
disappears. Somehow the order of visits to the chromatically colored squares is known to us
before the travel starts.
Your mission is to find the least number of steps for the cube to visit all the chromatically
colored squares in the given order.
Input
The input is a sequence of datasets. A dataset is formatted as follows:
w d
c
11
. . .
c
w
1
.        .
       .        .
       .        .
c
1
d
. . .
c
wd
v
1
v
2
v
3
v
4
v
5
v
6
The first line is a pair of positive integers w and d separated by a space. The next d lines are
w-character-long strings
c
11
. . .
c
w
1
, . . . ,
c
1
d
. . .
c
wd
with no spaces. Each character cij is one of
the letters r, g, b, c, m, y, w and k, which stands for red, green, blue, cyan, magenta, yellow,
white and black respectively, or a sign #. Each of r, g, b, c, m, y and # occurs once and only once
in a dataset. The last line is a six-character-long string
v
1
v
2
v
3
v
4
v
5
v
6
which is a permutation of
“rgbcmy”.
The integers
w
and
d
denote the width (the length from the east end to the west end) and the
depth (the length from the north end to the south end) of a bed. The unit is the length of a
side of a square. You can assume that neither
w
nor d is greater than 30.
Each character
c
ij
shows the color of a square in the bed. The characters
c
11
,
c
w
1
,
c
1
d
and
c
wd
correspond to the north-west corner, the north-east corner, the south-west
...(truncated)

Submitted solutions:

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

#define K	0	// Black
#define W	128	// White
#define R	1	// Red
#define G	2	// Green
#define B	3	// Blue
#define C	4	// Cyan
#define	M	5	// Magenta
#define	Y	6	// Yellow
#define S	192	// Start Point | White

unsigned char rev[256];
int n, m;
int sx, sy;
unsigned char map[32][32];
unsigned char Map[256];
int seen[1 << 22]; // 8 * 8 * 8 * 8
char data[32];

const char *name[] = {
	"Undefined",
	"Red",
	"Green",
	"Blue",
	"Cyan",
	"Magenta",
	"Yellow"
};

inline int serialize(const int top, const int front, const int left, const int now) {
	return (top << 9) | (front << 6) | (left << 3) | now;
}

inline void recover(const int serial, int &top, int &front, int &left, int &now) {
	top = serial >> 9;
	front = (serial >> 6) & 7;
	left = (serial >> 3) & 7;
	now = serial & 7;
}

inline bool rotateWest(int &x, int &y, int &serial) {
	if(!y) return false; // Can't move west.
	static int top, front, left, now, ntop, nfront, nleft;
	static int ny;
	ny = y - 1;
	if (map[x][ny] == 0) return false; // Black
	recover(serial, top, front, left, now);
	ntop = rev[left]; nleft = top; nfront = front;
	if (map[x][ny] & 128) { // White
		y = ny;
		serial = serialize(ntop, nfront, nleft, now);
		return true;
	}
	if ( ntop != map[x][ny] || data[now] != map[x][ny] ) return false;
	y = ny, serial = serialize(ntop, nfront, nleft, now + 1); // Move forward
	return true;
}

inline bool rotateEast(int &x, int &y, int &serial) {
	if(y + 1 == m) return false; // Can't move east.
	static int top, front, left, now, ntop, nfront, nleft;
	static int ny;
	ny = y + 1;
	if (map[x][ny] == 0) return false; // Black
	recover(serial, top, front, left, now);
	ntop = left; nleft = rev[top]; nfront = front;
	if (map[x][ny] & 128) { // White
		y = ny;
		serial = serialize(ntop, nfront, nleft, now);
		return true;
	}
	if ( ntop != map[x][ny] || data[now] != map[x][ny] ) return false;
	y = ny, serial = serialize(ntop, nfront, nleft, now + 1); // Move forward
	return true;
}

inline bool rotateNorth(int &x, int &y, int &serial) {
	if(!x) return false; // Can't move north.
	static int top, front, left, now, ntop, nfront, nleft;
	static int nx;
	nx = x - 1;
	if (map[nx][y] == 0) return false; // Black
	recover(serial, top, front, left, now);
	ntop = front; nleft = left; nfront = rev[top];
	if (map[nx][y] & 128) { // White
		x = nx;
		serial = serialize(ntop, nfront, nleft, now);
		return true;
	}
	if ( ntop != map[nx][y] || data[now] != map[nx][y] ) return false;
	x = nx, serial = serialize(ntop, nfront, nleft, now + 1); // Move forward
	return true;
}

inline bool rotateSouth(int &x, int &y, int &serial) {
	if(x + 1 == n) return false; // Can't move north.
	static int top, front, left, now, ntop, nfront, nleft;
	static int nx;
	nx = x + 1;
	if (map[nx][y] == 0) return false; // Black
	recover(serial, top, front, left, now);
	ntop = rev[front]; nleft = left; nfront = top;
	if (map[nx][y] & 128) { // White
		x = nx;
		serial = serialize(ntop, nfront, nleft, now);
		return true;
	}
	if ( ntop != map[nx][y] || data[now] != map[nx][y] ) return false;
	x = nx, serial = serialize(ntop, nfront, nleft, now + 1); // Move forward
	return true;
}

inline int zip(const int x, const int y, const int serial) {
	return (x << 17) | (y << 12) | serial;
}

inline void unzip(const int zipped, int &x, int &y, int &serial) {
	x = zipped >> 17;
	y = (zipped >> 12) & 31;
	serial = zipped & 4095;
}

void printSerial(const int serial) {
	static int top, front, left, now;
	recover(serial, top, front, left, now);
	fprintf(stderr, "Status: Top = %s, Front = %s, Left = %s, Now = %d\n", name[top], name[front], name[left], now);
}

void printZip(const int zipped) {
	static int x, y, serial;
	unzip(zipped, x, y, serial);
	fprintf(stderr, "CurPos: x = %d, y = %d\n", x, y);
	printSerial(serial);
}

int getAns() {
	static queue<int> Q;
	while(Q.size()) Q.pop();
	memset(seen, -1, sizeof seen);
	static int zipped, nzipped;
	zipped = zip(sx, sy, serialize(R, M, Y, 0));
	Q.push(zipped);
	seen[zipped] = 0;
	while(Q.size()) {
#define RECOVER tx = cx, ty = cy, ts = cs
		zipped = Q.front();
		Q.pop();
		static int cx, cy, cs, tx, ty, ts;
		unzip(zipped, cx, cy, cs);
		RECOVER;
		if(rotateEast(tx, ty, ts)) {
			if((ts & 7) == 6) return seen[zipped] + 1;
			nzipped = zip(tx, ty, ts);
			if(seen[nzipped] < 0) {
				seen[nzipped] = seen[zipped] + 1;
				Q.push(nzipped);
			}
		}
		RECOVER;
		if(rotateWest(tx, ty, ts)) {
			if((ts & 7) == 6) return seen[zipped] + 1;
			nzipped = zip(tx, ty, ts);
			if(seen[nzipped] < 0) {
				seen[nzipped] = seen[zipped] + 1;
				Q.push(nzipped);
			}
		}
		RECOVER;
		if(rotateNorth(tx, ty, ts)) {
			if((ts & 7) == 6) return seen[zipped] + 1;
			nzipped = zip(tx, ty, ts);
			if(seen[nzipped] < 0) {
				seen[nzipped] = seen[zipped] + 1;
				Q.push(nzipped);
			}
		}
		RECOVER;
		if(rotateSouth(tx, ty, ts)) {
			if((ts & 7) == 6) return seen[zipped] + 1;
			nzipped = zip(tx, ty, ts);
			if(seen[nzipped] < 0) {
				seen[nzipped] = seen[zipped] + 1;
				Q.push(nzipped);
			}
		}
#undef RECOVER
	}
	return -1;
}

int main() {
	memset(Map, 0, sizeof Map);
	Map['#'] = S;
	Map['w'] = W;
	Map['k'] = K;
	Map['r'] = R;
	Map['g'] = G;
	Map['b'] = B;
	Map['c'] = C;
	Map['m'] = M;
	Map['y'] = Y;
	rev[R] = C;
	rev[C] = R;
	rev[G] = M;
	rev[M] = G;
	rev[B] = Y;
	rev[Y] = B;
	while(scanf("%d%d", &m, &n), n) {
		register int i, j;
		for(i = 0; i < n; ++ i) {
			scanf("%s", map[i]);
			for(j = 0; j < m; ++ j) {
				map[i][j] = Map[map[i][j]];
				if(map[i][j] & 64) sx = i, sy = j;
			}
		}
		scanf("%s", data);
		for(i = 0; i < 6; ++ i) data[i] = Map[data[i]];
		static int ans;
		ans = getAns();
		if (ans < 0) {
			puts("unreachable");
			continue;
		}
		printf("%d\n", ans);
	}
}
accuracy: 1
time_ms: 40
memory_kb: 19372
final_rank: 7

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

#define			OK			std::cout << "------------" << std::endl;
#define			DEBUG(x)		std::cout << #x << " = " << x << std::endl;

using namespace std;

const int maxn = 64;

int W, D;
char di[maxn][maxn];

const int dx[] = {0, 0, -1, 1};
const int dy[] = {-1, 1, 0, 0};

struct St {
	int t, b, n, s, e, w;

	St(int t=0, int b=1, int n=2, int s=3, int e=4, int w=5) 
	:  t(t),b(b),n(n),s(s),e(e),w(w) { }

	St rot(int way) {
		switch (way) {
			case 0 : return St(e, w, n, s, b, t);	// left
			case 1 : return St(w, e, n, s, t, b);	// right
			case 2 : return St(s, n, t, b, e, w);	// front
			case 3 : return St(n, s, b, t, e, w);	// back
		}
	}
	inline int getHash() const {
		return t + b*6 + n*36 + s*36*6 + e*36*36 + w*36*36*6;
	}
	inline bool operator<(const St &a) const {
		return getHash() < a.getHash();
	}
};

inline int getColor(char c) {
	switch(c) {
		case 'r' : return 0;
		case 'c' : return 1;
		case 'g' : return 2;
		case 'm' : return 3;
		case 'b' : return 4;
		case 'y' : return 5;
		default : return -1;
	}
}

inline int find(int &x, int &y, char c) {
	for (int i = 0;i < D;i++) {
		for (int j = 0;j < W;j++) {
			if (di[i][j] == c) {
				x = i;
				y = j;
				return 0;
			}
		}
	}
	return -1;
}

const int maxq = 100000;
int X[maxq], Y[maxq], bt, tp;
St Que[maxq];

map <St,int> Map[maxn][maxn];

inline void push(int x, int y, St a) {
	X[tp] = x; Y[tp] = y; Que[tp] = a;
	tp ++; tp %= maxq;
}

inline bool inBound(int x, int y) {
	return 0 <= x && x < D && 0 <= y && y < W && (di[x][y] == 'w' || di[x][y] == '#');
}

inline void solve(int sx, int sy, int tx, int ty) {
	for (int i = 0;i < D;i++) {
		for (int j = 0;j < W;j++) {
			if (!(sx == i && sy == j))
				Map[i][j].clear();
		}
	}
	bt = tp = 0;
	for (map<St,int>::iterator it = Map[sx][sy].begin();it != Map[sx][sy].end();it++) {
		push(sx, sy, it->first);
	}
	while (bt < tp) {
		int x = X[bt], y = Y[bt];
		St a = Que[bt];
		bt ++; bt %= maxq;

		for (int i = 0;i < 4;i++) {
			int xx = x + dx[i], yy = y + dy[i];
			St b = a.rot(i);
			if (inBound(xx, yy) && (Map[xx][yy].find(b) == Map[xx][yy].end() || Map[xx][yy][b] > Map[x][y][a] + 1)) {
				Map[xx][yy][b] = Map[x][y][a] + 1;
				push(xx, yy, b);
			}
			if (xx == tx && yy == ty && b.t == getColor(di[xx][yy]) && (Map[xx][yy].find(b) == Map[xx][yy].end() || Map[xx][yy][b] > Map[x][y][a] + 1)) {
				Map[xx][yy][b] = Map[x][y][a] + 1;
			}
		}
	}
}

int main()
{
	while (scanf("%d%d\n", &W, &D), !(W == 0 && D == 0)) {
		for (int i = 0;i < D;i++) {
			for (int j = 0;j < W;j++) {
				Map[i][j].clear();
			}
		}
		for (int i = 0;i < D;i++) {
			scanf("%s\n", di[i]);
		}
		char path[16];
		scanf("%s\n", path);
		int sx, sy, tx, ty;
		find(sx, sy, '#');
		Map[sx][sy][St()] = 0;
		for (int i = 0;i < 6;i++) {
			find(tx, ty, path[i]);
			solve(sx, sy, tx, ty);
	//		cout << Map[tx][ty].size() << endl;
			sx = tx; sy = ty;
		}
		if (Map[tx][ty].empty()) {
			puts("unreachable");
		} else {
			int ans = 100000000;
			for (map<St, int>::iterator it = Map[tx][ty].begin();it != Map[tx][ty].end();it ++) {
				ans = min(ans, it->second);
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 7040
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
using namespace std;
using ll = long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

// up    0
// down  1
// left  2
// right 3
// front 4
// back  5

// r 0
// u 1
// l 2
// d 3

int face_perm[42][6];
int face_d[42][4];
string colors = "rcybmg";
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,-1,0,1 };


void enum_face_perm(){
    vector<vector<int>> Q;
    Q.push_back({0,1,2,3,4,5});
    map<vector<int>, int> perms;
    perms[Q[0]] = 0;
    rep(i,Q.size()){
        //cout << i << " : "; for(auto a : Q[i]){ cout << a << " "; } cout << endl;
        rep(f,2){
            auto a = Q[i];
            auto d0 = a;
            d0[0] = a[2^f];
            d0[1] = a[3^f];
            d0[2] = a[1^f];
            d0[3] = a[0^f];
            if(perms.count(d0) == 0){
                int v = Q.size();
                perms[d0] = v;
                Q.push_back(d0);
            }
            face_d[i][0+f*2] = perms[d0];
            d0 = a;
            d0[0] = a[4^f];
            d0[1] = a[5^f];
            d0[4] = a[1^f];
            d0[5] = a[0^f];
            if(perms.count(d0) == 0){
                int v = Q.size();
                perms[d0] = v;
                Q.push_back(d0);
            }
            face_d[i][1+f*2] = perms[d0];
        }
    }
    rep(i,24) rep(j,6) face_perm[i][j] = Q[i][j];
}

int H, W;
int idx(int y, int x){ return y*W+x; }
int dist[2000][24][6];

int main(){
    cin.tie(nullptr); ios::sync_with_stdio(false);
    enum_face_perm();
    queue<pair<pair<int,int>, int>> que;
    while(true){
        cin >> W >> H; if(H == 0) break;
        vector<string> G(H); rep(y,H) cin >> G[y];
        string g;
        rep(x,W+2) g.push_back('k');
        rep(y,H) g += "k" + G[y] + "k";
        rep(x,W+2) g.push_back('k');
        H += 2; W += 2;
        int s = g.find('#'); g[s] = 'w';
        int pt[6] = {};
        rep(i,6) pt[i] = g.find(colors[i]);
        int ord[6] = {};
        rep(i,6){ char c; cin >> c; ord[i] = colors.find(c); }
        que.push({{ s, 0 }, 0 });
        int dd[4] = {};
        rep(d,4) dd[d] = dy[d] * W + dx[d];
        rep(i,W*H) rep(j,24) rep(p,6) dist[i][j][p] = -1;
        dist[s][0][0] = 0;
        int ans = 1001001001;
        while(que.size()){
            int u = que.front().first.first;
            int x = que.front().first.second;
            int p = que.front().second;
            int w = dist[u][x][p];
            //cout << u << " " << x << " " << p << " " << w << endl;
            que.pop();
            rep(d,4){
                int nxu = u + dd[d];
                int nxx = face_d[x][d];
                int nxp = p;
                if(g[nxu] != 'w'){
                    if(g[nxu] != colors[face_perm[nxx][0]]) continue;
                    if(pt[ord[p]] != nxu) continue;
                    if(p == 5){ ans = w+1; break; }
                    nxp += 1;
                }
                if(dist[nxu][nxx][nxp] != -1) continue;
                dist[nxu][nxx][nxp] = w + 1;
                que.push({ {nxu,nxx}, nxp });
            }
            if(ans < 1001001001) break;
        }
        while(que.size()) que.pop();
        if(ans == 1001001001){ cout << "unreachable\n"; }
        else cout << ans << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 4004
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

using face = char;
struct dice {
    face front, right, back, left, top, bottom;

    dice() {}
    dice(string s) {
        front = s[0];
        right = s[1];
        back = s[2];
        left = s[3];
        top = s[4];
        bottom = s[5];
    }
    string state() {
        return ""s + front + right + back + left + top + bottom;
    }

    face cw(face f) {
        return f;
    }

    dice to_front() {
        dice x;
        x.front = top;
        x.top = cw(cw(back));
        x.back = cw(cw(bottom));
        x.bottom = front;
        x.left = cw(left);
        x.right = cw(cw(cw(right)));
        return x;
    }
    dice to_back() {
        dice x;
        x.front = bottom;
        x.top = front;
        x.back = cw(cw(top));
        x.bottom = cw(cw(back));
        x.left = cw(cw(cw(left)));
        x.right = cw(right);
        return x;
    }
    dice to_right() {
        dice x;
        x.right = cw(cw(cw(top)));
        x.top = cw(cw(cw(left)));
        x.left = cw(cw(cw(bottom)));
        x.bottom = cw(cw(cw(right)));
        x.front = cw(front);
        x.back = cw(cw(cw(back)));
        return x;
    }
    dice to_left() {
        dice x;
        x.left = cw(top);
        x.top = cw(right);
        x.right = cw(bottom);
        x.bottom = cw(left);
        x.front = cw(cw(cw(front)));
        x.back = cw(back);
        return x;
    }
};

int main() {
    cin.tie(0)->sync_with_stdio(0);

    while(true) {
        int W, H; cin >> W >> H;
        if(W == 0) return 0;
        vector<string> S(H);
        for(auto& e : S) cin >> e;

        int sx, sy;
        rep(x, H) rep(y, W) if(S[x][y] == '#') {
            tie(sx, sy) = make_pair(x, y);
            S[x][y] = 'w';
        }

        dice sd;
        sd.top = 'r';
        sd.bottom = 'c';
        sd.back = 'g';
        sd.front = 'm';
        sd.right = 'b';
        sd.left = 'y';

        using state = tuple<int, int, int, string>;
        vector<state> ss;
        ss.push_back({0, sx, sy, sd.state()});

        const int INF = 1e9;

        string gs; cin >> gs;
        for(char gcol : gs) {
            priority_queue<state, vector<state>, greater<state>> q;
            vector dist(H, vector(W, map<string, int>{}));
            for(auto s : ss) {
                auto [c, x, y, d] = s;
                dist[x][y][d] = c;
                q.push(s);
            }
            while(not q.empty()) {
                auto [c, x, y, d] = q.top(); q.pop();
                if(dist[x][y].count(d) and dist[x][y][d] < c) continue;

                auto push = [&](int nx, int ny, string nd) {
                    if(0 <= nx and nx < H and 0 <= ny and ny < W and (S[nx][ny] == 'w' or (S[nx][ny] == gcol and dice(nd).top == gcol))) {
                        if(not dist[nx][ny].count(nd)) dist[nx][ny][nd] = INF;
                        if(chmin(dist[nx][ny][nd], c + 1)) q.push({c + 1, nx, ny, nd});
                    }
                };

                auto [nx, ny] = make_pair(x + 1, y);
                string nd = dice(d).to_front().state();
                push(nx, ny, nd);

                tie(nx, ny) = make_pair(x - 1, y);
                nd = dice(d).to_back().state();
                push(nx, ny, nd);

                tie(nx, ny) = make_pair(x, y + 1);
                nd = dice(d).to_right().state();
                push(nx, ny, nd);

                tie(nx, ny) = make_pair(x, y - 1);
                nd = dice(d).to_left().state();
                push(nx, ny, nd);
            }

            auto [gx, gy] = [&] {
                rep(x, H) rep(y, W) if(S[x][y] == gcol) return make_pair(x, y);
                assert(0); 
            }();
            ss.clear();
            for(auto [d, c] : dist[gx][gy]) ss.push_back({c, gx, gy, d});
        }

        if(ss.empty()) {
            cout << "unreachable" << "\n";
        } else {
            int ans = INF;
            for(auto s : ss) chmin(ans, get<0>(s));
            cout << ans << "\n";
        }
    }
}
accuracy: 1
time_ms: 630
memory_kb: 4364
final_rank: 18

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int rots[4][6] = {{1,3,2,4,0,5},{5,1,0,2,4,3},{4,0,2,1,3,5},{2,1,3,5,4,0}};
int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};

map<char,int> mp;
map<vector<int>,int> DiceID;
vector<vector<int>> Dices;
int Cur = 0;

struct Dice {
    vector<int> A;
    Dice() {
        A.resize(6);
        iota(ALL(A),0);
    }
    Dice(vector<int> a) : A(a) {};
    int& operator[] (int i) {
        return A[i];
    }
    Dice rot(int dir) {
        Dice Ret;
        rep(i,0,6) Ret[i] = this->A[rots[dir][i]];
        return Ret;
    }
    int top() {
        return this->A[0];
    }
    int getID() {
        if (DiceID.count(this->A)) return DiceID[this->A];
        DiceID[this->A] = Cur;
        Dices.push_back(this->A);
        Cur++;
        return Cur-1;
    }
};

int main() {
    mp['r'] = 0;
    mp['g'] = 1;
    mp['b'] = 2;
    mp['c'] = 3;
    mp['m'] = 4;
    mp['y'] = 5;
    mp['w'] = 6;
    mp['k'] = -1;
    Dice _;
    _.getID();
while(1) {
    int N, M;
    cin >> M >> N;
    if (N == 0) return 0;
    vector G(N,vector<int>(M));
    vector DP(N,vector(M,vector(24,vector<int>(7,inf))));
    queue<tuple<int,int,int,int>> Q;
    rep(i,0,N) {
        rep(j,0,M) {
            char C;
            cin >> C;
            if (C == '#') G[i][j] = 6, DP[i][j][0][0] = 0, Q.push({i,j,0,0});
            else G[i][j] = mp[C];
        }
    }
    vector<int> ord(6);
    rep(i,0,6) {
        char C;
        cin >> C;
        ord[i] = mp[C];
    }
    while(!Q.empty()) {
        auto [X,Y,ID,P] = Q.front();
        Q.pop();
        if (P == 6) break;
        Dice D = Dices[ID];
        rep(i,0,4) {
            int NX = X + dx[i], NY = Y + dy[i];
            Dice ND = D.rot(i);
            int NID = ND.getID();
            if (NX < 0 || N <= NX || NY < 0 || M <= NY) continue;
            if (G[NX][NY] < 0) continue;
            if (G[NX][NY] != 6 && G[NX][NY] != ND.top()) continue;
            if (G[NX][NY] != 6 && G[NX][NY] != ord[P]) continue;
            int NP;
            if (G[NX][NY] == ord[P]) NP = P+1;
            else NP = P;
            if (chmin(DP[NX][NY][NID][NP],DP[X][Y][ID][P]+1)) {
                Q.push({NX,NY,NID,NP});
            }
        }
    }
    int ANS = inf;
    rep(i,0,N) {
        rep(j,0,M) {
            rep(k,0,24) {
                chmin(ANS,DP[i][j][k][6]);
            }
        }
    }
    if (ANS == inf) cout << "unreachable" << endl;
    else cout << ANS << endl;
}
}
accuracy: 1
time_ms: 280
memory_kb: 5128
final_rank: 11

code_snippet: #include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

#define INF (1000000000)

using namespace std;
using ll = long long;

template <typename T>
constexpr bool chmin(T& min, const T target) {
	if (target < min) {
		min = target;
		return true;
	}
	return false;
}

// face
// 0: top
// 1: bottom
// 2: north
// 3: south
// 4: east
// 5: west

// direction
// 0: north
// 1: south
// 2: east
// 3: west

class Index {
   public:
	int phase{0}, i{0}, j{0};
	string state{"012345"};
};

string Roll(string state, const int direction) {
	const int R[4][6]{
		{2, 3, 1, 0, 4, 5},
		{3, 2, 0, 1, 4, 5},
		{4, 5, 2, 3, 1, 0},
		{5, 4, 2, 3, 0, 1},
	};

	string rolled{"012345"};
	for (int f = 0; f < 6; f++) rolled[R[direction][f]] = state[f];
	return rolled;
}

int main(void) {
	const int directions[4][2]{{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

	while (true) {
		int width, depth;
		string visits;
		cin >> width >> depth;
		if (width == 0) break;
		vector<vector<char>> bed(width, vector<char>(depth));
		Index start{0, 0, 0, "rcgmby"};
		for (int j = 0; j < depth; j++) {
			string row;
			cin >> row;
			for (int i = 0; i < width; i++) {
				bed[i][j] = row[i];
				if (bed[i][j] == '#') {
					start.i = i;
					start.j = j;
					bed[i][j] = 'w';
				}
			}
		}
		cin >> visits;

		cout << flush;

		ll min_distance_to_goal = INF;
		vector<vector<vector<map<string, ll>>>> distance(6, vector<vector<map<string, ll>>>(width, vector<map<string, ll>>(depth)));
		distance[start.phase][start.i][start.j][start.state] = 0;
		queue<Index> tobe_search;
		tobe_search.push(start);
		while (!tobe_search.empty()) {
			Index current = tobe_search.front();
			tobe_search.pop();

			for (int d = 0; d < 4; d++) {
				Index adjacent{
					current.phase + (bed[current.i][current.j] == 'w' ? 0 : 1),
					current.i + directions[d][0],
					current.j + directions[d][1],
					Roll(current.state, d),
				};

				if (adjacent.phase == 6 ||
					adjacent.i < 0 || width <= adjacent.i || adjacent.j < 0 || depth <= adjacent.j ||
					bed[adjacent.i][adjacent.j] == 'k' ||
					(bed[adjacent.i][adjacent.j] != 'w' && bed[adjacent.i][adjacent.j] != visits[adjacent.phase]) ||
					(bed[adjacent.i][adjacent.j] != 'w' && bed[adjacent.i][adjacent.j] != adjacent.state[0]) ||
					distance[adjacent.phase][adjacent.i][adjacent.j].find(adjacent.state) != distance[adjacent.phase][adjacent.i][adjacent.j].end())
				{
					continue;
				}

				distance[adjacent.phase][adjacent.i][adjacent.j][adjacent.state] = distance[current.phase][current.i][current.j][current.state] + 1;
				tobe_search.push(adjacent);
			}

			if (bed[current.i][current.j] == visits[5]) chmin(min_distance_to_goal, distance[current.phase][current.i][current.j][current.state]);
		}

		if (min_distance_to_goal != INF) cout << min_distance_to_goal << endl;
		else cout << "unreachable" << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 8764
final_rank: 13

code_snippet: #include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

#define INF (1000000000)

using namespace std;
using ll = long long;

template <typename T>
constexpr bool chmin(T& min, const T target) {
	if (target < min) {
		min = target;
		return true;
	}
	return false;
}

// face
// 0: top
// 1: bottom
// 2: north
// 3: south
// 4: east
// 5: west

// direction
// 0: north
// 1: south
// 2: east
// 3: west

class Index {
   public:
	int phase{0}, i{0}, j{0};
	string state{"012345"};
};

string Roll(string state, const int direction) {
	const int R[4][6]{
		{2, 3, 1, 0, 4, 5},
		{3, 2, 0, 1, 4, 5},
		{4, 5, 2, 3, 1, 0},
		{5, 4, 2, 3, 0, 1},
	};

	string rolled{"012345"};
	for (int f = 0; f < 6; f++) rolled[R[direction][f]] = state[f];
	return rolled;
}

int main(void) {
	const int directions[4][2]{{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

	while (true) {
		int width, depth;
		string visits;
		cin >> width >> depth;
		if (width == 0) break;
		vector<vector<char>> bed(width, vector<char>(depth));
		Index start{0, 0, 0, "rcgmby"};
		for (int j = 0; j < depth; j++) {
			string row;
			cin >> row;
			for (int i = 0; i < width; i++) {
				bed[i][j] = row[i];
				if (bed[i][j] == '#') {
					start.i = i;
					start.j = j;
					bed[i][j] = 'w';
				}
			}
		}
		cin >> visits;

		cout << flush;

		ll min_distance_to_goal = INF;
		vector<vector<vector<map<string, ll>>>> distance(6, vector<vector<map<string, ll>>>(width, vector<map<string, ll>>(depth)));
		distance[start.phase][start.i][start.j][start.state] = 0;
		queue<Index> tobe_search;
		tobe_search.push(start);
		while (!tobe_search.empty()) {
			Index current = tobe_search.front();
			tobe_search.pop();

			for (int d = 0; d < 4; d++) {
				Index adjacent{
					current.phase + (bed[current.i][current.j] == 'w' ? 0 : 1),
					current.i + directions[d][0],
					current.j + directions[d][1],
					Roll(current.state, d),
				};

				if (adjacent.phase == 6) continue;

				if (adjacent.i < 0 || width <= adjacent.i || adjacent.j < 0 || depth <= adjacent.j ||
					bed[adjacent.i][adjacent.j] == 'k' ||
					(bed[adjacent.i][adjacent.j] != 'w' && bed[adjacent.i][adjacent.j] != visits[adjacent.phase])) continue;

				if (bed[adjacent.i][adjacent.j] != 'w' && adjacent.state[0] != bed[adjacent.i][adjacent.j]) continue;

				if (distance[adjacent.phase][adjacent.i][adjacent.j].find(adjacent.state) != distance[adjacent.phase][adjacent.i][adjacent.j].end()) continue;

				distance[adjacent.phase][adjacent.i][adjacent.j][adjacent.state] = distance[current.phase][current.i][current.j][current.state] + 1;
				tobe_search.push(adjacent);
			}

			if (bed[current.i][current.j] == visits[5]) chmin(min_distance_to_goal, distance[current.phase][current.i][current.j][current.state]);

			// cout << current.phase << endl;
		}

		if (min_distance_to_goal != INF) cout << min_distance_to_goal << endl;
		else cout << "unreachable" << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 8780
final_rank: 12

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

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long
int encoding(int step, pair<int, int> x, string s)
{
  int encoder = 0;
  REP(i, s.length())
  {
    encoder *= 26;
    encoder += s[i] - 'a';
  }
  return step + 901 * (x.first * 31 + x.second) + 100000000 * encoder;
}

string R(string s)
{
  string b = s;
  b[0] = s[5];
  b[1] = s[4];
  b[2] = s[2];
  b[3] = s[3];
  b[4] = s[0];
  b[5] = s[1];
  return b;
}
string D(string s)
{
  string b = s;
  b[0] = s[2];
  b[1] = s[3];
  b[2] = s[1];
  b[3] = s[0];
  b[4] = s[4];
  b[5] = s[5];
  return b;
}

void solve()
{
  int r, c;
  cin >> r >> c;
  if (r == 0)
    exit(0);
  vector<string> inputs;
  REP(i, c)
  {
    string s;
    cin >> s;
    inputs.push_back(s);
  }
  string target;
  cin >> target;
  queue<tuple<pair<int, int>, pair<int, int>, string>> nexts;
  set<int> already;
  REP(i, c)
  {
    REP(q, r)
    {
      if (inputs[i][q] == '#')
      {
        nexts.push({{0, 0}, {i, q}, "rcgmby"});
      }
    }
  }
  while (!nexts.empty())
  {
    tuple<pair<int, int>, pair<int, int>, string> now = nexts.front();
    nexts.pop();
    pair<int, int> place = get<1>(now);
    if (inputs[place.first][place.second] != 'w' and inputs[place.first][place.second] != '#')
    {
      if (inputs[place.first][place.second] != target[get<0>(now).second])
        continue;
      if (get<2>(now)[0] != target[get<0>(now).second])
        continue;
      get<0>(now).second++;
      if (get<0>(now).second == 6)
      {
        cout << get<0>(now).first << endl;
        return;
      }
    }
    get<0>(now).first++;
    const int dx[4] = {1, -1, 0, 0};
    REP(i, 4)
    {
      int x = place.first + dx[i];
      int y = place.second + dx[3 - i];
      if (!(x >= 0 and x < c and y >= 0 and y < r))
      {
        continue;
      }
      if (inputs[x][y] == 'k')
        continue;
      string moves = get<2>(now);
      if (i == 0)
      {
        moves = D(moves);
      }
      else if (i == 1)
      {
        moves = D(D(D(moves)));
      }
      else if (i == 2)
      {
        moves = R(R(R(moves)));
      }
      else
      {
        moves = R(moves);
      }
      int target = encoding(get<0>(now).second, {x, y}, moves);
      if (already.count(target))
        continue;
      already.insert(target);
      nexts.push({get<0>(now), {x, y}, moves});
    }
  }
  cout << "unreachable" << endl;
}

#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(10);
  // scanf/printf user should delete this fasterize input/output script

  int t = 10000;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 6508
final_rank: 14

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

#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

using namespace std;
#define INFS (1LL<<28)
#define DEKAI 1000000007
//#define INF 1000000007
//#define MOD 1000000007
#define lp(i,n) for(int i=0;i<(long long)n;i++)
#define lps(i,n) for(int i=1;i<=n;i++)
#define all(c) begin(c), end(c)

//#define int long long

namespace {
#define __DECLARE__(C)    \
	    template <typename T> \
	std::ostream &operator<<(std::ostream &, const C<T> &);

#define __DECLAREM__(C)               \
	    template <typename T, typename U> \
	std::ostream &operator<<(std::ostream &, const C<T, U> &);

    __DECLARE__(std::vector)
    __DECLARE__(std::deque)
    __DECLARE__(std::set)
    __DECLARE__(std::stack)
    __DECLARE__(std::queue)
    __DECLARE__(std::priority_queue)
    __DECLARE__(std::unordered_set)
    __DECLAREM__(std::map)
    __DECLAREM__(std::unordered_map)

    template <typename T, typename U>
    std::ostream &operator<<(std::ostream &, const std::pair<T, U> &);
    template <typename... T>
    std::ostream &operator<<(std::ostream &, const std::tuple<T...> &);
    template <typename T, std::size_t N>
    std::ostream &operator<<(std::ostream &, const std::array<T, N> &);

    template <typename Tuple, std::size_t N>
    struct __TuplePrinter__ {
        static void print(std::ostream &os, const Tuple &t) {
            __TuplePrinter__<Tuple, N - 1>::print(os, t);
            os << ", " << std::get<N - 1>(t);
        }
    };

    template <typename Tuple>
    struct __TuplePrinter__<Tuple, 1> {
        static void print(std::ostream &os, const Tuple &t) { os << std::get<0>(t); }
    };

    template <typename... T>
    std::ostream &operator<<(std::ostream &os, const std::tuple<T...> &t) {
        os << '(';
        __TuplePrinter__<decltype(t), sizeof...(T)>::print(os, t);
        os << ')';
        return os;
    }

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

#define __INNER__                             \
	os << '[';                                \
	for (auto it = begin(c); it != end(c);) { \
		os << *it;                            \
		os << (++it != end(c) ? ", " : "");   \
	}                                         \
	return os << ']';

    template <typename T, std::size_t N>
    std::ostream &operator<<(std::ostream &os, const std::array<T, N> &c) {
        __INNER__
    }

#define __DEFINE__(C)                                           \
	    template <typename T>                                       \
	std::ostream &operator<<(std::ostream &os, const C<T> &c) { \
		__INNER__                                               \
	}

#define __DEFINEM__(C)                                             \
	    template <typename T, typename U>                              \
	std::ostream &operator<<(std::ostream &os, const C<T, U> &c) { \
		__INNER__                                                  \
	}

#define __DEFINEW__(C, M1, M2)                                  \
	    template <typename T>                                       \
	std::ostream &operator<<(std::ostream &os, const C<T> &c) { \
		std::deque<T> v;                                        \
		for (auto d = c; !d.empty(); d.pop()) v.M1(d.M2());     \
			return os << v;                                         \
	}

    __DEFINE__(std::vector)
    __DEFINE__(std::deque)
    __DEFINE__(std::set)
    __DEFINEW__(std::stack, push_front, top)
    __DEFINEW__(std::queue, push_back, front)
    __DEFINEW__(std::priority_queue, push_front, top)
    __DEFINE__(std::unordered_set)
    __DEFINEM__(std::map)
    __DEFINEM__(std::unordered_map)
}

#define pii pair<int,int>
#define ll long long
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

// modint
template <signed M, unsigned T>
struct mod_int {
    constexpr static signed MODULO = M;
    constexpr static unsigned TABLE_SIZE = T;

    signed x;

    mod_int() : x(0) {}

    mod_int(long long y) : x(static_cast<signed>(y >= 0 ? y % MODULO : MODULO - (-y) % MODULO)) {}

    mod_int(int y) : x(y >= 0 ? y % MODULO : MODULO - (-y) % MODULO) {}

    mod_int &operator+=(const mod_int &rhs) {
        if ((x += rhs.x) >= MODULO) x -= MODULO;
        return *this;
    }

    mod_int &operator-=(const mod_int &rhs) {
        if ((x += MODULO - rhs.x) >= MODULO) x -= MODULO;
        return *this;
    }

    mod_int &operator*=(const mod_int &rhs) {
        x = static_cast<signed>(1LL * x * rhs.x % MODULO);
        return *this;
    }

    mod_int &operator/=(const mod_int &rhs) {
        x = static_cast<signed>((1LL * x * rhs.inv().x) % MODULO);
        return *this;
    }

    mod_int operator-() const { return mod_int(-x); }

    mod_int operator+(const mod_int &rhs) const { return mod_int(*this) += rhs; }

    mod_int operator-(const mod_int &rhs) const { return mod_int(*this) -= rhs; }

    mod_int operator*(const mod_int &rhs) const { return mod_int(*this) *= rhs; }

    mod_int operator/(const mod_int &rhs) const { return mod_int(*this) /= rhs; }

    bool operator<(const mod_int &rhs) const { return x < rhs.x; }

    mod_int inv() const {
        assert(x != 0);
        if (x <= static_cast<signed>(TABLE_SIZE)) {
            if (_inv[1].x == 0) prepare();
            return _inv[x];
        } else {
            signed a = x, b = MODULO, u = 1, v = 0, t;
            while (b) {
                t = a / b;
                a -= t * b;
                std::swap(a, b);
                u -= t * v;
                std::swap(u, v);
            }
            return mod_int(u);
        }
    }

    mod_int pow(long long t) const {
        assert(!(x == 0 && t == 0));
        mod_int e = *this, res = mod_int(1);
        for (; t; e *= e, t >>= 1)
            if (t & 1) res *= e;
        return res;
    }

    mod_int fact() {
        if (_fact[0].x == 0) prepare();
        return _fact[x];
    }

    mod_int inv_fact() {
        if (_fact[0].x == 0) prepare();
        return _inv_fact[x];
    }

    mod_int choose(mod_int y) {
        assert(y.x <= x);
        return this->fact() * y.inv_fact() * mod_int(x - y.x).inv_fact();
    }

    static mod_int _inv[TABLE_SIZE + 1];

    static mod_int _fact[TABLE_SIZE + 1];

    static mod_int _inv_fact[TABLE_SIZE + 1];

    static void prepare() {
        _inv[1] = 1;
        for (int i = 2; i <= (int)TABLE_SIZE; ++i) {
            _inv[i] = 1LL * _inv[MODULO % i].x * (MODULO - MODULO / i) % MODULO;
        }
        _fact[0] = 1;
        for (unsigned i = 1; i <= TABLE_SIZE; ++i) {
            _fact[i] = _fact[i - 1] * int(i);
        }
        _inv_fact[TABLE_SIZE] = _fact[TABLE_SIZE].inv();
        for (int i = (int)TABLE_SIZE - 1; i >= 0; --i) {
            _inv_fact[i] = _inv_fact[i + 1] * (i + 1);
        }
    }
};

template <int M, unsigned F>
std::ostream &operator<<(std::ostream &os, const mod_int<M, F> &rhs) {
    return os << rhs.x;
}

template <int M, unsigned F>
std::istream &operator>>(std::istream &is, mod_int<M, F> &rhs) {
    long long s;
    is >> s;
    rhs = mod_int<M, F>(s);
    return is;
}

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_inv[TABLE_SIZE + 1];

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_fact[TABLE_SIZE + 1];

template <int M, unsigned F>
mod_int<M, F> mod_int<M, F>::_inv_fact[TABLE_SIZE + 1];

template <int M, unsigned F>
bool operator==(const mod_int<M, F> &lhs, const mod_int<M, F> &rhs) {
    return lhs.x == rhs.x;
}

template <int M, unsigned F>
bool operator!=(const mod_int<M, F> &lhs, const mod_int<M, F> &rhs) {
    return !(lhs == rhs);
}

const int MF = 1000010;
const int MOD = 998244353;

using mint = mod_int<MOD, MF>;

mint binom(int n, int r) { return (r < 0 || r > n || n < 0) ? 0 : mint(n).choose(r); }

mint fact(int n) { return mint(n).fact(); }

mint inv_fact(int n) { return mint(n).inv_fact(); }
const ll mod = 1000000007;
// const int MAX_N = 1024; // 4MB
// nCr % mod

inline ll gcds(ll a, ll b) { return b ? gcds(b, a % b) : a; }
inline ll lcms(ll a, ll b) { return a / gcd(a, b) * b; }

template <typename Int, Int MOD, int N>
struct comb_util {
    std::array<Int, N + 1> fc, ifc;

    comb_util() {
        fc[0] = 1;
        for (int i = 1; i <= N; i++) fc[i] = fc[i - 1] * i % MOD;
        ifc[N] = inv(fc[N]);
        for (int i = N - 1; i >= 0; i--) ifc[i] = ifc[i + 1] * (i + 1) % MOD;
    }

    Int fact(Int n) { return fc[n]; }

    Int inv_fact(Int n) { return ifc[n]; }

    Int inv(Int n) { return pow(n, MOD - 2); }

    Int pow(Int n, Int a) {
        Int res = 1, exp = n;
        for (; a; a /= 2) {
            if (a & 1) res = res * exp % MOD;
            exp = exp * exp % MOD;
        }
        return res;
    }

    Int perm(Int n, Int r) {
        if (r < 0 || n < r)
            return 0;
        else
            return fc[n] * ifc[n - r] % MOD;
    }

    Int binom(Int n, Int r) {
        if (n < 0 || r < 0 || n < r) return 0;
        return fc[n] * ifc[r] % MOD * ifc[n - r] % MOD;
    }

    Int homo(Int n, Int r) {
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : binom(n + r - 1, r);
    }
};

using comb = comb_util<long long, 1000000007, 3000000>;

#define RK 200000000000
#define LK 300000000000
#define PL 400000000000
#define MI 500000000000
#define KA 600000000000
#define PI acos(-1)
#define int long long

enum { U, B, L, F, R, D};
struct dice {
    int face[6];
    dice() {
        face[F] = 1;
        face[R] = 2;
        face[U] = 3;
        face[B] = 6;
        face[L] = 5;
        face[D] = 4;
    }
    int find_face(int f){
        lp(i,6){
            if(face[i]==f)return i;
        }
        return -1;
    }
    int get_hash(){
        int res = 0;
        lp(i,6){
            res*=7;
            res+=face[i];
        }
        return res;
    }
    void turn(int dir){
        switch(dir){
            case R:
                rotate(U,R,D,L);
                break;
            case B:
                rotate(U,B,D,F);
                break;
            case L:
                rotate(U,L,D,R);
                break;
            case F:
                rotate(U,F,D,B);
                break;
            case U:
                rotate(F,R,B,L);
            case D:
                rotate(F,L,B,R);
            default:
                assert(false);
        }
    }

    int& operator[](int n) {
        return face[n];
    }
    const int& operator[](int n) const {
        return face[n];
    }

    vector<dice> all_rolls() {
        vector<dice> res;
        lp(k,6){
            lp(i,4){
                res.push_back(*this);
                turn(R);
            }
            turn(k%2==1?U:F);
        }
        return res;
    }

    void rotate(int a,int b,int c, int d){
        int t = face[d];
        face[d]=face[c];
        face[c]=face[b];
        face[b]=face[a];
        face[a]=t;
    }
};


signed main(){
    map<char,int> face;
    face['r']=3;
    face['c']=4;
    face['g']=1;
    face['m']=6;
    face['b']=2;
    face['y']=5;

    while(1){
        int w,d;
        cin>>w>>d;
        if(w==0)break;
        vector<string> s(d);
        lp(i,d)cin>>s[i];
        int sx,sy;
        lp(i,d){
            lp(j,w){
                if(s[i][j]=='#'){
                    sx=i;
                    sy=j;
                    s[i][j]='w';
                }
            }
        }
        string t;
        cin>>t;
        queue<pair<pair<int,int>,pair<dice,pair<int,int>>>> q;
        set<pair<pair<int,int>,pair<int,int>>> st;
        dice def = dice();
        //x y dice cnt target
        q.push({{sx,sy},{def,{0,0}}});
        st.insert({{sx,sy},{def.get_hash(),0}});

        int dir[4] = {B,F,R,L};
        int dx[4] = {1, -1, 0, 0};
        int dy[4] = {0, 0, 1, -1};

        int ans = -1;
        while(!q.empty()&&ans==-1){
            int x = q.front().first.first;
            int y = q.front().first.second;
            dice di = q.front().second.first;
            int cnt = q.front().second.second.first;
            int tit = q.front().second.second.second;
            //cout<<x<<" "<<y<<" "<<cnt<<" "<<tit<<" "<<di.find_face(3)<<endl;
            //cout<<di[0]<<di[1]<<di[2]<<di[3]<<di[4]<<di[5]<<endl;
            q.pop();
            lp(i,4){
                int nx = dx[i]+x;
                int ny = dy[i]+y;
                if(nx<0||nx>=d||ny<0||ny>=w)continue;
                dice nd = di;
                nd.turn(dir[i]);

                if(s[nx][ny]=='k')continue;
                if(st.find({{nx,ny},{nd.get_hash(),tit}})!=st.end()){
                    continue;
                }

                if(s[nx][ny]!='w'){
                    if(s[nx][ny]!=t[tit])continue;
                    if(nd.find_face(face[s[nx][ny]])!=U)continue;
                    if(tit+1==6){
                        ans=cnt+1;
                        break;
                    }
                    q.push({{nx,ny},{nd,{cnt+1,tit+1}}});
                    st.insert({{nx,ny},{nd.get_hash(),tit+1}});
                }
                else{
                    q.push({{nx,ny},{nd,{cnt+1,tit}}});
                    st.insert({{nx,ny},{nd.get_hash(),tit}});
                }
            }

        }
        if(ans==-1){
            cout<<"unreachable"<<endl;
        }
        else cout<<ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 360
memory_kb: 20184
final_rank: 17

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

struct Dice {
    std::array<int, 6> surface;

    Dice(int TOP = 1, int FRONT = 2) {
        assert(1 <= TOP and TOP <= 6);
        assert(1 <= FRONT and FRONT <= 6);
        assert(TOP + FRONT != 7);
        surface[0] = TOP;
        surface[1] = FRONT;
        surface[2] = dice[TOP - 1][FRONT - 1];
        surface[3] = 7 - surface[2];
        surface[4] = 7 - surface[1];
        surface[5] = 7 - surface[0];
    }

    Dice(const std::vector<int>& v) {
        assert(v.size() == 6);
        for (size_t i = 0; i < 6; i++) surface[i] = v[i];
    }

    const int& top() const { return surface[0]; }
    const int& front() const { return surface[1]; }
    const int& right() const { return surface[2]; }
    const int& left() const { return surface[3]; }
    const int& back() const { return surface[4]; }
    const int& bottom() const { return surface[5]; }
    const int& operator[](int k) const { return surface[k]; }

    int& top() { return surface[0]; }
    int& front() { return surface[1]; }
    int& right() { return surface[2]; }
    int& left() { return surface[3]; }
    int& back() { return surface[4]; }
    int& bottom() { return surface[5]; }
    int& operator[](int k) { return surface[k]; }

    bool operator==(const Dice& d) const { return surface == d.surface; }
    bool operator!=(const Dice& d) const { return surface != d.surface; }
    bool operator<(const Dice& d) const { return surface < d.surface; }

    int roll(int k) {  // x++, x--, y++, y--, turn right, turn left
        assert(0 <= k and k < 6);
        int tmp = surface[code[k][0]];
        for (int i = 0; i < 3; i++) surface[code[k][i]] = surface[code[k][i + 1]];
        surface[code[k][3]] = tmp;
        return surface[0];
    }

    int rollc(char c) {
        for (int k = 0; k < 6; k++) {
            if (direction[k] != c) continue;
            return roll(k);
        }
        assert(false);
    }

    int hash() const {
        int res = 0;
        for (size_t i = 0; i < 6; i++) {
            assert(1 <= surface[i] and surface[i] <= 6);
            (res *= 6) += surface[i] - 1;
        }
        return res;
    }

    std::vector<Dice> make_all() {
        std::vector<Dice> res;
        for (int i = 0; i < 6; i++) {
            Dice d(*this);
            if (i == 1) d.roll(2);
            if (i == 2) d.roll(3);
            if (i == 3) d.roll(3), d.roll(3);
            if (i == 4) d.roll(5);
            if (i == 5) d.roll(4);
            for (int j = 0; j < 4; j++) {
                res.emplace_back(d);
                d.roll(0);
            }
        }
        return res;
    }

    Dice identifier() {
        auto dices = make_all();
        return *min_element(dices.begin(), dices.end());
    }

private:
    const int dice[6][6] = {{0, 3, 5, 2, 4, 0}, {4, 0, 1, 6, 0, 3}, {2, 6, 0, 0, 1, 5},
                            {5, 1, 0, 0, 6, 2}, {3, 0, 6, 1, 0, 4}, {0, 4, 2, 5, 3, 0}};
    const int code[6][4] = {{0, 3, 5, 2}, {0, 2, 5, 3}, {0, 1, 5, 4}, {0, 4, 5, 1}, {1, 2, 4, 3}, {1, 3, 4, 2}};
    const char direction[6] = {'E', 'W', 'N', 'S', 'R', 'L'};
};

/**
 * @brief Dice
 * @docs docs/util/Dice.md
 */

const int INF = 1e9;
const int MAX_H = 32, MAX_S = 24, MAX_C = 6;
const int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
int dp[MAX_H][MAX_H][MAX_S][MAX_C + 1];

int ctoi(char c) {
    if (c == 'r') return 1;
    if (c == 'c') return 6;
    if (c == 'g') return 5;
    if (c == 'm') return 2;
    if (c == 'b') return 3;
    if (c == 'y') return 4;
    if (c == 'k') return 7;
    return 8;
}

void solve(int w, int d) {
    vector<string> S(d);
    for (auto& s : S) cin >> s;
    string T;
    cin >> T;

    int sx, sy, gx, gy;
    for (int i = 0; i < d; i++) {
        for (int j = 0; j < w; j++) {
            if (S[i][j] == '#') sx = i, sy = j;
            if (S[i][j] == T.back()) gx = i, gy = j;
            for (int k = 0; k < MAX_S; k++) {
                for (int l = 0; l <= MAX_C; l++) {
                    dp[i][j][k][l] = INF;
                }
            }
        }
    }

    Dice dice;
    auto all = dice.make_all();
    map<int, int> mp;
    for (size_t i = 0; i < all.size(); i++) mp[all[i].hash()] = i;
    queue<tuple<int, int, int, int, int>> que;
    dp[sx][sy][0][0] = 0;
    que.emplace(-dp[sx][sy][0][0], sx, sy, 0, 0);
    auto update = [&](int val, int x, int y, int s, int c) {
        if (dp[x][y][s][c] <= val) return;
        dp[x][y][s][c] = val;
        que.emplace(-val, x, y, s, c);
    };

    while (!que.empty()) {
        auto t = que.front();
        que.pop();
        int val, x, y, s, c;
        tie(val, x, y, s, c) = t;
        val *= -1;
        if (c == MAX_C) continue;
        auto cur = all[s];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 0 or d <= nx or ny < 0 or w <= ny) continue;
            if (S[nx][ny] == 'k') continue;
            cur.roll(i);
            int to = ctoi(S[nx][ny]);
            if (to <= 6) {
                if (to == ctoi(T[c]) and cur.top() == to) {
                    update(val + 1, nx, ny, mp[cur.hash()], c + 1);
                }
            } else
                update(val + 1, nx, ny, mp[cur.hash()], c);
            cur.roll(i ^ 1);
        }
    }

    int ans = INF;
    for (int k = 0; k < MAX_S; k++) ans = min(ans, dp[gx][gy][k][MAX_C]);
    if (ans == INF)
        cout << "unreachable" << '\n';
    else
        cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    for (int w, d; cin >> w >> d, w;) solve(w, d);
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3820
final_rank: 4

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <array>
#include <cassert>
#include <string>
#include <vector>

struct Dice {
    std::array<int, 6> surface;

    Dice(int TOP = 1, int FRONT = 2) {
        assert(1 <= TOP and TOP <= 6);
        assert(1 <= FRONT and FRONT <= 6);
        assert(TOP + FRONT != 7);
        surface[0] = TOP;
        surface[1] = FRONT;
        surface[2] = dice[TOP - 1][FRONT - 1];
        surface[3] = 7 - surface[2];
        surface[4] = 7 - surface[1];
        surface[5] = 7 - surface[0];
    }

    Dice(const std::vector<int>& v) {
        assert(v.size() == 6);
        for (size_t i = 0; i < 6; i++) surface[i] = v[i];
    }

    const int& top() const { return surface[0]; }
    const int& front() const { return surface[1]; }
    const int& right() const { return surface[2]; }
    const int& left() const { return surface[3]; }
    const int& back() const { return surface[4]; }
    const int& bottom() const { return surface[5]; }
    const int& operator[](int k) const { return surface[k]; }

    int& top() { return surface[0]; }
    int& front() { return surface[1]; }
    int& right() { return surface[2]; }
    int& left() { return surface[3]; }
    int& back() { return surface[4]; }
    int& bottom() { return surface[5]; }
    int& operator[](int k) { return surface[k]; }

    bool operator==(const Dice& d) const { return surface == d.surface; }
    bool operator!=(const Dice& d) const { return surface != d.surface; }
    bool operator<(const Dice& d) const { return surface < d.surface; }

    int roll(int k) {  // x++, x--, y++, y--, turn right, turn left
        assert(0 <= k and k < 6);
        int tmp = surface[code[k][0]];
        for (int i = 0; i < 3; i++) surface[code[k][i]] = surface[code[k][i + 1]];
        surface[code[k][3]] = tmp;
        return surface[0];
    }

    int rollc(char c) {
        for (int k = 0; k < 6; k++) {
            if (direction[k] != c) continue;
            return roll(k);
        }
        assert(false);
    }

    int hash() const {
        int res = 0;
        for (size_t i = 0; i < 6; i++) {
            assert(1 <= surface[i] and surface[i] <= 6);
            (res *= 6) += surface[i] - 1;
        }
        return res;
    }

    std::vector<Dice> make_all() {
        std::vector<Dice> res;
        for (int i = 0; i < 6; i++) {
            Dice d(*this);
            if (i == 1) d.roll(2);
            if (i == 2) d.roll(3);
            if (i == 3) d.roll(3), d.roll(3);
            if (i == 4) d.roll(5);
            if (i == 5) d.roll(4);
            for (int j = 0; j < 4; j++) {
                res.emplace_back(d);
                d.roll(0);
            }
        }
        return res;
    }

    Dice identifier() {
        auto dices = make_all();
        return *min_element(dices.begin(), dices.end());
    }

private:
    const int dice[6][6] = {{0, 3, 5, 2, 4, 0}, {4, 0, 1, 6, 0, 3}, {2, 6, 0, 0, 1, 5},
                            {5, 1, 0, 0, 6, 2}, {3, 0, 6, 1, 0, 4}, {0, 4, 2, 5, 3, 0}};
    const int code[6][4] = {{0, 3, 5, 2}, {0, 2, 5, 3}, {0, 1, 5, 4}, {0, 4, 5, 1}, {1, 2, 4, 3}, {1, 3, 4, 2}};
    const char direction[6] = {'E', 'W', 'N', 'S', 'R', 'L'};
};

/**
 * @brief Dice
 * @docs docs/util/Dice.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

const int MAX_H = 32, MAX_S = 24, MAX_C = 6;
const int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
int dp[MAX_H][MAX_H][MAX_S][MAX_C + 1];

int ctoi(char c) {
    if (c == 'r') return 1;
    if (c == 'c') return 6;
    if (c == 'g') return 5;
    if (c == 'm') return 2;
    if (c == 'b') return 3;
    if (c == 'y') return 4;
    if (c == 'k') return 7;
    return 8;
}

void solve(int w, int d) {
    vector<string> S(d);
    for (auto& s : S) cin >> s;
    string T;
    cin >> T;

    int sx, sy, gx, gy;
    for (int i = 0; i < d; i++) {
        for (int j = 0; j < w; j++) {
            if (S[i][j] == '#') sx = i, sy = j;
            if (S[i][j] == T.back()) gx = i, gy = j;
            for (int k = 0; k < MAX_S; k++) {
                for (int l = 0; l <= MAX_C; l++) {
                    dp[i][j][k][l] = INF;
                }
            }
        }
    }

    Dice dice;
    auto all = dice.make_all();
    map<int, int> mp;
    for (size_t i = 0; i < all.size(); i++) mp[all[i].hash()] = i;
    queue<tuple<int, int, int, int, int>> que;
    dp[sx][sy][0][0] = 0;
    que.emplace(-dp[sx][sy][0][0], sx, sy, 0, 0);
    auto update = [&](int val, int x, int y, int s, int c) {
        if (dp[x][y][s][c] <= val) return;
        dp[x][y][s][c] = val;
        que.emplace(-val, x, y, s, c);
    };

    while (!que.empty()) {
        auto t = que.front();
        que.pop();
        int val, x, y, s, c;
        tie(val, x, y, s, c) = t;
        val *= -1;
        if (c == MAX_C) continue;
        auto cur = all[s];
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 0 or d <= nx or ny < 0 or w <= ny) continue;
            if (S[nx][ny] == 'k') continue;
            cur.roll(i);
            int to = ctoi(S[nx][ny]);
            if (to <= 6) {
                if (to == ctoi(T[c]) and cur.top() == to) {
                    update(val + 1, nx, ny, mp[cur.hash()], c + 1);
                }
            } else
                update(val + 1, nx, ny, mp[cur.hash()], c);
            cur.roll(i ^ 1);
        }
    }

    int ans = INF;
    for (int k = 0; k < MAX_S; k++) ans = min(ans, dp[gx][gy][k][MAX_C]);
    if (ans == INF)
        cout << "unreachable" << '\n';
    else
        cout << ans << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    for (int w, d; cin >> w >> d, w;) solve(w, d);
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 4056
final_rank: 5

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

struct state{
    int x,y;
    int idx;
    array<char, 6> dice;
    state(int _x, int _y, int _idx, array<char, 6> _dice){
        x = _x;
        y = _y;
        idx = _idx;
        dice = _dice;
    }
};
bool operator< (state const &a, state const &b){
    if(a.x != b.x){
        return a.x < b.x;
    }
    else if(a.y != b.y){
        return a.y < b.y;
    }
    else if(a.idx != b.idx){
        return a.idx < b.idx;
    }
    else{
        return a.dice < b.dice;
    }
}

int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false); 
    int w,h;
    array<char, 6> init_dice;
    init_dice = {'r','m','b','g','y','c'};
    while(cin >> w >> h,w){
        vector<string> s(h);
        for(int i=0;i<h;i++){
            cin >> s[i];
        }
        string per; cin >> per;
        queue<state> q;
        map<state,int> dp;
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                if(s[i][j] == '#'){
                    s[i][j] = 'w';
                    q.push(state(i,j,0,init_dice));
                    dp[state(i,j,0,init_dice)] = 0;
                }
            }
        }
        int res = -1;
        while(q.size()){
            auto p = q.front(); q.pop();
            int cost = dp[p];
            if(p.idx == 6){
                res = cost;
                break;
            }
            int x = p.x, y = p.y;
            auto dice = p.dice;
            for(int k=0;k<4;k++){
                int nx = x+dx[k];
                int ny = y+dy[k];
                auto nx_dice = dice;
                if(k == 0){
                    nx_dice[3] = dice[0];
                    nx_dice[0] = dice[1];
                    nx_dice[1] = dice[5];
                    nx_dice[5] = dice[3];
                }
                else if(k == 1){
                    nx_dice[0] = dice[3];
                    nx_dice[1] = dice[0];
                    nx_dice[5] = dice[1];
                    nx_dice[3] = dice[5];
                }
                else if(k == 2){
                    nx_dice[2] = dice[0];
                    nx_dice[5] = dice[2];
                    nx_dice[4] = dice[5];
                    nx_dice[0] = dice[4];
                }
                else{
                    nx_dice[2] = dice[5];
                    nx_dice[5] = dice[4];
                    nx_dice[4] = dice[0];
                    nx_dice[0] = dice[2];
                }
                if(0<=nx and nx<h and 0<=ny and ny<w){
                    auto nx_state = state(nx,ny,p.idx,nx_dice);
                    if(s[nx][ny] == 'w'){
                        if(dp.find(nx_state) == dp.end()){
                            dp[nx_state] = cost + 1;
                            q.push(nx_state);
                        }
                    }
                    else if(per[p.idx] == s[nx][ny]){
                        if(per[p.idx] == nx_dice[0]){
                            nx_state.idx++;
                            if(dp.find(nx_state) == dp.end()){
                                dp[nx_state] = cost + 1;
                                q.push(nx_state);
                            }
                        }
                    }
                }
            }
        }
        if(res == -1) cout << "unreachable" << "\n";
        else cout << res << "\n";
    }
}
accuracy: 1
time_ms: 490
memory_kb: 7196
final_rank: 15

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

const int N=30;
const int D=4;
const int S=24;
const int O=6;

const int dx[D]={-1,0,0,1};
const int dy[D]={0,-1,1,0};

string roll(string c, int d) {
    char t;
    switch(d) {
        case 0:  // {1,0,4,3}
            t=c[1]; c[1]=c[0]; c[0]=c[4]; c[4]=c[3]; c[3]=t; break;
        case 1:  // {5,0,2,3}
            t=c[5]; c[5]=c[0]; c[0]=c[2]; c[2]=c[3]; c[3]=t; break;
        case 2:  // {3,2,0,5}
            t=c[3]; c[3]=c[2]; c[2]=c[0]; c[0]=c[5]; c[5]=t; break;
        case 3:  // {3,4,0,1}
            t=c[3]; c[3]=c[4]; c[4]=c[0]; c[0]=c[1]; c[1]=t; break;
    }
    return c;
}


vector<string> cube;
int w,d,s[N][N][S][1+O];
string bed[N],order;

int cubeid(string s) {
    int i=0;
    while (i<cube.size() && cube[i]!=s) i++;
    return i;
}

void init_cubes() {
    cube.push_back("rgbcmy");
    for (int i=0; i<cube.size(); i++) {
        for (int d=0; d<D; d++) {
            string s=roll(cube[i],d);
            int j=cubeid(s);
            if (j>=cube.size()) cube.push_back(s);
        }
    }
}

void loc(char c, int &x, int &y) {
    for (x=0; x<d; x++)
        for (y=0; y<w; y++)
            if (bed[x][y]==c) return;
}

struct State { int x,y,cid,ord; };

int solve() {
    cin>>w>>d;
    if (w==0 && d==0) return 0;
    for (int i=0; i<d; i++) cin>>bed[i];
    cin>>order;

    // BFS: s[x][y][cid][ord] means the min step to reach (x,y), at that time,
    // its faces are the same as cube[cid] and have visited ord colors.
    int x,y;
    queue<State> Q;
    order.insert(0,"#");
    memset(s,-1,sizeof(s));
    loc('#',x,y);
    s[x][y][0][0]=0;
    Q.push({x,y,0,0});
    while (!Q.empty()) {
        auto u=Q.front();
        Q.pop();
        for (int j=0; j<D; j++) {
            string cb=roll(cube[u.cid],j);
            State v = {u.x+dx[j], u.y+dy[j], cubeid(cb), u.ord};
            int su=s[u.x][u.y][u.cid][u.ord];

            if (0<=v.x && v.x<d && 0<=v.y && v.y<w) {
                if (bed[v.x][v.y]=='w' || bed[v.x][v.y]=='#') {
                    // pass
                } else if (cb[0]==bed[v.x][v.y] && cb[0]==order[v.ord+1]) {
                    v.ord+=1;
                } else {
                    continue;
                }
                if (s[v.x][v.y][v.cid][v.ord]==-1) {
                    s[v.x][v.y][v.cid][v.ord]=su+1;
                    Q.push(v);
                }
            }
        }
    }

    loc(order[O],x,y);
    int k=-1;
    for (int i=0; i<S; i++) {
        int j=s[x][y][i][O];
        if (j!=-1 && (k==-1 || k>j)) k=j;
    }
    if (k==-1) {
        cout<<"unreachable\n";
    } else {
        cout<<k<<'\n';
    }
    return 1;
}

int main() {
    init_cubes();
    while (solve());
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 3824
final_rank: 8

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

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

vector<int> rotate_N(const vector<int> &dice) {
    vector<int> new_dice = dice;
    new_dice[0] = dice[2];
    new_dice[2] = dice[5];
    new_dice[5] = dice[4];
    new_dice[4] = dice[0];
    return new_dice;
}

vector<int> rotate_S(const vector<int> &dice) {
    vector<int> new_dice = dice;
    new_dice[2] = dice[0];
    new_dice[5] = dice[2];
    new_dice[4] = dice[5];
    new_dice[0] = dice[4];
    return new_dice;
}

vector<int> rotate_E(const vector<int> &dice) {
    vector<int> new_dice = dice;
    new_dice[3] = dice[0];
    new_dice[0] = dice[1];
    new_dice[1] = dice[5];
    new_dice[5] = dice[3];
    return new_dice;
}

vector<int> rotate_W(const vector<int> &dice) {
    vector<int> new_dice = dice;
    new_dice[3] = dice[5];
    new_dice[5] = dice[1];
    new_dice[1] = dice[0];
    new_dice[0] = dice[3];
    return new_dice;
}

using T = tuple<int, int, int, int, int>;

char maze[30][31];
char v[7];
int dist[30][30][6][6][7];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
// top front
int r[6][6];
int main() {
    r[0][1] = 2;
    r[0][2] = 4;
    r[0][3] = 1;
    r[0][4] = 3;

    r[1][0] = 3;
    r[1][2] = 0;
    r[1][3] = 5;
    r[1][5] = 2;

    r[2][0] = 1;
    r[2][1] = 5;
    r[2][4] = 0;
    r[2][5] = 4;

    r[3][0] = 4;
    r[3][1] = 0;
    r[3][4] = 5;
    r[3][5] = 1;

    r[4][0] = 2;
    r[4][2] = 5;
    r[4][3] = 0;
    r[4][5] = 3;

    r[5][1] = 3;
    r[5][2] = 1;
    r[5][3] = 4;
    r[5][4] = 2;

    while (1) {
        int w, d;
        cin >> w >> d;
        if (w == 0)
            break;
        for (int i = 0; i < d; i++)
            cin >> maze[i];
        cin >> v;
        memset(dist, -1, sizeof(dist));
        queue<T> que;
        for (int i = 0; i < d; i++) {
            for (int j = 0; j < w; j++) {
                if (maze[i][j] == '#') {
                    que.emplace(j, i, 0, 2, 0);
                    dist[j][i][0][2][0] = 0;
                    maze[i][j] = 'w';
                }
            }
        }
        int ans = -1;
        while (!que.empty()) {
            T now = que.front();
            que.pop();
            int x = get<0>(now);
            int y = get<1>(now);
            int top = get<2>(now);
            int front = get<3>(now);
            int k = get<4>(now);
            if (k == 6) {
                ans = dist[x][y][top][front][k];
                break;
            }
            vector<int> dice(6);
            dice[0] = top;
            dice[2] = front;
            dice[3] = r[top][front];
            dice[5] = 5 - dice[0];
            dice[4] = 5 - dice[2];
            dice[1] = 5 - dice[3];
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (0 > nx || nx >= w || 0 > ny || ny >= d ||
                    maze[ny][nx] == 'k')
                    continue;
                if (maze[ny][nx] != 'w' && maze[ny][nx] != v[k])
                    continue;
                vector<int> new_dice;
                if (i == 0)
                    new_dice = rotate_E(dice);
                else if (i == 1)
                    new_dice = rotate_S(dice);
                else if (i == 2)
                    new_dice = rotate_W(dice);
                else
                    new_dice = rotate_N(dice);
                int color = -1;
                if (maze[ny][nx] == 'r')
                    color = 0;
                else if (maze[ny][nx] == 'y')
                    color = 1;
                else if (maze[ny][nx] == 'm')
                    color = 2;
                else if (maze[ny][nx] == 'g')
                    color = 3;
                else if (maze[ny][nx] == 'b')
                    color = 4;
                else if (maze[ny][nx] == 'c')
                    color = 5;
                if (color != -1 && new_dice[0] != color)
                    continue;
                int nk = k + (color != -1);
                if (dist[nx][ny][new_dice[0]][new_dice[2]][nk] == -1) {
                    dist[nx][ny][new_dice[0]][new_dice[2]][nk] =
                        dist[x][y][top][front][k] + 1;
                    que.emplace(nx, ny, new_dice[0], new_dice[2], nk);
                }
            }
        }
        if (ans == -1)
            cout << "unreachable" << endl;
        else
            cout << ans << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 4256
final_rank: 3

code_snippet: #include<cstdio>
#include<map>
#include<queue>
using namespace std;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int w, d;
char c[30][31], v[7];
char convert[8] = "rcgmby";

struct Dice {
  int d[6]; // (top, bottom, up, down, right, left)
  // 0:red, 1:cyan, 2:green, 3:magenta, 4:blue, 5:yellow
  Dice(int d1 = 0, int d2 = 1, int d3 = 2, int d4 = 3, int d5 = 4, int d6 = 5) {
    d[0] = d1;
    d[1] = d2;
    d[2] = d3;
    d[3] = d4;
    d[4] = d5;
    d[5] = d6;
  }
  int get() {
    int result = 0;
    for (int i = 0; i < 6; i++) result = result * 6 + d[i];
    return result;
  }
  Dice up() {
    return Dice(d[3], d[2], d[0], d[1], d[4], d[5]);
  }
  Dice down() {
    return Dice(d[2], d[3], d[1], d[0], d[4], d[5]);
  }
  Dice right() {
    return Dice(d[5], d[4], d[2], d[3], d[0], d[1]);
  }
  Dice left() {
    return Dice(d[4], d[5], d[2], d[3], d[1], d[0]);
  }
  Dice move(int num) {
    if (num == 0) return down();
    if (num == 1) return right();
    if (num == 2) return up();
    return left();
  }
};

using P = pair<int, int>;
using Q = pair<int, P>;
using R = pair<Q, Dice>;

void solve() {
  map<int, int> mp[6][30][30];
  queue<R> que;
  for (int i = 0; i < d; i++) for (int j = 0; j < w; j++) if (c[i][j] == '#') {
    R p = R(Q(0, P(i, j)), Dice());
    que.push(p);
    mp[0][i][j][p.second.get()] = 0;
  }
  while (!que.empty()) {
    R r = que.front(); que.pop();
    int x = r.first.second.first, y = r.first.second.second, num = r.first.first;
    Dice dice = r.second;
    for (int i = 0; i < 4; i++) {
      int num2 = num;
      int x2 = x + dx[i], y2 = y + dy[i];
      if (x2 < 0 || y2 < 0 || x2 == d || y2 == w) continue;
      Dice dice2 = dice.move(i);
      if (c[x2][y2] != 'w' && c[x2][y2] != '#') {
        if (v[num2] == c[x2][y2] && convert[dice2.d[0]] == c[x2][y2]) {
          num2++;
        } else {
          continue;
        }
      }
      if (mp[num][x2][y2].empty() || mp[num2][x2][y2].count(dice2.get()) == 0) {
        if (num2 == 6) {
          printf("%d\n", mp[num][x][y][dice.get()] + 1);
          return;
        }
        mp[num2][x2][y2][dice2.get()] = mp[num][x][y][dice.get()] + 1;
        que.push(R(Q(num2, P(x2, y2)), dice2));
      }
    }
  }
  printf("unreachable\n");
}

int main() {
  while (scanf("%d%d", &w, &d), w) {
    for (int i = 0; i < d; i++) scanf("%s", c[i]);
    scanf("%s", v);
    solve();
  }
}
accuracy: 1
time_ms: 170
memory_kb: 6048
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define reps(i, s, n) for(ll i = (s); i < n; ++i)
#define rep(i, n) reps(i, 0, n)
#define ALL(v) v.begin(), v.end()

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

int W, H;

const int base = 6;
struct Dice{
    int ii, jj, nxtord;
    int l, r, u, d, f, b;
    vector<int*> val;

    void init(){
        val[0]=&l; val[1]=&r;
        val[2]=&u; val[3]=&d;
        val[4]=&f; val[5]=&b;
    }

    Dice(vector<int> v) : val(6), ii(-1), jj(-1), nxtord(0){
        init();
        rep(i, 6) {
            *val[i] = v[i];
        }
    }

    Dice(const Dice &dice) : val(6), ii(dice.ii), jj(dice.jj), nxtord(dice.nxtord){
        init();
        rep(i, 6) {
            *val[i] = *(dice.val[i]);
        }
    }

    bool operator<(const Dice &dice) const{
        rep(i, 6){
            if(*val[i] < *(dice.val[i])) return true;
            if(*val[i] > *(dice.val[i])) return false;
        }
        return false;
    }

    void RollN(){
        int temp = u;
        u = f; f = d; d = b; b = temp;
    }

    void RollE(){
        int temp = u;
        u = l; l = d; d = r; r = temp;
    }

    void RollS(){RollN(); RollN(); RollN(); }
    void RollW(){RollE(); RollE(); RollE(); }
    //void RollL(){RollN(); RollE(); RollS();}
    //void RollR(){RollS(); RollE(); RollN();}

    bool roll(int i){
        if(i == 0){ --ii; RollN();}
        else if(i == 1) {++jj; RollE();}
        else if(i == 2) {++ii; RollN(); RollN(); RollN(); }
        else if(i == 3) {--jj; RollE(); RollE(); RollE(); }

        if(ii>=0 && ii<H && jj>=0 && jj<W) return true;
        return false;
    }

    void print(){
        cout<<ii<<' '<<jj<<' '<<nxtord<<endl;
        cout<<l<<' '<<r<<' '<<u<<' '<<d<<' '<<f<<' '<<b<<endl;
        rep(i, 6) cout<<*val[i]<<" \n"[i == 5];
    }

};

template<class T, class U> bool chmin(T &a, const U &b){
    if(a > b) {a = b; return true;}
    else return false;
}

void solve(){
    string S;
    vector<string> G(H);
    map<char, int> ord;
    map<Dice, int> dist[30][30][7];
    using P = pair<int, Dice>;
    queue<P> que;

    rep(i, H) cin>>G[i];
    cin>>S;
    rep(i, 6) ord[S[i]] = i;
    Dice dice({ord['y'], ord['b'], ord['r'], ord['c'], ord['m'], ord['g']});
    mat g(H, vec(W, 10));
    rep(i, H) rep(j, W){
        char c = G[i][j];
        if(c=='#'){
            dice.ii = i; dice.jj = j;
        }else if(c == 'k'){
            g[i][j] = -1;
        }else if(c != 'w'){
            g[i][j] = ord[G[i][j]];
        }
    }

    dist[dice.ii][dice.jj][0][dice] = -(1<<30);
    que.emplace(-(1<<30), dice);
    while(!que.empty()){
        P p = que.front(); que.pop();
        Dice now = p.second;
        if(dist[now.ii][now.jj][now.nxtord][now] < p.first) continue;
        if(now.nxtord == 6) {
            cout<<p.first + (1<<30)<<endl;
            return;
        }
        rep(k, 4){
            Dice nxt(now);
            if(nxt.roll(k)){
                if(g[nxt.ii][nxt.jj] == 10 && chmin(dist[nxt.ii][nxt.jj][nxt.nxtord][nxt], p.first + 1)){
                    que.emplace(p.first + 1, nxt);
                }else if(g[nxt.ii][nxt.jj] == nxt.nxtord && nxt.u == nxt.nxtord){
                    ++nxt.nxtord;
                    if(chmin(dist[nxt.ii][nxt.jj][nxt.nxtord][nxt], p.first + 1)) que.emplace(p.first + 1, nxt);
                }
            }
        }
    }

    cout<<"unreachable"<<endl;
}

int main(){
    while(cin>>W>>H, W){
        solve();
    }
}
accuracy: 1
time_ms: 400
memory_kb: 14820
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define reps(i, s, n) for(ll i = (s); i < n; ++i)
#define rep(i, n) reps(i, 0, n)
#define ALL(v) v.begin(), v.end()

#define fi first
#define se second

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

const int base = 6;
struct Dice{
    int l, r, u, d, f, b;
    vector<int*> val;
    static map<int, int> hash_to_id;
    static vector<int> id_to_hash;
    Dice(vector<int> v) : val(6){
        val[0]=&l; val[1]=&r;
        val[2]=&u; val[3]=&d;
        val[4]=&f; val[5]=&b;
        rep(i, 6) *val[i] = v[i];
    }

    Dice(int id) : val(6){
        val[0]=&l; val[1]=&r;
        val[2]=&u; val[3]=&d;
        val[4]=&f; val[5]=&b;
        int hash = id_to_hash[id];
        rep(i, 6) {
            *val[5 - i] = hash % base;
            hash /= base;
        }
    }

    static void set_hash(vector<int*> v){
        hash_to_id.clear();
        id_to_hash.clear();
        vector<int> ord(6);
        iota(ALL(ord), 0);
        int id(0);
        do{
            int hash(0);
            rep(i, 6) (hash *= base) += *v[ord[i]];
            id_to_hash.push_back(hash);
            hash_to_id[hash] = id++;
        }while(next_permutation(ALL(ord)));
    }

    void RollN(){
        int temp = u;
        u = f; f = d; d = b; b = temp;
    }

    void RollE(){
        int temp = u;
        u = l; l = d; d = r; r = temp;
    }

    void RollS(){RollN(); RollN(); RollN(); }
    void RollW(){RollE(); RollE(); RollE(); }
    //void RollL(){RollN(); RollE(); RollS();}
    //void RollR(){RollS(); RollE(); RollN();}

    void roll(int i, int j){
        if(i == 0){
            if(j == 1) RollE();
            else RollW();
        }else{
            if(i == 1) RollS();
            else RollN();
        }
    }

    int id(){
        int hash(0);
        rep(i, 6) (hash *= base) += *val[i];
        if(id_to_hash[hash_to_id[hash]] != hash){
            cout<<hash<<' '<<hash_to_id[hash]<<' '<<id_to_hash[hash_to_id[hash]]<<endl;
            exit(0);
        }
        return hash_to_id[hash];
    }

    void print(){
        //cout<<"Dice state\n";
        cout<<l<<' '<<r<<' '<<u<<' '<<d<<' '<<f<<' '<<b<<endl;
        /*rep(i, 6) cout<<*val[i]<<" \n"[i == 5];
        cout<<id()<<endl;*/
    }

};

map<int, int> Dice::hash_to_id;
vector<int> Dice::id_to_hash;

int W, H;
int encode(int i, int j, int id){
    return (id * W + j) * H + i;
}

vector<int> decode(int code){
    vector<int> res(3);
    res[0] = code % H; code /= H;
    res[1] = code % W; code /= W;
    res[2] = code;
    return res;
}

template<class T, class U> bool chmin(T &a, const U &b){
    if(a > b) {a = b; return true;}
    else return false;
}

int main(){
    while(cin>>W>>H, W){
        string S;
        vector<string> G(H);
        rep(i, H) cin>>G[i];
        cin>>S;
        map<char, int> ord;
        rep(i, 6) ord[S[i]] = i;
        Dice dice({ord['y'], ord['b'], ord['r'], ord['c'], ord['m'], ord['g']});
        Dice::set_hash(dice.val);

        mat g(H, vec(W, 10)), dist(H * W * Dice::id_to_hash.size(), vec(7, 1LL<<60));
        int si, sj;
        rep(i, H) rep(j, W){
            if(G[i][j]=='k') {
                g[i][j] = -1;
            }else if(G[i][j] == '#'){
                si = i; sj = j;
            }else if(G[i][j] != 'w'){
                g[i][j] = ord[G[i][j]];
            }
        }

        using P = pair<ll, ll>;
        priority_queue<P, vector<P>, greater<> > pque;
        dist[encode(si, sj, dice.id())][0] = 0;
        pque.emplace(0, encode(si, sj, dice.id()) * 7 + 0);
        vector<int> di = {-1, 0, 1, 0}, dj = {0, -1, 0, 1};
        ll res(1LL<<30);

        vec check(6, 1LL<<30);

        while(!pque.empty()){
            P p = pque.top(); pque.pop();
            vector<int> v = decode(p.se / 7);
            int i = v[0], j = v[1];
            //cout<<v[0]<<' '<<v[1]<<' '<<p.se%7<<' '<<v[2]<<endl;
            if(dist[p.se/7][p.se%7] < p.fi) continue;
            p.se %= 7;
            if(p.se == 6) {chmin(res, p.fi); continue;}
/*
            if(g[i][j]==p.se-1) chmin(check[p.se], p.fi);
            Dice temp(v[2]);
            if(p.se == 1) {
                cout<<p.fi<<' '<<v[0]<<' '<<v[1]<<endl; 
                temp.print();
                Dice test(temp.id());
                test.print();
            }
*/
            rep(k, 4){
                int ni = i + di[k], nj = j + dj[k];
                if(ni>=0 && ni < H && nj >= 0 && nj < W && g[ni][nj] >= 0){
                    Dice nxt_dice(v[2]);
                    nxt_dice.roll(di[k], dj[k]);
                    if(g[ni][nj] == 10 && chmin(dist[encode(ni, nj, nxt_dice.id())][p.se], p.fi + 1)){
                        pque.emplace(p.fi + 1, encode(ni, nj, nxt_dice.id()) * 7 + p.se);
                    }else if(g[ni][nj] == p.se && nxt_dice.u == p.se && chmin(dist[encode(ni, nj, nxt_dice.id())][p.se + 1], p.fi + 1)){
                        pque.emplace(p.fi + 1, encode(ni, nj, nxt_dice.id()) * 7 + p.se + 1);
                    }
                }
            }
        }
        //rep(i, 6) cout<<check[i]<<" \n"[i==5];
        if(res == (1LL<<30)) cout<<"unreachable"<<endl;
        else cout<<res<<endl;
    }
}
accuracy: 1
time_ms: 870
memory_kb: 68964
final_rank: 20

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

struct Node {
	int y, x, dir;
	Node(const int yy, const int xx, const int dd) {
		y = yy, x = xx, dir = dd;
	}
};

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

	string vs = { "rmbygc" };
	vector<vector<int>>dice = { {0,1,2},{0,2,4},{0,4,3},{0,3,1},{1,2,0},{1,0,3},{1,3,5},{1,5,2},{2,0,1},{2,1,5},{2,5,4},{2,4,0},{3,5,1},{3,1,0},{3,0,4},{3,4,5},{4,2,5},{4,5,3},{4,3,0},{4,0,2},{5,4,2},{5,2,1},{5,1,3},{5,3,4} };
	map<vector<int>, int>mp;
	int cnt = 0;
	for (auto i : dice) {
		mp[i] = cnt++;
	}
	int dir[] = { 1,0,-1,0,1 };
	while (cin >> W >> H, H) {
		vector<string>s(H);
		vector<vector<vector<int>>>dis(H, vector<vector<int>>(W, vector<int>(24, MOD)));
		int sy, sx;
		for (auto &i : s)cin >> i;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				if (s[i][j] == '#') {
					sy = i, sx = j;
				}
			}
		}
		string t;
		cin >> t;
		dis[sy][sx][0] = 0;
		queue<Node>Q;
		Q.push(Node(sy, sx, 0));
		int ans = MOD;
		for (auto i : t) {
			while (!Q.empty()) {
				auto node = Q.front();
				Q.pop();
				for (int j = 0; j < 4; j++) {
					int ny = node.y + dir[j];
					int nx = node.x + dir[j + 1];
					if (ny < 0 || nx < 0 || ny >= H || nx >= W)continue;
					if (s[ny][nx] != i && s[ny][nx] != 'w'&&s[ny][nx]!='#')continue;
					auto ndir = dice[node.dir];
					auto nxdir = ndir;
					if (j == 0) {
						ndir[0] = 5 - nxdir[1];
						ndir[1] = nxdir[0];
					}
					if (j == 1) {
						ndir[0] = nxdir[2];
						ndir[2] = 5 -nxdir[0];
					}
					if (j == 2) {
						ndir[0] = nxdir[1];
						ndir[1] = 5 - nxdir[0];
					}
					if (j == 3) {
						ndir[0] = 5 - nxdir[2];
						ndir[2] = nxdir[0];
					}
					if (s[ny][nx] != 'w'&&s[ny][nx]!='#'&&vs[ndir[0]] != s[ny][nx])continue;
					auto nndir = mp[ndir];
					if (dis[ny][nx][nndir] > dis[node.y][node.x][node.dir] + 1) {
						dis[ny][nx][nndir] = dis[node.y][node.x][node.dir] + 1;
						Q.push(Node(ny, nx, nndir));
					}
				}
			}
			int ny, nx;
			for (int j = 0; j < H; j++) {
				for (int k = 0; k < W; k++) {
					if (s[j][k] == i) {
						ny = j, nx = k;
					}
				}
			}
			auto ndis = dis;
			for (auto &j : ndis)for (auto &k : j)for (auto &l : k)l = MOD;
			ans = MOD;
			for (int j = 0; j < 24; j++) {
				ndis[ny][nx][j] = dis[ny][nx][j];
				ans = min(ans, dis[ny][nx][j]);
				Q.push(Node(ny, nx, j));
			}
		//	cout << ans << endl;
			dis = ndis;
		}
		if (ans == MOD) {
			cout << "unreachable" << endl;
		}
		else {
			cout << ans << endl;
		}
	}
}
accuracy: 1
time_ms: 280
memory_kb: 3432
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
vector<int> dy = {1, 0, -1, 0};
vector<int> dx = {0, 1, 0, -1};
vector<vector<int>> r = {{2, 3, 1, 0, 4, 5}, {5, 4, 2, 3, 0, 1}, {3, 2, 0, 1, 4, 5}, {4, 5, 2, 3, 1, 0}};
int main(){
  while (1){
    int w, d;
    cin >> w >> d;
    if (w == 0 && d == 0){
      break;
    }
    vector<vector<char>> c(d + 2, vector<char>(w + 2, 'k'));
    for (int i = 1; i <= d; i++){
      for (int j = 1; j <= w; j++){
        cin >> c[i][j];
      }
    }
    string s;
    cin >> s;
    int sy, sx;
    for (int i = 1; i <= d; i++){
      for (int j = 1; j <= w; j++){
        if (c[i][j] == '#'){
          sy = i;
          sx = j;
        }
      }
    }
    c[sy][sx] = 'w';
    tuple<array<char, 6>, int, int, int> T = make_tuple(array<char, 6>{'r', 'c', 'g', 'm', 'b', 'y'}, sy, sx, 0);
    set<tuple<array<char, 6>, int, int, int>> st;
    queue<pair<int, tuple<array<char, 6>, int, int, int>>> Q;
    st.insert(T);
    Q.push(make_pair(0, T));
    int ans = -1;
    while (!Q.empty()){
      int t = Q.front().first;
      array<char, 6> f = get<0>(Q.front().second);
      int y = get<1>(Q.front().second);
      int x = get<2>(Q.front().second);
      int p = get<3>(Q.front().second);
      Q.pop();
      if (p == 6){
        ans = t;
        break;
      }
      for (int i = 0; i < 4; i++){
        int y2 = y + dy[i];
        int x2 = x + dx[i];
        if (c[y2][x2] == 'w' || c[y2][x2] == f[r[i][0]] && c[y2][x2] == s[p]){
          array<char, 6> f2;
          for (int j = 0; j < 6; j++){
            f2[j] = f[r[i][j]];
          }
          int p2 = p;
          if (c[y2][x2] == s[p]){
            p2++;
          }
          tuple<array<char, 6>, int, int, int> next = make_tuple(f2, y2, x2, p2);
          if (!st.count(next)){
            st.insert(next);
            Q.push(make_pair(t + 1, next));
          }
        }
      }
    }
    if (ans == -1){
      cout << "unreachable" << endl;
    } else {
      cout << ans << endl;
    }
  }
}
accuracy: 1
time_ms: 830
memory_kb: 7040
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=35,INF=1<<30;

int ri(int u,int f){
    if(u==1){
        if(f==2) return 3;
        if(f==3) return 5;
        if(f==5) return 4;
        if(f==4) return 2;
    }
    if(u==2){
        if(f==1) return 4;
        if(f==4) return 6;
        if(f==6) return 3;
        if(f==3) return 1;
    }
    if(u==3){
        if(f==1) return 2;
        if(f==2) return 6;
        if(f==6) return 5;
        if(f==5) return 1;
    }
    if(u==4){
        if(f==1) return 5;
        if(f==5) return 6;
        if(f==6) return 2;
        if(f==2) return 1;
    }
    if(u==5){
        if(f==1) return 3;
        if(f==3) return 6;
        if(f==6) return 4;
        if(f==4) return 1;
    }
    if(u==6){
        if(f==2) return 4;
        if(f==4) return 5;
        if(f==5) return 3;
        if(f==3) return 2;
    }
    
    return -1000;
}//uとfが与えられた時にrを返す(u==1,f==2,r==3型のサイコロ)

struct dice{
    int u,f,r,b,l,d;
    
    void init(int uu,int ff,int rr,int bb,int ll,int dd){
        u=uu;
        f=ff;
        r=rr;
        b=bb;
        l=ll;
        d=dd;
    }
    
    void init(int uu,int ff){
        u=uu;
        f=ff;
        r=ri(u,f);
        b=7-f;
        l=7-r;
        d=7-u;
    }
    
    void turnF(){
        int save=f;
        f=u;
        u=b;
        b=d;
        d=save;
    }
    
    void turnR(){
        int save=r;
        r=u;
        u=l;
        l=d;
        d=save;
    }
    
    void turnB(){
        int save=b;
        b=u;
        u=f;
        f=d;
        d=save;
    }
    
    void turnL(){
        int save=l;
        l=u;
        u=r;
        r=d;
        d=save;
    }
    
    void turn1(){
        int save=r;
        r=b;
        b=l;
        l=f;
        f=save;
    }//時計回り
    
    void turn2(){
        int save=r;
        r=f;
        f=l;
        l=b;
        b=save;
    }//反時計回り
};

struct dat{
    int wh;
    int h;
    int w;
    int u;
    int f;
};

int H,W;
int sh,sw;
int S[MAX][MAX];
int dis[7][MAX][MAX][7][7];
int jun[7];

void BFS(){
    for(int a=0;a<7;a++) for(int b=0;b<MAX;b++) for(int c=0;c<MAX;c++) for(int d=0;d<7;d++) for(int e=0;e<7;e++) dis[a][b][c][d][e]=INF;
    
    dis[0][sh][sw][1][2]=0;
    queue<dat> Q;
    Q.push({0,sh,sw,1,2});
    
    while(!Q.empty()){
        auto u=Q.front();Q.pop();
        if(u.wh==6) break;
        
        int d=dis[u.wh][u.h][u.w][u.u][u.f];
        
        dice X;
        X.init(u.u,u.f);
        
        int toh,tow;
        
        if(u.h>=1){
            toh=u.h-1;tow=u.w;
            if(S[toh][tow]!=-1){
                X.turnB();
                if(S[toh][tow]==0){
                    if(chmin(dis[u.wh][toh][tow][X.u][X.f],d+1)) Q.push({u.wh,toh,tow,X.u,X.f});
                }
                if(S[toh][tow]==X.u&&jun[u.wh+1]==X.u){
                    if(chmin(dis[u.wh+1][toh][tow][X.u][X.f],d+1)) Q.push({u.wh+1,toh,tow,X.u,X.f});
                }
                X.turnF();
            }
        }
        
        if(u.h+1<H){
            toh=u.h+1;tow=u.w;
            X.turnF();
            if(S[toh][tow]==0){
                if(chmin(dis[u.wh][toh][tow][X.u][X.f],d+1)) Q.push({u.wh,toh,tow,X.u,X.f});
            }
            if(S[toh][tow]==X.u&&jun[u.wh+1]==X.u){
                if(chmin(dis[u.wh+1][toh][tow][X.u][X.f],d+1)) Q.push({u.wh+1,toh,tow,X.u,X.f});
            }
            X.turnB();
        }
        
        if(u.w>=1){
            toh=u.h;tow=u.w-1;
            X.turnL();
            if(S[toh][tow]==0){
                if(chmin(dis[u.wh][toh][tow][X.u][X.f],d+1)) Q.push({u.wh,toh,tow,X.u,X.f});
            }
            if(S[toh][tow]==X.u&&jun[u.wh+1]==X.u){
                if(chmin(dis[u.wh+1][toh][tow][X.u][X.f],d+1)) Q.push({u.wh+1,toh,tow,X.u,X.f});
            }
            X.turnR();
        }
        
        if(u.w+1<W){
            toh=u.h;tow=u.w+1;
            X.turnR();
            if(S[toh][tow]==0){
                if(chmin(dis[u.wh][toh][tow][X.u][X.f],d+1)) Q.push({u.wh,toh,tow,X.u,X.f});
            }
            if(S[toh][tow]==X.u&&jun[u.wh+1]==X.u){
                if(chmin(dis[u.wh+1][toh][tow][X.u][X.f],d+1)) Q.push({u.wh+1,toh,tow,X.u,X.f});
            }
            X.turnL();
        }
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    map<char,int> MA;
    MA['r']=1;
    MA['m']=2;
    MA['b']=3;
    MA['y']=4;
    MA['g']=5;
    MA['c']=6;
    MA['#']=0;
    MA['w']=0;
    MA['k']=-1;
    
    while(1){
        cin>>W>>H;
        if(H==0) break;
        memset(S,-1,sizeof(S));
        for(int i=0;i<H;i++){
            for(int j=0;j<W;j++){
                char c;cin>>c;
                S[i][j]=MA[c];
                if(c=='#'){
                    sh=i;
                    sw=j;
                }
            }
        }
        string T;cin>>T;
        for(int i=0;i<6;i++) jun[i+1]=MA[T[i]];
        
        BFS();
        
        int ans=INF;
        
        for(int i=0;i<H;i++){
            for(int j=0;j<W;j++){
                if(S[i][j]==jun[6]){
                    for(int a=1;a<=6;a++){
                        for(int b=1;b<=6;b++){
                            chmin(ans,dis[6][i][j][a][b]);
                        }
                    }
                }
            }
        }
        
        if(ans==INF) cout<<"unreachable\n";
        else cout<<ans<<endl;
    }
}
accuracy: 1
time_ms: 40
memory_kb: 4892
final_rank: 2