#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <cassert>

#define foreach(it,v) for (__typeof((v).begin()) it = (v).begin(); it != (v).end(); it++)
#define sqr(a) ((a)*(a)) 
#define mp(a,b) make_pair((a),(b))

template <class T> void Cmin(T &t,T x){if (x < t) t = x;}
template <class T> void Cmax(T &t,T x){if (x > t) t = x;}

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int> VI;

const int INF = 0x3fffffff;
const LL LINF = 1LL << 60;
const double PI = acos(-1.0);
const double EPS = 1e-9;

const int maxN = 20100;
const int maxM = 1000000;

struct graph
{
    int v, next, op, c;
}edge[maxM];
 
int lv[maxN], vect[maxN];
int S, T, tot;
 
void add(int u, int v, int c)
{
	//printf("# %d %d\n", u, v);
    edge[++tot].v = v;
    edge[tot].c = c;
    edge[tot].next = vect[u];
    vect[u] = tot;
    edge[tot].op = tot + 1;
    edge[++tot].v = u;
    edge[tot].c = 0;
    edge[tot].next = vect[v];
    vect[v] = tot;
    edge[tot].op = tot - 1;
}

bool build()
{
    memset(lv, 0, sizeof(lv));
    queue<int> Q;
    Q.push(S);
    lv[S] = 1;
    while (!Q.empty()){
            int u = Q.front();
            Q.pop();
            for (int it = vect[u]; it; it = edge[it].next){
                    int v = edge[it].v; 
                    int c = edge[it].c;
                    if (c > 0 && !lv[v]){
                            lv[v] = lv[u] + 1;
                            Q.push(v);
                            if (v == T) return true;
                    }
            }
    }
    return false;   
}
 
int dfs(int u, int flow)
{
    if (u == T || !flow) return flow;
    int tp, now = 0;
    for (int it = vect[u]; it; it = edge[it].next){
            int v = edge[it].v;
            int c = edge[it].c;
            int op = edge[it].op;
            if (c > 0 && lv[u] + 1 == lv[v]){
                tp = dfs(v, min(flow, c));
                now = now + tp;
                flow = flow - tp;     
                edge[it].c -= tp;
                edge[op].c += tp;
            }    
    }
    if (!now) lv[u] = 0; 
    return now;
}
 
int dinic()
{
    int ans = 0;
    while (build()) ans += dfs(S, INF);
    return ans;
}

int init(int s, int t)
{
    S = s, T = t, tot = 0;
    memset(vect, 0, sizeof(vect));
}

const int dx[] = {0, 0, 1, -1};
const int dy[] = {-1, 1, 0, 0};

char g[60][60];
int vis[60][60];
int mark[60][60];
int n, m;
int cnt;
int num[3];

void dfs(int x, int y, int col)
{
	vis[x][y] = col;
	mark[x][y] = ++cnt; 
	num[col]++;
	if (col == 1) add(S, mark[x][y], 1);
	if (col == 2) add(mark[x][y], T, 1);
	for (int i = 0; i < 4; i++){
		int tx = x + dx[i];
		int ty = y + dy[i];
		if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
		if (!vis[tx][ty] && g[tx][ty] == '.') dfs(tx, ty, 3 - col);
		if (col == 1){
			add(mark[x][y], mark[tx][ty], 1);
		}
	}
}

int main()
{
	while(scanf("%d%d%d", &n, &m) != EOF){
		for (int i = 0; i < n; i++) scanf("%s", g[i]);
		init(1, 2);
		cnt = 2;
		memset(vis, 0, sizeof(vis));
		memset(num, 0, sizeof(num));
		for (int i = 0; i < n; i++){
			for (int j = 0; j < m; j++){
				if (!vis[i][j] && g[i][j] == '.'){
					dfs(i, j, 1);
				}
			}
		}
		//printf("%d %d %d\n", dinic(), num[1], num[2]);
		int ans = dinic();
		if (ans == num[1] && ans == num[2])
			puts("2");
		else
			puts("1");
	}
    return 0;
}



    
