#include <bits/stdc++.h>
const int ms = 1 << 14;
int c = 0;
bool table[2][ms];
int rep[2][ms];
int par[2 * ms];
int nxt[2 * ms];
int step[2 * ms];
int ans = 0;
int get() {
  ans++;
  par[c] = c;
  return c++;
}
int get_par(int x) {
  if (par[x] == x) {
    return x;
  } else {
    return par[x] = get_par(par[x]);
  }
}
void make_union(int a, int b) {
  a = get_par(a);
  b = get_par(b);
  if (a == b) {
    return;
  }
  ans--;
  par[b] = a;
}
char buffer[ms];
int main() {
  int n, m;
  std::cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    scanf(" %s", buffer);
    for (int j = 0; j < m / 4; j++) {
      char c = buffer[j];
      int cur;
      if (c >= '0' && c <= '9') {
        cur = c - '0';
      } else {
        cur = c - 'A' + 10;
      }
      for (int k = 0; k < 4; k++) {
        table[i & 1][4 * j + k] = ((1 << (3 - k)) & cur) ? true : false;
      }
    }
    for (int j = 0; j < m; j++) {
      if (!table[i & 1][j]) {
        continue;
      }
      if (j && table[i & 1][j - 1]) {
        rep[i & 1][j] = rep[i & 1][j - 1];
      } else if (table[(i + 1) & 1][j]) {
        rep[i & 1][j] = rep[(i + 1) & 1][j];
        continue;
      } else {
        rep[i & 1][j] = get();
      }
      if (table[(i + 1) & 1][j]) {
        make_union(rep[(i + 1) & 1][j], rep[i & 1][j]);
      }
    }
    c = 0;
    for (int j = 0; j < m; j++) {
      if (!table[i & 1][j]) {
        continue;
      }
      rep[i & 1][j] = get_par(rep[i & 1][j]);
      if (step[rep[i & 1][j]] != i) {
        step[rep[i & 1][j]] = i;
        nxt[rep[i & 1][j]] = c++;
      }
    }
    for (int j = 0; j < m; j++) {
      if (!table[i & 1][j]) {
        continue;
      }
      rep[i & 1][j] = nxt[rep[i & 1][j]];
    }
    for (int j = 0; j < c; j++) {
      par[j] = j;
    }
  }
  std::cout << ans << "\n";
}
