#include<iostream>
#include<queue>
#include<deque>
#include<vector>
#include<algorithm>
#include<cassert>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define MAX 40

using namespace std;

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
template <class T>
class dice {
public:
  dice() {
    id[TOP] = 0; id[FRONT] = 1; id[LEFT] = 2;
    id[RIGHT] = 3; id[BACK] = 4; id[BOTTOM] = 5;
  }
  T& operator[] (FACE f) { return var[id[f]]; }
  const T& operator[] (FACE f) const { return var[id[f]]; }
  bool operator==(const dice<T>& b) const {
    const dice<T> &a = *this;
    return a[TOP] == b[TOP] && a[BOTTOM] == b[BOTTOM] &&
      a[FRONT] == b[FRONT] && a[BACK] == b[BACK] &&
      a[LEFT] == b[LEFT] && a[RIGHT] == b[RIGHT];
  }
  void roll_x() { roll(TOP, BACK, BOTTOM, FRONT); }
  void roll_y() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_z() { roll(FRONT, RIGHT, BACK, LEFT); }
  vector<dice> all_rolls() {
    vector<dice> ret;
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }
  bool equivalent_to(const dice& di) {
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        if (*this == di) return true;
    return false;
  }
private:
  void roll(FACE a, FACE b, FACE c, FACE d) {
    T tmp = id[a];
    id[a] = id[b]; id[b] = id[c];
    id[c] = id[d]; id[d] = tmp;
  }
  T var[6];
  int id[6];
};

struct P
{
  int x,y;
  P(int x=inf,int y=inf):x(x),y(y){}
};



FACE face[] = {TOP,BOTTOM,FRONT,BACK,LEFT,RIGHT};
string output[]= {"TOP","BOTTOM","FRONT","BAXK","LEFT","RIGHT"};
int value[] = {  1,     6,    2,   5,   3,    4};
char COLOR[] = {'r','c','m','g','y','b'};
int W,H;
char G[MAX][MAX];
bool used[6][MAX][MAX][6][6];
int mincost[6];
vector<P> colors;
string perm;
P Index[200];
int number[200];
int dx[] = {0,-1,0,1};
int dy[] = {+1,0,-1,0};
int ANS;
bool OK;
bool added[6];

struct Pox
{
  int depth,x,y,cost;
  dice<char> die;
  Pox(int depth=inf,int x=inf,int y=inf,int cost=inf):depth(depth),x(x),y(y),cost(cost){}
  bool operator < (const Pox& a)const
  {
    if(depth != a.depth)
      return depth > a.depth;
    if(cost != a.cost)
      return cost > a.cost;
    if(x != a.x)
      return x > a.x;
    return y > a.y;
  }
};



void compute(int sx,int sy)
{

  dice<char> ini;
  rep(i,6)rep(j,MAX)rep(k,MAX)rep(l,6)rep(x,6)used[i][j][k][l][x] = false;

  rep(i,6)ini[face[i]] = COLOR[i];
  used[0][sy][sx][number[ini[TOP]]][number[ini[FRONT]]] = true;

  priority_queue<Pox> deq;  
  Pox poxas7 = Pox(0,sx,sy,0);
  poxas7.die = ini;
  deq.push(poxas7);

  while(!deq.empty())
    {
      Pox pox = deq.top(); deq.pop();

      if(pox.depth+1 >= 7)break;
      char cur = (pox.depth==0?'#':perm[pox.depth-1]);
      char next = perm[pox.depth];

      //cout << pox.depth << " (" << pox.x << "," << pox.y << ") cost : " << pox.cost << " TOP : " << pox.die[TOP] << " G : " << G[pox.y][pox.x] << " cur " << cur << "next " << next<< endl;  

      if(G[pox.y][pox.x] == next && pox.die[TOP] == next)
	{

	  //assert(mincost[number[next]] != inf && mincost[number[next]] > pox.cost);
	  //if(mincost[number[next]] < pox.cost)continue;
	  //cout << mincost[number[next]] << "-------------------------- add " << pox.cost << endl;
	  mincost[number[next]] = pox.cost;
	  if(pox.depth >= 5)
	    {
	      OK = true;
	      cout << pox.cost << endl;
	      return;
	    }
	  else
	    {
	      pox.depth++;
	      deq.push(pox);
	      continue;
	    }
	}
      /*
      rep(i,4)
	{
	  int nx = pox.x + dx[i];
	  int ny = pox.y + dy[i];
	  if(!(0 <= nx && nx < W && 0 <= ny && ny < H))continue;
	  if(G[ny][nx] == 'k')continue;
	  if(G[ny][nx] != 'w' && G[ny][nx] != next)continue;

	  dice<char> die = pox.die;
	  if(i == 0)die.roll_x();
	  if(i == 1)rep(j,3)die.roll_y();
	  if(i == 2)rep(j,3)die.roll_x();
	  if(i == 3)die.roll_y();

	  if(G[ny][nx] != 'w' && next != die[TOP])continue;
	  if(used[pox.depth][ny][nx][number[die[TOP]]][number[die[FRONT]]])continue;

	  used[pox.depth][ny][nx][number[die[TOP]]][number[die[FRONT]]] = true;
	  poxas7 = Pox(pox.depth,nx,ny,pox.cost+1);
	  poxas7.die = die;
	  deq.push(poxas7);

	}
      */
      rep(i,4)
	{
	  int nx = pox.x + dx[i];
	  int ny = pox.y + dy[i];
	  dice<char> die = pox.die;
	  if(!( 0 <= nx && nx < W && 0 <= ny && ny < H ))continue;
	  if(G[ny][nx] == 'k')continue;
	  if(G[ny][nx] != 'w' && G[ny][nx] != next)continue;
 
	  if(i == 0)die.roll_x();
	  if(i == 1)rep(j,3)die.roll_y();
	  if(i == 2)rep(j,3)die.roll_x();
	  if(i == 3)die.roll_y();
 
	  if(used[pox.depth][ny][nx][number[die[TOP]]][number[die[FRONT]]] )continue;
	  if(G[ny][nx] != 'w')if(G[ny][nx] != die[TOP])continue;
       
	  used[pox.depth][ny][nx][number[die[TOP]]][number[die[FRONT]]] = true;
	  poxas7 = Pox(pox.depth,nx,ny,pox.cost+1);
	  poxas7.die = die;
	  deq.push(poxas7);
 
 
	}
 
    }

}


int main()
{
  rep(i,6)number[COLOR[i]] = i;
  while(cin >> W >> H,W|H)
    {

      colors.clear();
      colors.resize(6);
      int sx,sy;
      rep(i,H)rep(j,W)
	{
	  cin >> G[i][j];
	  if(G[i][j]=='#')sx = j,sy = i,G[i][j] = 'w';
	  if(G[i][j]=='r')Index['r'] = P(j,i);
	  if(G[i][j]=='c')Index['c'] = P(j,i);
	  if(G[i][j]=='g')Index['g'] = P(j,i);
	  if(G[i][j]=='m')Index['m'] = P(j,i);
	  if(G[i][j]=='b')Index['b'] = P(j,i);
	  if(G[i][j]=='y')Index['y'] = P(j,i);
	}

      cin >> perm;
      ANS = 0;
      OK = false;
      rep(i,6)added[i] = false,mincost[i] = inf;
      compute(sx,sy);
      ANS = 0;
      rep(i,6)ANS+=mincost[i];
      if(!OK)cout << "unreachable"<< endl;
      //if(OK)cout << ANS << endl;
      //else  cout << "unreachable" << endl;
    }
  return 0;
}

Measured memory_bytes: 1640