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

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define show(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define show(x)
#endif

typedef long long int ll;
typedef pair<int,int> pii;
template<typename T> using vec=std::vector<T>;

const int inf=1<<16;
const long long int infll=1LL<<62;
const double eps=1e-9;
const int dx[]={1,0},dy[]={0,1};

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
    os << "[";
    for (const auto &v : vec) {
    	os << v << ",";
    }
    os << "]";
    return os;
}

void solve(int h,int w){
    vector<string> c(h);
    rep(i,0,h) cin >> c[i];

    auto ok=[&](int y,int x){
        return 0<=y and y<h and 0<=x and x<w and c[y][x]!='#';
    };
    auto is_adjacent=[](int y1,int x1,int y2,int x2){
        return (y1+1==y2 and x1==x2) or (y1==y2 and x1+1==x2);
    };

    static bool can_move[50][50][50][50];
    vector<pii> ps[26];
    fill_n((bool*)can_move,50*50*50*50,false);
    for(int y=h-1; y>=0; --y) for(int x=w-1; x>=0; --x){
        if('A'<=c[y][x] and c[y][x]<='Z') ps[c[y][x]-'A'].push_back(make_pair(y,x));
        can_move[y][x][y][x]=true;
        rep(i,0,2){
            int ny=y+dy[i],nx=x+dx[i];
            if(!ok(ny,nx)) continue;
            can_move[y][x][ny][nx]=true;
            rep(y_,ny,h) rep(x_,nx,w) can_move[y][x][y_][x_]|=can_move[ny][nx][y_][x_];
        }
    }

    static int memo[50][50][50][50];
    static bool done[50][50][50][50];
    fill_n((bool*)done,50*50*50*50,false);
    function<int(int,int,int,int)> rec=[&](int y1,int x1,int y2,int x2){
        if(done[y1][x1][y2][x2]) return memo[y1][x1][y2][x2];
        done[y1][x1][y2][x2]=true;
        if(y1==y2 and x1==x2) return memo[y1][x1][y2][x2]=0;
        if(!can_move[y1][x1][y2][x2]) return memo[y1][x1][y2][x2]=-inf;
        int res=-1;
        if(ok(y1+1,x1)) res=max(res,rec(y1+1,x1,y2,x2));
        if(ok(y1,x1+1)) res=max(res,rec(y1,x1+1,y2,x2));
        if('a'<=c[y1][x1] and c[y1][x1]<='z'){
            for(pii &p:ps[c[y1][x1]-'a']){
                int y=p.first,x=p.second;
                if(!can_move[y1][x1][y][x] or !can_move[y][x][y2][x2]) continue;
                if(is_adjacent(y1,x1,y,x)){
                    res=max(res,rec(y,x,y2,x2)+1);
                    continue;
                }
                rep(i,0,2){
                    int y1_=y1+dy[i],x1_=x1+dx[i];
                    if(!ok(y1_,x1_)) continue;
                    rep(j,0,2){
                        int y_=y-dy[j],x_=x-dx[j];
                        if(!ok(y_,x_) or !can_move[y1_][x1_][y_][x_]) continue;
                        res=max(res,rec(y1_,x1_,y_,x_)+rec(y,x,y2,x2)+1);
                    }
                }
            }
        }
        return memo[y1][x1][y2][x2]=res;
    };
    int ans=rec(0,0,h-1,w-1);
    cout << (ans<0?-1:ans) << endl;
}

int main(){
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(10);
    for(;;){
        int h,w;
        cin >> h >> w;
        if(h==0 and w==0) break;
        solve(h,w);
    }
    return 0;
}

Measured memory_bytes: 35632