#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2>
ostream &operator<<(ostream &o, const pair<T1, T2> &p) {
  return o << '(' << p.first << ", " << p.second << ')';
}
template <typename I>
ostream &print(ostream &o, I s, I e, int w = 5, int prec = 2,
               const string &sep = ", ", const string &lhs = "",
               const string &rhs = "") {
  o << lhs;
  if (s != e) o << setw(w) << setprecision(prec) << *(s++);
  for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
  return o << rhs;
}
template <typename T,
          template <typename E, typename A = std::allocator<E>> class C>
ostream &operator<<(ostream &o, const C<T> &c) {
  return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");
}
template <typename T, template <typename E, typename Compare = less<E>,
                                typename Alloc = allocator<E>>
                      class C>
ostream &operator<<(ostream &o, const C<T> &c) {
  return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");
}
template <typename K, typename T,
          template <typename E1, typename E2, typename Compare = std::less<E1>,
                    class Allocator = std::allocator<std::pair<const E1, E2>>>
          class C>
ostream &operator<<(ostream &o, const C<K, T> &c) {
  return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");
}
const int oo = numeric_limits<int>::max();
const int MAX_N = 1010;
int Maze[MAX_N][MAX_N];
enum Side {
  TOP = 1 << 0,
  RIGHT = 1 << 1,
  BOTTOM = 1 << 2,
  LEFT = 1 << 3,
};
int Dist[4][MAX_N][MAX_N];
void print(int p) {
  cout << !!(p & LEFT) << !!(p & BOTTOM) << !!(p & RIGHT) << !!(p & TOP)
       << '\n';
}
int rotate(int p, int w) {
  w = w % 4;
  return (p & ((1 << (4 - w)) - 1)) << w | (p >> (4 - w));
}
int main() {
  ios_base::sync_with_stdio(false), cin.tie(0);
  int W, H;
  cin >> H >> W;
  for (int t = 0; t < 4; t += 1) {
    for (int i = 0; i < MAX_N; i += 1) {
      for (int j = 0; j < MAX_N; j += 1) Dist[t][i][j] = +oo;
    }
  }
  cin.ignore();
  for (int i = 0; i < H; i += 1) {
    for (int j = 0; j < W; j += 1) {
      char ch;
      cin >> ch;
      switch (ch) {
        case '+':
          Maze[i][j] = TOP | RIGHT | BOTTOM | LEFT;
          break;
        case '-':
          Maze[i][j] = RIGHT | LEFT;
          break;
        case '|':
          Maze[i][j] = TOP | BOTTOM;
          break;
        case '^':
          Maze[i][j] = TOP;
          break;
        case '>':
          Maze[i][j] = RIGHT;
          break;
        case '<':
          Maze[i][j] = LEFT;
          break;
        case 'v':
          Maze[i][j] = BOTTOM;
          break;
        case 'L':
          Maze[i][j] = TOP | RIGHT | BOTTOM;
          break;
        case 'R':
          Maze[i][j] = TOP | BOTTOM | LEFT;
          break;
        case 'U':
          Maze[i][j] = RIGHT | BOTTOM | LEFT;
          break;
        case 'D':
          Maze[i][j] = TOP | RIGHT | LEFT;
          break;
        case '*':
          Maze[i][j] = 0;
          break;
        default:
          exit(1);
      }
    }
  }
  pair<int, int> start, end;
  cin >> start.first >> start.second;
  start.second -= 1, start.first -= 1;
  cin >> end.first >> end.second;
  end.second -= 1, end.first -= 1;
  priority_queue<pair<pair<int, int>, pair<int, int>>> q;
  q.push({{-0, 0}, start});
  Dist[0][start.first][start.second] = 0;
  while (!q.empty()) {
    pair<pair<int, int>, pair<int, int>> cur = q.top();
    q.pop();
    const int cost = cur.first.first *= -1;
    const int time = cur.first.second;
    const pair<int, int> pos = cur.second;
    if (Dist[time][pos.first][pos.second] < cost) continue;
    for (int wait = 0; wait <= 3; wait += 1) {
      static const vector<pair<int, int>> moves = {
          {TOP, BOTTOM}, {BOTTOM, TOP}, {LEFT, RIGHT}, {RIGHT, LEFT}};
      const int next_time = (wait + time) % 4;
      for (pair<int, int> dir : moves) {
        pair<int, int> move;
        switch (dir.first) {
          case TOP:
            switch (next_time) {
              case 0:
                move = {-1, 0};
                break;
              case 1:
                move = {0, 1};
                break;
              case 2:
                move = {1, 0};
                break;
              case 3:
                move = {0, -1};
                break;
              default:
                exit(1);
            }
            break;
          case BOTTOM:
            switch (next_time) {
              case 0:
                move = {1, 0};
                break;
              case 1:
                move = {0, -1};
                break;
              case 2:
                move = {-1, 0};
                break;
              case 3:
                move = {0, 1};
                break;
              default:
                exit(1);
            }
            break;
          case LEFT:
            switch (next_time) {
              case 0:
                move = {0, -1};
                break;
              case 1:
                move = {-1, 0};
                break;
              case 2:
                move = {0, 1};
                break;
              case 3:
                move = {1, 0};
                break;
              default:
                exit(1);
            }
            break;
          case RIGHT:
            switch (next_time) {
              case 0:
                move = {0, 1};
                break;
              case 1:
                move = {1, 0};
                break;
              case 2:
                move = {0, -1};
                break;
              case 3:
                move = {-1, 0};
                break;
              default:
                exit(1);
            }
            break;
          default:
            exit(1);
        }
        const pair<int, int> next_pos = {pos.first + move.first,
                                         pos.second + move.second};
        if (next_pos.first < 0 || next_pos.first >= H) continue;
        if (next_pos.second < 0 || next_pos.second >= W) continue;
        if (!(Maze[pos.first][pos.second] & dir.first)) continue;
        if (!(Maze[next_pos.first][next_pos.second] & dir.second)) continue;
        const int next_cost = cost + wait + 1;
        if (Dist[next_time][next_pos.first][next_pos.second] <= next_cost)
          continue;
        Dist[next_time][next_pos.first][next_pos.second] = next_cost;
        q.push({{-next_cost, next_time}, next_pos});
      }
    }
  }
  int r = +oo;
  for (int i = 0; i <= 3; i += 1) {
    r = min(r, Dist[i][end.first][end.second]);
  }
  cout << (r == +oo ? -1 : r) << '\n';
  return 0;
}
