/*
 * Mysterious Dungeons
 * http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2089
 */

 #include <bits/stdc++.h>

using namespace std;

#define LOG(...) fprintf(stderr, __VA_ARGS__)
//#define LOG(...)
#define FOR(i, a, b) for(int i = (int)(a); i < (int)(b); ++i)
#define REP(i, n) for(int i = 0; i < (int)(n); ++i)
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort(ALL(c))
#define RSORT(c) sort(RALL(c))
#define SQ(n) (n) * (n)

typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

char field[30][30];

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


struct P {
  int x, y, cost;
  long c;
};

int main() {
  int w, h;
  while(cin >> w >> h, w | h) {
    vector<vector<set<long>>> G(h, vector<set<long>>(w));
    // map<char, int> id;
    fill_n((char*)field, 30 * 30, '#');
    int sx, sy;
    int gx, gy;
    REP(y, h){
      REP(x, w){
        cin >> field[y][x];
        switch (field[y][x]) {
        case '<':
          gx = x;
          gy = y;
          break;
        case '@':
          sx = x;
          sy = y;
          break;
        case '.':
        case '#':
          break;
        default:
          // {
          //   char c = tolower(field[y][x]);
          //   if (!EXIST(id, c)) {
          //     id[c] = id.size();
          //   }
          // }
          break;
        }
      }
    }

    queue<P> que;
    G[sy][sx].insert(0);
    que.push({sx, sy, 0, 0});
    int res = -1;
    while(!que.empty()) {
      P p = que.front(); que.pop();
      // LOG("%d %d %d %d\n", p.x, p.y, p.c, p.cost);
      if (p.x == gx && p.y == gy) {
        res = p.cost;
        break;
      }

      REP(i, 4){
        int nx = p.x + dx[i];
        int ny = p.y + dy[i];
        int ncost = p.cost + 1;
        long nc = p.c;
        if (field[ny][nx] == '#') continue;
        if (islower(field[ny][nx])) {
          nc ^= 1 << (field[ny][nx] - 'a');
        } else if (isupper(field[ny][nx])) {
          if(!(nc & (1 << (field[ny][nx] - 'A')))) continue;
        }
        if (!EXIST(G[ny][nx], nc)) {
          G[ny][nx].insert(nc);
          que.push({nx, ny, ncost, nc});
        }
      }
    }

    cout << res << endl;
  }
}