#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
//#define int long long 
#define rep(i,j,k) for(int i=j;i<k;i+=1)
#define rrep(i,j,k) for(int i=n-1;i>=0;i-=1)
#define sorti(v) sort(v.begin(),v.end())
#define sortd(v) sort(v.begin(),v.end(),greater<int>())
#define mm map<int,int>
#define vv vector<int>
#define tmm map<int,map<int,int>>
#define trav(a, x) for(auto& a : x)
#define ff first
#define ss second
#define lb lower_bound
#define ub upper_bound
#define all(v) v.begin(),v.end()
#define pb push_back
#define alot(x,y) memset(x,y,sizeof(x))
#define pii pair<int,int>
#define code ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
const int MOD=1e9+7;
const double pi=acos(-1.0);
//memset(array_name,value_to_be_intialized,sizeof(array_name));
// __builtin_popcount(n) count no of set bit in number n
//next_permutation(s.begin(),s.end());
/*int change(string g){
     int p=10;
     int ans=g[g.length()-1]-'0';
     for(int i=g.length()-2;i>=0;i--){
         int j=g[i]-'0';
         ans=p*ans+j;
     }
     return ans;
}
int binpow(int a,int b){
    int res=1;
    while(b>0){
        if(b&1)res*=a;
        a*=a;
        b>>=1;
        
    }
    return res;
}
// lower_bound==> if the element is present it return its first occurence else 1st element which is greater than 
// upper_bound==> it will always return iterator to element which is greater than searched element
*/
vector<pii>v[1000];
char c[2002][2002];
int dis[2002][2002];
bool vis[2002][2002];
bool g[2002];
int n,m;
bool check(int i,int j){
    if(i<n && i>=0 && j<m && j>=0)return true;
    return false;
}
int32_t main ()
{
     code;
    int tt;
    //cin>>tt;
    tt=1;
    while(tt--){
        int x,y;
        cin>>n>>m;
        int rx,ry;
        rep(i,0,n){
            rep(j,0,m){
                cin>>c[i][j];
                if(c[i][j]=='S'){
                    x=i;
                    y=j;
                }
                else if(c[i][j]=='G'){
                    rx=i;
                    ry=j;
                }
                else if(c[i][j]!='#' && c[i][j]!='.'){
                    v[c[i][j]-'a'].pb(make_pair(i,j));
                }
            }
        }
        queue<pii>q;
        q.push(make_pair(x,y));
        alot(vis,false);
        alot(g,false);
        while(!q.empty()){
            pii x=q.front();
            q.pop();
            int i=x.ff;
            int j=x.ss;
            vis[i][j]=true;
            if(check(i+1,j) && c[i+1][j]!='#' && !vis[i+1][j]){
                dis[i+1][j]=dis[i][j]+1;
                vis[i+1][j]=true;
                q.push(make_pair(i+1,j));
            }
            if(check(i-1,j) && c[i-1][j]!='#' && !vis[i-1][j]){
                dis[i-1][j]=dis[i][j]+1;
                vis[i-1][j]=true;
                q.push(make_pair(i-1,j));
            }
            if(check(i,j+1) && c[i][j+1]!='#' && !vis[i][j+1]){
                dis[i][j+1]=dis[i][j]+1;
                vis[i][j+1]=true;
                q.push(make_pair(i,j+1));
            }
            if(check(i,j-1) && c[i][j-1]!='#' && !vis[i][j-1]){
                dis[i][j-1]=dis[i][j]+1;
                vis[i][j-1]=true;
                q.push(make_pair(i,j-1));
            }
            if(c[i][j]>='a' && c[i][j]<='z' && !g[c[i][j]-'0']){
                g[c[i][j]-'0']=true;
                trav(k,v[c[i][j]-'a']){
                     if(!vis[k.ff][k.ss]){
                        dis[k.ff][k.ss]=dis[i][j]+1;
                        vis[k.ff][k.ss]=true;
                        q.push(make_pair(k.ff,k.ss));
                    }
                }
            }
            
        }
        if(dis[rx][ry]){
        cout<<dis[rx][ry]<<'\n';
        }
        else cout<<"-1\n";
   
    }
    return 0;
    
}
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
typedef pair<int, int> P;
const int INF = 5e6;

int di[4] = {1, 0, -1, 0};
int dj[4] = {0, 1, 0, -1};

int main() {
  int h, w;
  cin >> h >> w;
  vector<string> s(h);
  rep(i,h) cin >> s[i];
  // vector dist(h, vector(w, INF));
  vector<vector<int>> dist(h, vector<int>(w, INF));
  queue<P> q;
  rep(i,h)rep(j,w) {
    if (s[i][j] == 'S') {
      q.emplace(i,j);
      dist[i][j] = 0;
    }
  }
  vector<vector<P>> warps(256);
  rep(i,h)rep(j,w) warps[s[i][j]].emplace_back(i,j);
 
  while (!q.empty()) {
    auto [i,j] = q.front(); q.pop();
    if (s[i][j] == 'G') {
      cout << dist[i][j] << endl;
      return 0;
    }
    rep(v,4) {
      int ni = i + di[v], nj = j + dj[v];
      if (ni < 0 || ni >= h || nj < 0 || nj >= w) continue;
      if (s[ni][nj] == '#') continue;
      if (dist[ni][nj] != INF) continue;
      dist[ni][nj] = dist[i][j] + 1;
      q.emplace(ni,nj);
    }
 
    if (islower(s[i][j])) {
      for (P p : warps[s[i][j]]) {
        int ni = p.first, nj = p.second;
        if (dist[ni][nj] != INF) continue;
        dist[ni][nj] = dist[i][j] + 1;
        q.emplace(ni,nj);
      }
      warps[s[i][j]] = vector<P>();
    }
  }
  cout << -1 << endl;
  return 0;
}
