typedef complex<int> P;
#define X real()
#define Y imag()
P dirs[] = { P(1, 0), P(0, 1), P(-1, 0), P(0, -1), };
namespace std{
bool operator<(const P &p1, const P &p2) {
return p1.X == p2.X ? p1.Y < p2.Y : p1.X < p2.X;
}
};
// pos と同じ色で連結している所を, color で塗る.
set<P> coloring(vvi &in, P pos, int color){
int bck = in[pos.X][pos.Y];
in[pos.X][pos.Y] = color;
set<P> res;
res.insert(pos);
rep(dir, 4){
P npos = pos + dirs[dir];
if(in[npos.X][npos.Y] == bck){
set<P> tmp = coloring(in, npos, color);
res.insert(all(tmp));
}
}
return res;
}
bool is_maxsnake(vvi &in, set<P> &body){
// 蛇かチェックし, 頭/尻尾を決める.
vector<P> heads;
foreach(it, body){
int cnt = 0;
rep(dir, 4) if(body.count(*it + dirs[dir])) ++cnt;
if(cnt > 2) return false;
if(cnt < 2) heads.pb(*it);
}
if(sz(heads) >= 3 || sz(heads) == 0) return false;
// 蛇が最大であるかチェックする.
repsz(i, heads) rep(dir, 4){
P nei = heads[i] + dirs[dir];
if(in[nei.X][nei.Y] == 0){
int cnt = 0;
rep(dir2, 4)
if(in[(nei+dirs[dir2]).X][(nei+dirs[dir2]).Y] > 0) ++cnt;
if(cnt == 1) return false;
}
}
return true;
}
/*
void output(const vvi &in){
repsz(i, in){
repsz(j, in[i]){
cout << setw(3) << in[i][j];
}
cout << endl;
}
cout << endl;
}
*/
bool solve(){
int h, w;
cin >> h >> w;
if(!(h|w)) return false;
// 周りは -1 で囲う.
vvi in(h+2, vi(w+2, -1));
rep(i, h) rep(j, w){
char c; cin >> c;
in[i+1][j+1] = c - '0';
}
h += 2; w += 2;
int color = 2;
vector<set<P> > connects;
rep(i, h) rep(j, w) if(in[i][j] == 1){
connects.pb(coloring(in, P(i, j), color++));
}
// output(in);
int res = 0;
repsz(i, connects) if(is_maxsnake(in, connects[i])) ++res;
cout << res << endl;
return true;
}