#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using i64 = long long;
using i32 = int;
using f64 = long double;
template <class Key>
using vec = vector<Key>;
template <class Key>
using heap = priority_queue<Key>;
template <class Key>
using hash_set = unordered_set<Key>;
template <class Key, class Value>
using hash_map = unordered_map<Key, Value>;
using str = string;
template <size_t Size1>
using a64 = array<i64, Size1>;
template <size_t Size1, size_t Size2>
using aa64 = array<a64<Size2>, Size1>;
template <size_t Size1, size_t Size2, size_t Size3>
using aaa64 = array<aa64<Size2, Size3>, Size1>;
using p64 = pair<i64, i64>;
using v64 = vec<i64>;
using vv64 = vec<v64>;
using s64 = set<i64>;
using m64 = map<i64, i64>;
mt19937 gen(998244353);
const i64 inf = numeric_limits<i64>::max() / 2;
template <typename T>
inline i64 sz(const T& a) {
  return (i64)(a.size());
}
inline void fast() { ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0); }
template <typename T>
inline bool check_min(T& a, T b) {
  if (a > b) return a = b, 1;
  return 0;
}
template <typename T>
inline bool check_max(T& a, T b) {
  if (a < b) return a = b, 1;
  return 0;
}
struct Problem {
  Problem(bool multitest = 0) {
    read();
    if (!multitest) solve();
  }
  void solve(), read();
};
signed main() {
  fast();
  Problem();
  return 0;
}
i64 n, m;
vec<p64> a;
map<i64, v64> xs, ys, ds1, ds2;
v64 ans;
void add_to_ans(map<i64, v64>& m) {
  for (auto& p : m) {
    v64& v = p.second;
    for (i64 i = 0; i < sz(v) - 1; i++) ++ans[v[i]];
    for (i64 i = 1; i < sz(v); i++) ++ans[v[i]];
  }
}
void Problem::solve() {
  ans.assign(m, 0);
  for (i64 i = 0; i < m; i++) {
    i64 x = a[i].first, y = a[i].second;
    xs[x].push_back(i);
    ys[y].push_back(i);
    ds1[y - x].push_back(i);
    ds2[x + y].push_back(i);
  }
  for (auto& p : xs)
    sort((p.second).begin(), (p.second).end(),
         [&](i64 i, i64 j) { return a[i].second < a[j].second; });
  for (auto& p : ys)
    sort((p.second).begin(), (p.second).end(),
         [&](i64 i, i64 j) { return a[i].first < a[j].first; });
  for (auto& p : ds1)
    sort((p.second).begin(), (p.second).end(),
         [&](i64 i, i64 j) { return a[i].first < a[j].first; });
  for (auto& p : ds2)
    sort((p.second).begin(), (p.second).end(),
         [&](i64 i, i64 j) { return a[i].first < a[j].first; });
  add_to_ans(xs);
  add_to_ans(ys);
  add_to_ans(ds1);
  add_to_ans(ds2);
  v64 cnt(9, 0);
  for (i64 i = 0; i < m; i++) {
    ++cnt[ans[i]];
  }
  for (i64 i = 0; i <= 8; i++) {
    cout << cnt[i] << " ";
  }
  cout << "\n";
}
void Problem::read() {
  cin >> n >> m;
  a.resize(m);
  for (i64 i = 0; i < m; i++) {
    i64 x, y;
    cin >> x >> y;
    --x, --y;
    a[i] = {x, y};
  }
}
