#include <bits/stdc++.h>
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wunused-macros"
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wsign-compare"
using namespace std;
template <typename T, typename I = typename T::iterator>
void read(T &cnt) {
  for (auto &x : cnt) cin >> x;
}
template <typename S, typename T>
istream &operator>>(istream &in, pair<S, T> &p) {
  return in >> p.first >> p.second;
}
template <typename S, typename T>
ostream &operator<<(ostream &out, const pair<S, T> &p) {
  return out << "{" << p.first << ", " << p.second << "}";
}
template <typename T>
struct show_container {
  const T &container;
  show_container(const T &container_) : container(container_) {}
};
template <typename T>
ostream &operator<<(ostream &o, const show_container<T> &thing) {
  bool first = true;
  o << "{";
  for (const auto &x : thing.container) {
    if (!first) o << ", ";
    first = false;
    o << x;
  }
  o << "}";
  return o;
}
template <typename T>
show_container<T> show(const T &container) {
  return show_container<T>(container);
}
static const bool debug = false;
template <typename T, typename Q, typename S>
bool Bounded(const T &x, const Q &a, const S &b) {
  return a <= x && x <= b;
}
template <typename T>
int sz(const T &x) {
  return x.size();
}
template <typename T, typename Q>
bool mem(const T &s, const Q &x) {
  return s.find(x) != s.end();
}
template <typename T>
void umin(T &x, const T &y) {
  x = min(x, y);
}
template <typename T>
void umax(T &x, const T &y) {
  x = max(x, y);
}
template <typename T>
int sign(const T &x) {
  return x == 0 ? 0 : x > 0 ? 1 : -1;
}
template <typename T>
T square(const T &x) {
  return x * x;
}
struct Pos {
  int r, c, rot;
  Pos(int r = -1, int c = -1, int rot = 0) : r(r), c(c), rot(rot) {}
  bool operator<(Pos p) const { return tie(r, c, rot) < tie(p.r, p.c, p.rot); }
};
bool solve() {
  int N, M;
  cin >> N >> M;
  if (!cin) return false;
  vector<string> S(N);
  read(S);
  pair<int, int> start, end;
  cin >> start >> end;
  --start.first, --start.second, --end.first, --end.second;
  auto okay = [&](Pos p) {
    return Bounded(p.r, 0, N - 1) && Bounded(p.c, 0, M - 1);
  };
  auto rotate = [](int d, int rot) { return (d - rot + 8) % 4; };
  const string doorTypes = "+-|^><vLRUD*";
  const int DR[4] = {0, -1, 0, 1}, DC[4] = {1, 0, -1, 0};
  vector<int> blockDirs[128];
  blockDirs[int('+')] = {0, 1, 2, 3};
  blockDirs[int('-')] = {0, 2};
  blockDirs[int('|')] = {1, 3};
  blockDirs[int('^')] = {1};
  blockDirs[int('>')] = {0};
  blockDirs[int('<')] = {2};
  blockDirs[int('v')] = {3};
  blockDirs[int('L')] = {0, 1, 3};
  blockDirs[int('R')] = {1, 2, 3};
  blockDirs[int('U')] = {0, 2, 3};
  blockDirs[int('D')] = {0, 1, 2};
  blockDirs[int('*')] = {};
  bool oppositeDoor[4][128][4];
  memset(oppositeDoor, 0, sizeof(oppositeDoor));
  for (char from : doorTypes) {
    for (char to : doorTypes) {
      for (int rot = 0; rot < int(4); ++rot) {
        for (int thisDir : blockDirs[int(from)]) {
          oppositeDoor[thisDir][int(to)][rot] = false;
          for (int otherDir : blockDirs[int(to)]) {
            if (rotate(thisDir, rot) == (2 + rotate(otherDir, rot)) % 4) {
              oppositeDoor[thisDir][int(to)][rot] = true;
              break;
            }
          }
        }
      }
    }
  }
  int ans = -1;
  static int dist[1024][1024][4];
  memset(dist, 127, sizeof(dist));
  static bool seen[1024][1024][4];
  memset(seen, 0, sizeof(seen));
  Pos beginPos = {start.first, start.second, 0};
  queue<Pos> q;
  q.push(beginPos);
  dist[beginPos.r][beginPos.c][beginPos.rot] = 0;
  seen[beginPos.r][beginPos.c][beginPos.rot] = true;
  while (!q.empty()) {
    Pos u = q.front();
    q.pop();
    if (u.r == end.first && u.c == end.second) {
      ans = dist[u.r][u.c][u.rot];
      break;
    }
    {
      Pos v = {u.r, u.c, (u.rot + 1) % 4};
      if (!seen[v.r][v.c][v.rot]) {
        seen[v.r][v.c][v.rot] = true;
        dist[v.r][v.c][v.rot] = 1 + dist[u.r][u.c][u.rot];
        q.push(v);
      }
    }
    for (int blockDir : blockDirs[int(S[u.r][u.c])]) {
      int dir = rotate(blockDir, u.rot);
      Pos v = {u.r + DR[dir], u.c + DC[dir], u.rot};
      if (!okay(v)) continue;
      if (!oppositeDoor[blockDir][int(S[v.r][v.c])][u.rot]) continue;
      int delta = 1 + dist[u.r][u.c][u.rot];
      if (!seen[v.r][v.c][v.rot]) {
        seen[v.r][v.c][v.rot] = true;
        dist[v.r][v.c][v.rot] = delta;
        q.push(v);
      }
    }
  }
  cout << ans << endl;
  return true;
}
int main() {
  std::ios::sync_with_stdio(false);
  cin.tie(nullptr);
  solve();
  return 0;
}
