#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;

struct point_t {
	int x, y;
	point_t() { x = y = 0; }
	point_t(int tx, int ty) { x = tx, y = ty; }
	point_t operator+(const point_t &r) const {
		return point_t(x + r.x, y + r.y);
	}
	point_t operator-(const point_t &r) const {
		return point_t(x - r.x, y - r.y);
	}
	point_t operator*(const double &r) const {
		return point_t(x * r, y * r);
	}
	point_t operator/(const double &r) const {
		return point_t(x / r, y / r);
	}
	double l() const {
		return sqrt((double)x * x + y * y);
	}
	void read() { scanf("%d%d", &x, &y); }
	bool operator<(const point_t &r) const {
		if (x != r.x) return y < r.y;
		return x < r.x;
	} 
	bool operator==(const point_t &r) const {
		return x == r.x && y == r.y;
	}
};

int dblcmp(int x) {
	return x < 0 ? -1 : x > 0;
}

int dot(point_t p1, point_t p2) {
	return p1.x * p2.x + p1.y * p2.y;
}

int cross(point_t p1, point_t p2) {
	return p1.x * p2.y - p1.y * p2.x;
}

const int maxn = 2001;
int n, m, deg[maxn];
point_t seg[maxn][2], p[maxn];
int id[1001][1001];
vector<int> edge[maxn];
vector<pair<int, int> > con;
bool vis[maxn];
bool hasm[maxn];

const int pattern[10][10] = {
	{4, 2, 2, 2, 2},
	{2, 1, 1},
	{6, 1, 1, 2, 2, 2, 2},
	{6, 1, 1, 1, 2, 2, 3},
	{5, 1, 1, 1, 2, 3},
	{6, 1, 1, 2, 2, 2, 2},
	{6, 1, 2, 2, 2, 2, 3},
	{4, 1, 1, 2, 2},
	{6, 2, 2, 2, 2, 3, 3},
	{5, 1, 2, 2, 2, 3}
};
int get(point_t p) {
	return id[p.x][p.y];
}

bool onseg(point_t p1, point_t p2, point_t p) {
	if (cross(p - p1, p2 - p1) != 0) return false;
	return dot(p1 - p, p2 - p) < 0;
}

void dfs(int u) {
	vis[u] = true;
	con.push_back(make_pair(deg[u], u));
	for (vector<int>::iterator it = edge[u].begin(); it != edge[u].end(); ++it) {
		int v = *it;
		if (vis[v]) continue;
		dfs(v);
	}
}

int recognize() {
	sort(con.begin(), con.end());
	int ans = -1;
	for (int i = 0; i < 10; ++i) {
		if (con.size() != pattern[i][0]) continue;
		bool flag = true;
		for (int j = 1; j <= con.size(); ++j) {
			if (con[j - 1].first != pattern[i][j]) {
				flag = false;
				break;
			}
		}
		if (flag) {
			ans = i;
			break;
		} 
	}
	if (ans != 2) return ans;
	int u = con[0].second;
	int v = -1, w = -1;
	v = edge[u][0];
	w = (edge[v][0] == u ? edge[v][1] : edge[v][0]);
	if (cross(p[w] - p[u], p[v] - p[u]) > 0) return 2;
	return 5;
}

int main() {
	while (scanf("%d", &n) != EOF) {
		if (n == 0) break;
		m = 0;
		for (int i = 1; i <= n; ++i) {
			seg[i][0].read();
			seg[i][1].read();
			p[++m] = seg[i][0];
			p[++m] = seg[i][1];
		}
		sort(p + 1, p + 1 + m);
		m = unique(p + 1, p + 1 + m) - p - 1;
		memset(id, 0, sizeof(id));
		memset(hasm, 0, sizeof(hasm));
		for (int i = 1; i <= m; ++i) id[p[i].x][p[i].y] = i;
		for (int i = 1; i <= m; ++i) edge[i].clear(), deg[i] = 0;
		for (int i = 1; i <= m; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (onseg(seg[j][0], seg[j][1], p[i])) {
					int u = get(seg[j][0]), v = get(seg[j][1]), w = get(p[i]);
					edge[u].push_back(w);
					edge[w].push_back(u);
					edge[v].push_back(w);
					edge[w].push_back(v);			
					++deg[u], ++deg[v], deg[w] += 2;
					hasm[j] = true;
				}	
			}
		}
		for (int i = 1; i <= n; ++i) {
			if (hasm[i]) continue;
			int u = get(seg[i][0]), v = get(seg[i][1]);
			edge[u].push_back(v);
			edge[v].push_back(u);
			++deg[u], ++deg[v];
		}
		memset(vis, 0, sizeof(vis));
		static int cnt[10];
		memset(cnt, 0, sizeof(cnt));
		for (int i = 1; i <= m; ++i) {
			if (vis[i]) continue;
			con.clear();
			dfs(i);
			int num = recognize();
			if (num == -1) continue;
			++cnt[num];
		}
		for (int i = 0; i < 10; ++i) printf("%d%c", cnt[i], i == 9 ? '\n' : ' ');
	}
	return 0;
}

Measured memory_bytes: 5280