#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define dump(n) cerr<<"# "<<#n<<'='<<(n)<<endl
template<typename T>
ostream& operator<<(ostream& os,const vector<T>& a)
{
	os<<'[';
	for(int i=0;i<a.size();i++)
		os<<(i?" ":"")<<a[i];
	return os<<']';
}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p)
{
	return os<<'('<<p.first<<','<<p.second<<')';
}

void dfs(vector<string>& grid,int i,int j)
{
	int h=grid.size(),w=grid[0].size();
	if(i<0 || h<=i || j<0 || w<=j || grid[i][j]=='.')
		return;
	grid[i][j]='.';
	for(int k=0;k<4;k++)
		dfs(grid,i+"\xff\x1\0\0"[k],j+"\0\0\xff\x1"[k]);
}
bool valid(vector<string> grid)
{
	int h=grid.size(),w=grid[0].size();
	for(int i=0;i<h;i++)
		for(int j=0;j<w;j++){
			if(grid[i][j]!='.')
				continue;
			for(int k=0;k<4;k++){
				int ii=i+"\xff\x1\0\0"[k],jj=j+"\0\0\xff\x1"[k];
				if(0<=ii && ii<h && 0<=jj && jj<w && grid[ii][jj]=='.')
					return -1;
			}
		}
	int cnt=0;
	for(int i=0;i<h;i++)
		for(int j=0;j<w;j++)
			if(grid[i][j]=='#'){
				dfs(grid,i,j);
				cnt++;
			}
	return cnt<=1;
}

string adjust(string s)
{
	unordered_map<char,char> m;
	for(int i=0;i<s.size();i++)
		if(isdigit(s[i]) && !m.count(s[i]))
			m.insert(make_pair(s[i],'0'+m.size()));
	for(int i=0;i<s.size();i++)
		if(isdigit(s[i]))
			s[i]=m[s[i]];
	return s;
}

string change(string s,int i,char c)
{
	if(c=='#'){
		if(isdigit(s[i]) && i>0 && isdigit(s[i-1])){
			char mn=min(s[i-1],s[i]),mx=max(s[i-1],s[i]);
			replace(s.begin(),s.end(),mx,mn);
		}
		else if(!isdigit(s[i]) && (i==0 || !isdigit(s[i-1]))){
			char mx='0'-1;
			for(int j=0;j<s.size();j++)
				mx=max(mx,s[j]);
			s[i]=mx+1;
		}
		else if(i>0 && isdigit(s[i-1])){
			s[i]=s[i-1];
		}
		//if(!isdigit(s[i]))
		//	s[i]='9';
		//if(i>0 && isdigit(s[i-1]))
		//	replace(s.begin(),s.end(),(char)s[i-1],(char)s[i]);
	}
	else
		s[i]='.';
	return adjust(s);
}

int solve(vector<string>& grid)
{
	if(!valid(grid))
		return -1;
	
	int h=grid.size(),w=grid[0].size();
	
	unordered_map<string,int> dp;
	dp[string(w,'$')]=0;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			unordered_map<string,int> dp2;
			for(auto kv:dp){
				if(grid[i][j]=='#'){
					string key=kv.first;
					if(j>0 && isdigit(key[j-1]) && key[j-1]==key[j])
						continue;
					key=change(key,j,'#');
					dp2[key]=max(dp2[key],kv.second+1);
				}
				else if(grid[i][j]=='.'){
					string key=kv.first;
					if(key[j]=='.' || j>0 && key[j-1]=='.' || isdigit(key[j]) && count(key.begin(),key.end(),key[j])==1)
						continue;
					key=change(kv.first,j,'.');
					dp2[key]=max(dp2[key],kv.second);
				}
				else{
					string key=kv.first;
					if(!(key[j]=='.' || j>0 && key[j-1]=='.' || isdigit(key[j]) && count(key.begin(),key.end(),key[j])==1)){
						key=change(kv.first,j,'.');
						dp2[key]=max(dp2[key],kv.second);
					}
					key=kv.first;
					if(!(j>0 && isdigit(key[j-1]) && key[j-1]==key[j])){
						key=change(key,j,'#');
						dp2[key]=max(dp2[key],kv.second+1);
					}
				}
			}
			dp=dp2;
			//cout<<"dp:"; for(auto kv:dp) cout<<' '<<kv; cout<<endl;
		}
	}
	
	int res=-1;
	for(auto kv:dp){
		unordered_set<char> s(kv.first.begin(),kv.first.end());
		s.erase('.');
		if(s.size()>1)
			continue;
		res=max(res,kv.second);
	}
	return res;
}

int main()
{
	for(int h,w;cin>>h>>w && h|w;){
		vector<string> grid(h);
		for(int i=0;i<h;i++)
			cin>>grid[i];
		if(h>w){
			vector<string> temp(w);
			for(int i=0;i<h;i++)
				for(int j=0;j<w;j++)
					temp[j]+=grid[i][j];
			grid=temp;
		}
		cout<<solve(grid)<<endl;
	}
	return 0;
}

Measured memory_bytes: 1948