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

#define DUMP(x) cerr << #x << "=" << x << endl
#define DUMP2(x, y) cerr<<"("<<#x<<", "<<#y<<") = ("<<x<<", "<<y<<")"<< endl
#define BINARY(x) static_cast<bitset<16> >(x)

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,m,n) for (int i=m;i<(int)(n);i++)

#define in_range(x, y, w, h) (0<=(int)(x) && (int)(x)<(int)(w) && 0<=(int)(y) && (int)(y)<(int)(h))
#define ALL(a) (a).begin(),(a).end()

typedef long long ll;
const int INF   = 1e9;
const ll  INFLL = 1e18;
typedef pair<int, int> PII;
int dx[4]={0, -1, 1, 0}, dy[4]={-1, 0, 0, 1};

int R, C;

const int UP    = 0;
const int LEFT  = 1;
const int RIGHT = 2;
const int DOWN  = 3;

struct State {
    int x, y, memory, direction;
    bool operator<(const State &rhs) const 
    {
        if (x == rhs.x) {
           if (y == rhs.y) {
               if (memory == rhs.memory) return direction < rhs.direction;
               else return memory < rhs.memory;
           } else {
               return y < rhs.y;
           }
        } else {
            return x < rhs.x;
        }
    }
    
};

PII move(int x, int y, int dir)
{
    PII res(x + dx[dir], y + dy[dir]);
    res.first = (res.first + C) % C;
    res.second = (res.second + R) % R;
    return res;
}

int increment(int x)
{
    return (x+1)%16;
}

int decrement(int x)
{
    return (x - 1 + 16) % 16;
}

bool solve(vector<string> P)
{
   map<State, bool> vis;
    queue<State> Q;
    Q.push({0, 0, 0, RIGHT});
    vis[State({0, 0, 0, RIGHT})] = true;

    while (Q.size()) {
        State s = Q.front(); Q.pop();
        vector<State> ns;

#ifdef DEBUG
        cerr << s.x << " " << s.y << " " << s.memory << " " << "<^>v"[s.direction] << endl;
#endif

        switch (P[s.y][s.x]) {
            case '<':
                {
                    PII npos = move(s.x, s.y, LEFT);
                    ns.push_back({npos.first, npos.second, s.memory, LEFT});
                }
                break;
            case '>':
                {
                    PII npos = move(s.x, s.y, RIGHT);
                    ns.push_back({npos.first, npos.second, s.memory, RIGHT});
                }
                break;
            case '^':
                {
                    PII npos = move(s.x, s.y, UP);
                    ns.push_back({npos.first, npos.second, s.memory, UP});
                }
                break;
            case 'v':
                {
                    PII npos = move(s.x, s.y, DOWN);
                    ns.push_back({npos.first, npos.second, s.memory, DOWN});
                }
                break;
            case '_':
                {
                    int ndir = (!s.memory ? RIGHT : LEFT);
                    PII npos = move(s.x, s.y, ndir);
                    ns.push_back({npos.first, npos.second, s.memory, ndir});
                }
                break;
            case '|':
                {
                    int ndir = (!s.memory ? DOWN : UP);
                    PII npos = move(s.x, s.y, ndir);
                    ns.push_back({npos.first, npos.second, s.memory, ndir});
                }
                break;
            case '?':
                rep(i, 4) {
                    int ndir = i;
                    PII npos = move(s.x, s.y, ndir);
                    ns.push_back({npos.first, npos.second, s.memory, ndir});
                }
                break;
            case '.':
                {
                    int ndir = s.direction;
                    PII npos = move(s.x, s.y, ndir);
                    ns.push_back({npos.first, npos.second, s.memory, ndir});
                }
                break;
            case '@':
                return true;
            case '+':
                {
                    int nmemory = increment(s.memory);
                    PII npos = move(s.x, s.y, s.direction);
                    ns.push_back({npos.first, npos.second, nmemory, s.direction});
                }
                break;
            case '-':
                {
                    int nmemory = decrement(s.memory);
                    PII npos = move(s.x, s.y, s.direction);
                    ns.push_back({npos.first, npos.second, nmemory, s.direction});
                }
                break;
            default:
                {
                    int nmemory = (P[s.y][s.x] - '0');
                    PII npos = move(s.x, s.y, s.direction);
                    ns.push_back({npos.first, npos.second, nmemory, s.direction});
                }
                break;
        }

        for (State m : ns) {
            if (!vis[m]) {
                vis[m] = true;
                Q.push(m);
            }
        }
    }
    return false;
}

int main()
{
    ios::sync_with_stdio(false);

    cin >> R >> C;
    vector<string> P(R);
    rep(i, R) cin >> P[i];
    cout << (solve(P) ? "YES" : "NO") << endl;
}

Measured memory_bytes: 4852