#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
constexpr int INF = 0x3f3f3f3f;
constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr double EPS = 1e-8;
constexpr int MOD = 1000000007;
// constexpr int MOD = 998244353;
constexpr int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
constexpr int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    std::cout << fixed << setprecision(20);
  }
} iosetup;

struct UnionFind {
  UnionFind(int n) : data(n, -1) {}

  int root(int ver) { return data[ver] < 0 ? ver : data[ver] = root(data[ver]); }

  bool unite(int u, int v) {
    u = root(u);
    v = root(v);
    if (u == v) return false;
    if (data[u] > data[v]) std::swap(u, v);
    data[u] += data[v];
    data[v] = u;
    return true;
  }

  bool same(int u, int v) { return root(u) == root(v); }

  int size(int ver) { return -data[root(ver)]; }

private:
  std::vector<int> data;
};

template <typename T>
std::vector<std::vector<T>> rotate(const std::vector<std::vector<T>> &grid, int angle, T basis = ' ') {
  int h = grid.size(), w = grid.front().size();
  std::vector<std::vector<T>> rotated_grid;
  if (angle == 45) {
    rotated_grid.assign(h + w - 1, std::vector<T>(h + w - 1, basis));
    for (int i = 0; i < h; ++i) for (int j = 0; j < w; ++j) rotated_grid[i + j][i - j + w - 1] = grid[i][j];
  } else if (angle == 90) {
    rotated_grid.assign(w, std::vector<T>(h));
    for (int i = 0; i < h; ++i) for (int j = 0; j < w; ++j) rotated_grid[w - 1 - j][i] = grid[i][j];
  } else {
    assert(false);
  }
  return rotated_grid;
}

int solve(const vector<vector<char>> &s) {
  int h = s.size(), w = s.front().size();
  if (h == 2) return 0;
  UnionFind uf(h);
  uf.unite(0, h - 1);
  FOR(i, 1, h - 1) {
    if (s[i].front() == '#' || s[i].back() == '#') uf.unite(0, i);
  }
  FOR(j, 1, w - 1) {
    vector<int> wall;
    REP(i, h) {
      if (s[i][j] == '#') wall.emplace_back(i);
    }
    FOR(i, 1, wall.size()) uf.unite(wall[i - 1], wall[i]);
  }
  int ans = 0;
  FOR(i, 1, h - 1) {
    if (uf.root(i) == i && uf.root(0) != i) ++ans;
  }
  return ans;
}

int main() {
  int h, w; cin >> h >> w;
  vector<vector<char>> s(h, vector<char>(w)); REP(i, h) REP(j, w) cin >> s[i][j];
  int ans = solve(s);
  s = rotate(s, 90);
  chmin(ans, solve(s));
  cout << ans << '\n';
  return 0;
}

/**
 *    Author : Tanbin_Hasan
 *    Created : 13.04.2021 02:40:07
**/
#include <bits/stdc++.h>

using namespace std ;

int main(void) {
  ios::sync_with_stdio(false) ; cin.tie(0) ;
  string a , b , c ;
  cin >> a ;
  cin >> b ;
  cin >> c ;
  string s = a + b + c ;
  unordered_set<char> tot ;
  for (auto &i : s) {
    tot.insert(i) ;
  } 
  if ((int) tot.size() > 10) {
    cout << "UNSOLVABLE" ;
    return 0 ;
  }
  unordered_map<char,int> value ;
  vector<int> ar = {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9} ;
  do {
    int cnt = 0 ;
    for (auto &i : tot) {
      value[i] = ar[cnt++] ;
    }
    string x = a , y = b , z = c ;
    for (auto &i : x) {
      i = (value[i] + '0') ;
    }
    for (auto &i : y) {
      i = (value[i] + '0') ;
    }
    for (auto &i : z) {
      i = (value[i] + '0') ;
    }
    if (x.front() == '0' || y.front() == '0' || z.front() == '0') {
      continue ;
    }
    long long p = stoll(x) , q = stoll(y) , r = stoll(z) ;
    if (p + q == r) {
      cout << p << '\n' ;
      cout << q << '\n' ;
      cout << r ;
      return 0 ;
    }
  } while (next_permutation(ar.begin() , ar.end())) ;
  cout << "UNSOLVABLE" ;
  return 0 ;
}