#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};


int H,W;
int dp[50][50][50][50];
int diff_row[2] = {0,1},diff_col[2] = {1,0};
char table[50][51];
bool can_visit[50][50][50][50];


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

int recursive(int row1,int col1,int row2,int col2){

	if(dp[row1][col1][row2][col2] != -1)return dp[row1][col1][row2][col2];

	if(row1 == row2 && row1 == H-1 && col1 == col2 && col1 == W-1)return 0;

	int ret = 0;

	if(table[row1][col1] == '.' || (table[row1][col1] >= 'A' && table[row1][col1] <= 'Z')){

		if(rangeCheck(row1,col1+1) == true && can_visit[row1][col1][row1][col1+1] == true)ret = max(ret,recursive(row1,col1+1,row2,col2));

		if(rangeCheck(row1+1,col1) == true && can_visit[row1][col1][row1+1][col1] == true)ret = max(ret,recursive(row1+1,col1,row2,col2));

	}else if(table[row1][col1] >= 'a' && table[row1][col1] <= 'z'){

		if(rangeCheck(row1,col1+1) == true && can_visit[row1][col1][row1][col1+1] == true)ret = max(ret,recursive(row1,col1+1,row2,col2));

		if(rangeCheck(row1+1,col1) == true && can_visit[row1][col1][row1+1][col1] == true)ret = max(ret,recursive(row1+1,col1,row2,col2));

		for(int tmp_row = row1; tmp_row <= row2; tmp_row++){
			for(int tmp_col = col1; tmp_col <= col2; tmp_col++){
				if(table[tmp_row][tmp_col]+32 == table[row1][col1] && can_visit[row1][col1][tmp_row][tmp_col] == true &&
						can_visit[tmp_row][tmp_col][row2][col2] == true){

					if((tmp_row == row1 && tmp_col == col1+1) || (tmp_row == row1+1 && tmp_col == col1)){

						ret = max(ret,recursive(tmp_row,tmp_col,row2,col2)+1);

					}else{

						if(rangeCheck(row1,col1+1) == true && can_visit[row1][col1][row1][col1+1] == true){

							if(rangeCheck(tmp_row-1,tmp_col) == true && can_visit[row1][col1+1][tmp_row-1][tmp_col] == true){
								ret = max(ret,recursive(row1,col1+1,tmp_row-1,tmp_col)+recursive(tmp_row,tmp_col,row2,col2)+1);
							}

							if(rangeCheck(tmp_row,tmp_col-1) == true && can_visit[row1][col1+1][tmp_row][tmp_col-1] == true){
								ret = max(ret,recursive(row1,col1+1,tmp_row,tmp_col-1)+recursive(tmp_row,tmp_col,row2,col2)+1);
							}
						}

						if(rangeCheck(row1+1,col1) == true && can_visit[row1][col1][row1+1][col1] == true){

							if(rangeCheck(tmp_row-1,tmp_col) == true && can_visit[row1+1][col1][tmp_row-1][tmp_col] == true){
								ret = max(ret,recursive(row1+1,col1,tmp_row-1,tmp_col)+recursive(tmp_row,tmp_col,row2,col2)+1);
							}

							if(rangeCheck(tmp_row,tmp_col-1) == true && can_visit[row1+1][col1][tmp_row][tmp_col-1] == true){
								ret = max(ret,recursive(row1+1,col1,tmp_row,tmp_col-1)+recursive(tmp_row,tmp_col,row2,col2)+1);
							}
						}
					}
				}
			}
		}
	}

	return dp[row1][col1][row2][col2] = ret;
}

void func(){

	for(int row = 0; row < H; row++){
		scanf("%s",table[row]);
	}


	for(int a = 0; a < H; a++){
		for(int b = 0; b < W; b++){
			for(int c = 0; c < H; c++){
				for(int d = 0; d < W; d++){
					dp[a][b][c][d] = -1;
					can_visit[a][b][c][d] = false;
				}
			}
		}
	}

	queue<Info> Q;

	int adj_row,adj_col;

	for(int start_row = 0; start_row < H; start_row++){
		for(int start_col = 0; start_col < W; start_col++){
			if(table[start_row][start_col] == '#')continue;

			can_visit[start_row][start_col][start_row][start_col] = true;
			Q.push(Info(start_row,start_col));

			while(!Q.empty()){

				for(int i = 0; i < 2; i++){
					adj_row = Q.front().row+diff_row[i];
					adj_col = Q.front().col+diff_col[i];

					if(rangeCheck(adj_row,adj_col) == false || table[adj_row][adj_col] == '#' || can_visit[start_row][start_col][adj_row][adj_col] == true)continue;

					can_visit[start_row][start_col][adj_row][adj_col] = true;
					Q.push(Info(adj_row,adj_col));
				}
				Q.pop();
			}
		}
	}

	if(can_visit[0][0][H-1][W-1] == false){
		printf("-1\n");
		return;
	}

	printf("%d\n",recursive(0,0,H-1,W-1));
}

int main(){

	while(true){
		scanf("%d %d",&H,&W);
		if(H == 0 && W == 0)break;

		func();
	}

	return 0;
}

Measured memory_bytes: 33684