#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
using namespace std;

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

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
template <class T>
class Dice {
public:
  Dice() {
    id[TOP] = 0; id[FRONT] = 3; id[LEFT] = 2;
    id[RIGHT] = 4; id[BACK] = 1; id[BOTTOM] = 5;
  }
  T& operator[] (FACE f) { return id[f]; }
  const T& operator[] (FACE f) const { return 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];
  }

  bool operator<(const Dice<T>& b) const {
	  const Dice<T> &a = *this;

	  if(a[TOP] != b[TOP]) return a[TOP] < b[TOP];
	  if(a[BOTTOM] != b[BOTTOM]) return a[BOTTOM] < b[BOTTOM];
	  if(a[FRONT] != b[FRONT]) return a[FRONT] < b[FRONT];
	  if(a[BACK] != b[BACK]) return a[BACK] < b[BACK];
	  if(a[LEFT] != b[LEFT]) return a[LEFT] < b[LEFT];

	  return 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); }


  void roll_L() { roll(TOP, RIGHT, BOTTOM, LEFT); }
  void roll_R() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_T() { roll(TOP, FRONT, BOTTOM, BACK); }
  void roll_B() { roll(TOP, BACK, BOTTOM, FRONT); }

  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];
};

class State
{
public:
	int x,y,p;
	Dice<int> d;

	State(int x, int y, Dice<int> d, int p = 1)
		:x(x),y(y),d(d),p(p)
	{}

	bool operator<(const State& s) const
	{
		if(x != s.x) return x < s.x;
		if(y != s.y) return y < s.y;
		if(p != s.p) return p < s.p;

		return d < s.d;
	}
};

int W,H;
int xs,ys,xd,yd;

string field[12], alpha[6];
bool reached[12][12][6][6][2];

int dir(char c)
{
	if(c == '+') return 1 + 2 + 4 + 8;
	if(c == '|') return     2 +     8;
	if(c == '-') return 1 +     4    ;
	if(c == '<') return 1            ;
	if(c == '>') return         4    ;
	if(c == '^') return     2        ;
	if(c == 'v') return		        8;

	return 0;
}

void bfs(int sx, int sy, int p)
{
	queue<State> q;
	if(p == 0) {
		q.push(State(sx, sy, Dice<int>()));
	}
	else {
		Dice<int> d;
		vector<Dice<int> > a = d.all_rolls();
		for(int i=0; i<a.size(); i++) {
			q.push(State(sx, sy, a[i]));
		}
	}


	while(!q.empty()) {
		State s=q.front(); q.pop();
		if(reached[s.x][s.y][s.d[TOP]][s.d[LEFT]][p]) continue;
		reached[s.x][s.y][s.d[TOP]][s.d[LEFT]][p] = 1;


		
		for(int i=0; i<4; i++) {
			int tx = s.x + dx[i];
			int ty = s.y + dy[i];

			if(tx < 0 || ty < 0 || tx >= W || ty >= H) continue;

			if(p == 0) {
				int d = dir(field[s.y][s.x]);
				if(! (d >> i & 1) ) continue;
			}
			else {
				int d = dir(field[ty][tx]);
				if(! (d >> (i+2)%4 & 1 ) ) continue;
			}

			Dice<int> td = s.d;
			if(i == 0) td.roll_L();
			if(i == 1) td.roll_T();
			if(i == 2) td.roll_R();
			if(i == 3) td.roll_B();

			if(reached[tx][ty][td[TOP]][td[LEFT]][p]) continue;

			q.push(State(tx, ty, td));

		}
	}
}

string solve()
{
	string res;
	res += alpha[0][0];
	set<State> dice;

	dice.insert(State(xs, ys, Dice<int>(), 1));

	while(1) {
		//最小となる次の状態を見つける
		set<State>::iterator it = dice.begin();
		set<State> next;
		char minc = '_';

		if(res.size() > W*H*12*24) {
			res = "infinite";
			break;
		}

		bool goal = false;

		for(; it != dice.end(); it++) {
			State s = *it;

			if(s.x == xd && s.y == yd && alpha[s.d[TOP]].size() == s.p) goal = true;

			if(alpha[s.d[TOP]].size() > s.p) {
				char c = alpha[s.d[TOP]][s.p];
				if(minc > c) {
					minc = c;
					next.clear();
					next.insert(State(s.x, s.y, s.d, s.p + 1));
				}
				else if(minc == c) {
					next.insert(State(s.x, s.y, s.d, s.p + 1));
				}
			}
			else {
				int d = dir(field[s.y][s.x]);
				for(int i=0; i<4; i++) {
					if(! (d >> i & 1) ) continue;

					int tx = s.x + dx[i];
					int ty = s.y + dy[i];

					if(tx < 0 || ty < 0 || tx >= W || ty >= H) continue;

					Dice<int> td = s.d;
					if(i == 0) td.roll_L();
					if(i == 1) td.roll_T();
					if(i == 2) td.roll_R();
					if(i == 3) td.roll_B();

					if(reached[tx][ty][td[TOP]][td[LEFT]][0] &&
					   reached[tx][ty][td[TOP]][td[LEFT]][1]) {
						   char c = alpha[td[TOP]][0];
						   if(minc > c) {
							   minc = c;
							   next.clear();
							   next.insert(State(tx,ty,td, 1));
						   }
						   else if(minc == c) {
							   next.insert(State(tx,ty,td, 1));
						   }
					}
				}
			}
		}

		if(goal) {
			break;
		}

		if(next.empty()) {
			res = "no";
			break;
		}

		res += minc;
		swap(dice, next);
		
	}

	return res;
}

int main()
{
	cin >> H >> W;
	for(int i=0; i<H; i++)
		cin >> field[i];

	for(int i=0; i<6; i++)
		cin >> alpha[i];

	cin >> ys >> xs;
	cin >> yd >> xd;

	xs--; ys--;
	xd--; yd--;

	memset(reached, 0, sizeof(reached));
	bfs(xs, ys, 0);
	bfs(xd, yd, 1);

	cout << solve() << endl;
}

Measured memory_bytes: 4836