#include <bits/stdc++.h>
using namespace std;
#define FOR(i,k,n) for(int i = (int)(k); i < (int)(n); i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(a) a.begin(), a.end()
#define MS(m,v) memset(m,v,sizeof(m))
#define D10 fixed<<setprecision(10)
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template<class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/
//const int dx[] = { -1, 0, 0, 1 }, dy[] = { 0, -1, 1, 0 };
//[const int dx[] = { -1, -1, -1, 0, 0, 1, 1, 1 }, dy[] = { 0, -1, 1, -1, 1, 0, -1, 1 };
bool valid(int x, int y, int h, int w) { return (x >= 0 && y >= 0 && x < h&&y < w); }
int place(int x, int y, int w) { return w*x + y; }

int h, w;
vs fld;
bool edge[55][55][55][55];
int dp[55][55][55][55];

int is_pair(char c, char d)
{
	if (islower(c) && isupper(d) && toupper(c) == d) return 1;
	return 0;
}

int solve(int top, int left, int bottom, int right)
{
	if (top == bottom && left == right) return 0;
	if (left > right || top > bottom) return 0;
	if (!edge[top][left][bottom][right]) return 0;
	if (!valid(top, left, h, w) || !valid(bottom, right, h, w)) return 0;
	if (dp[top][left][bottom][right] >= 0) return dp[top][left][bottom][right];
	int res = 0;
	if (valid(top + 1, left, h, w) && fld[top + 1][left] != '#') chmax(res, solve(top + 1, left, bottom, right));
	if (valid(top, left + 1, h, w) && fld[top][left + 1] != '#') chmax(res, solve(top, left + 1, bottom, right));
	if (islower(fld[top][left]))
	{
		int match = is_pair(fld[top][left], fld[bottom][right]);
		if (match)
		{
			if (valid(top + 1, left, h, w) && fld[top + 1][left] != '#')
			{
				chmax(res, solve(top + 1, left, bottom, right - 1) + 1);
				chmax(res, solve(top + 1, left, bottom - 1, right) + 1);
			}
			if (valid(top, left + 1, h, w) && fld[top][left + 1] != '#')
			{
				chmax(res, solve(top, left + 1, bottom - 1, right) + 1);
				chmax(res, solve(top, left + 1, bottom, right - 1) + 1);
			}
		}
		else
		{
			FOR(i, top, bottom + 1)FOR(j, left, right + 1)
			{
				if (fld[i][j] != toupper(fld[top][left]) || !edge[top][left][i][j] || !edge[i][j][bottom][right]) continue;
				chmax(res, solve(top, left, i, j) + solve(i, j, bottom, right));
			}
		}
	}
	//cout << top << " " << left << " " << bottom << " " << right << endl;
	//cout << res << endl;
	return dp[top][left][bottom][right] = res;
}

int main()
{
	while (cin >> h >> w, h)
	{
		MS(edge, false);
		MS(dp, -1);
		fld.resize(h);
		REP(i, h) cin >> fld[i];
		REP(i, h)REP(j, w)
		{
			if (fld[i][j] == '#') continue;
			queue<pii> que;
			que.emplace(i, j);
			while (!que.empty())
			{
				int x = que.front().first, y = que.front().second;
				que.pop();
				if (!edge[i][j][x + 1][y] && valid(x + 1, y, h, w) && fld[x + 1][y] != '#')
				{
					edge[i][j][x + 1][y] = true;
					que.emplace(x + 1, y);
				}
				if (!edge[i][j][x][y + 1] && valid(x, y + 1, h, w) && fld[x][y + 1] != '#')
				{
					edge[i][j][x][y + 1] = true;
					que.emplace(x, y + 1);
				}
			}
		}
		if (!(h == 1 && w == 1) && !edge[0][0][h - 1][w - 1])
		{
			puts("-1");
			continue;
		}
		//int a = is_pair(fld[0][0], fld[h - 1][w - 1]);
		cout << solve(0, 0, h-1, w-1) << endl;
	} 
	return 0;
}

Measured memory_bytes: 47744