#include <set>
#include <iostream>
#include <cstdio>
#include <queue>

#include <tr1/unordered_map>

#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define IN(x,s,g) ((x) >= (s) && (x) < (g))
#define ISIN(x,y,w,h) (IN((x),0,(w)) && IN((y),0,(h)))

using namespace std;

int h, w;
char g[20][20];
vector<int> xs;
vector<int> ys;
int n;
int cnt;

tr1::unordered_map<long long, int> memo[15][15];

inline long long gen(){
  long long ret = 0ll;

  REP(i, n){
    long long item = g[ys[i]][xs[i]] - '0';
    ret |= (item << (i * 4));
  }

  return ret;
}

inline bool ok(int y){
  if(y < 2) return true;
  REP(i, n){
    if(ys[i] < y - 1 && g[ys[i]][xs[i]] != '0'){
      return false;
    }
    if(ys[i] >= y - 1) return true;
  }
  return true;
}

void print(){
  REP(i,h){
    puts(g[i]);
  }
}

inline void paint(int y, int x){
  REP(i,3) REP(j,3){
    int xx = x + j - 1;
    int yy = y + i - 1;
    if(ISIN(xx, yy, w, h) && isdigit(g[yy][xx])) g[yy][xx]--;
  }
}

inline void unpaint(int y, int x){
  REP(i,3) REP(j,3){
    int xx = x + j - 1;
    int yy = y + i - 1;
    if(ISIN(xx, yy, w, h) && isdigit(g[yy][xx])) g[yy][xx]++;
  }
}

const int MAX = 10000;

int solve(int y, int x, long long flag){
  if(y == h){
    return flag == 0ll ? 0 : MAX;
  }

  if(x == 0 && !ok(y)){
    return MAX;
  }

  if(g[y][x] == '.'){
    if(x == w - 1) return solve(y + 1, 0, flag);
    return solve(y, x + 1, flag);
  }

  {
    tr1::unordered_map<long long, int>::iterator it = memo[y][x].find(flag);
    if(it != memo[y][x].end()) return it->second;
  }

  int ret = MAX;

  bool canput = true;
  int nx = (x == w - 1 ? 0 : x + 1);
  int ny = (x == w - 1 ? y + 1 : y);

  ret = min(ret, solve(ny, nx, flag));

  REP(i, 3) REP(j, 3){
    int xx = x + j - 1;
    int yy = y + i - 1;

    if(ISIN(xx, yy, w, h) && isdigit(g[yy][xx]) && g[yy][xx] == '0')
      canput = false;
  }

  if(canput){
    paint(y, x);
    cnt++;
    ret = min(ret, 1 + solve(ny, nx, gen()));
    cnt--;
    unpaint(y, x);
  }

  // printf("solve(%d, %d, %lld): cnt = %d, ret = %d, canput = %d\n", y, x, flag, cnt, ret, canput);
  // print(); puts("");

  return memo[y][x][flag] = ret;
}

int main(){
  while(scanf("%d%d", &h, &w), h + w){
    REP(i,h) scanf("%s", g[i]);

    bool update = true;
    int tmp = 0;

    while(update){
      update = false;
      REP(i,h) REP(j, w) if(isdigit(g[i][j])){
        int c = 0;
        REP(ii, 3) REP(jj, 3){
          int yy = i + ii - 1;
          int xx = j + jj - 1;
          if(ISIN(xx, yy, w, h) && g[i][j] != '.'){
            c++;
          }
        }

        if(g[i][j] - '0' == c){
          REP(ii, 3) REP(jj, 3){
            int yy = i + ii - 1;
            int xx = j + jj - 1;
            if(ISIN(xx, yy, w, h) && g[i][j] != '.'){
              paint(yy, xx);
              update = true;
              tmp++;
            }
          }
        }
      }
    }

    xs = vector<int>();
    ys = vector<int>();
    REP(i,h) REP(j,w){
      if(isdigit(g[i][j])){
        xs.push_back(j);
        ys.push_back(i);
      }

      if(g[i][j] == '*'){
        bool valid = false;
        REP(ii, 3) REP(jj, 3){
          int yy = i + ii - 1;
          int xx = j + jj - 1;

          if(ISIN(xx, yy, w, h) && isdigit(g[yy][xx]))
            valid = true;
        }
        if(!valid) g[i][j] = '.';
      }
    }

    n = xs.size();

    REP(i,h) REP(j,w) memo[i][j].clear();

    // print();
    printf("%d\n", tmp + solve(0, 0, gen()));
  }
  return 0;
}

Measured memory_bytes: 0