#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<stack>
#include<bitset>
#include<numeric>
using namespace std;
typedef long long ll;
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;
const ll mod = 1000000007;
const long double eps = 1e-8;
typedef pair<int, int> P;

typedef long double ld;

#include<complex>
typedef complex<ld> Point;
const ld pi = acos(-1.0);
ld dot(Point a, Point b) { return real(conj(a)*b); }
ld cross(Point a, Point b) { return imag(conj(a)*b); }
namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
	}
}
bool eq(ld a, ld b) {
	return abs(a - b) < eps;
}
bool eq(Point a, Point b) {
	return abs(a - b) < eps;
}
struct Line {
	Point a, b;
};
struct Circle {
	Point p; ld r;
};
int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps)return 1;//counter clockwise
	if (cross(b, c) < -eps)return -1;//clock wise
	if (dot(b, c) < 0)return 2;//c--a--b on line
	if (norm(b) < norm(c))return -2;//a--b--c on line
	return 0; //a--c--b on line
}
//2直線の交差判定
bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}
//直線と線分の交差判定
bool isis_ls(Line l, Line s) {
	return (cross(l.b - l.a, s.a - l.a)*cross(l.b - l.a, s.b - l.a) < eps);
}
//点が直線上に存在するか
bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}
//点が線分上に存在するか
bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}
//線分と線分の交差判定
bool isis_ss(Line s, Line t) {
	if (isis_sp(t, s.a) || isis_sp(t, s.b) || isis_sp(s, t.a) || isis_sp(s, t.b))return true;
	return(cross(s.b - s.a, t.a - s.a)*cross(s.b - s.a, t.b - s.a) < -eps && cross(t.b - t.a, s.a - t.a)*cross(t.b - t.a, s.b - t.a) < -eps);
}
//点から直線への垂線の足
Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}
//直線と直線の交点
//平行な２直線に対しては使うな！！！！
Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a; Point tv = t.b - t.a;
	//if (cross(tv, sv) == 0)return { 0,0 };
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
//直線と点の距離
ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}
//直線と直線の距離
ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}
//線分と直線の距離
ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}
//線分と点の距離
ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(p - r) : min(abs(p - s.a), abs(p - s.b));
}
//線分と線分の距離
ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t))return 0;
	return min({ dist_sp(s,t.a),dist_sp(s,t.b),dist_sp(t,s.a),dist_sp(t,s.b) });
}

int distingish_number(vector<Line> &v) {
	if (v.size() == 1)return 1;
	if (v.size() == 3) {
		vector<Point> p;
		rep(i, 3) {
			Rep(j, i + 1, 3) {
				Line lhs = v[i], rhs = v[j];
				if (isis_ss(lhs, rhs)) {
					Point c = is_ll(lhs, rhs);
					p.push_back(c);
				}
			}
		}
		//
		if (p.size() != 2)return 0;
		//
		rep(i, 2) {
			int cnt = 0;
			rep(j, 3) {
				Line l = v[j];
				if (eq(l.a, p[i]) || eq(l.b, p[i]))cnt++;
			}
			if (cnt != 2)return 4;
		}
		return 7;
	}
	if (v.size() == 4) {
		vector<Point> p;
		rep(i, 4) {
			Rep(j, i + 1, 4) {
				Line lhs = v[i], rhs = v[j];
				if (isis_ss(lhs, rhs)) {
					Point c = is_ll(lhs, rhs);
					p.push_back(c);
				}
			}
		}
		if (p.size() == 3)return 3;
		//
		if (p.size() != 4)return 0;
		//
		rep(i, 4) {
			int cnt = 0;
			rep(j, 4) {
				Line l = v[j];
				if (eq(l.a, p[i]) || eq(l.b, p[i]))cnt++;
			}
			if (cnt != 2)return 9;
		}
		return 0;
	}
	vector<Point> p;
	rep(i, 5) {
		Rep(j, i + 1, 5) {
			Line lhs = v[i], rhs = v[j];
			if (isis_ss(lhs, rhs)) {
				Point c = is_ll(lhs, rhs);
				p.push_back(c);
			}
		}
	}
	if (p.size() == 6)return 8;
	if (p.size() == 5)return 6;
	if (p.size() != 4)return 0;
	ld ma = -1;
	int le, ri;
	rep(i, 4)Rep(j, i + 1, 4) {
		if (abs(p[i] - p[j]) > ma) {
			ma = abs(p[i] - p[j]); le = i, ri = j;
		}
	}
	ma = -1;
	int le2, ri2;
	rep(i, 4) {
		if (i == le || i == ri)continue;
		if (abs(p[i] - p[ri]) > ma) {
			ma = abs(p[i] - p[ri]);
			le2 = i;
		}
	}
	ri2 = 6 - le - ri - le2;
	if (ccw(p[le], p[le2], p[ri2]) == -1)return 2;
	return 5;
}

int n;
void solve() {
	vector<Line> v(n);
	vector<bool> used(n, false);
	rep(i, n) {
		Point a, b;
		ld x, y; cin >> x >> y; a = { x,y };
		cin >> x >> y; b = { x,y };
		v[i] = { a,b };
	}
	int cnt[10] = {};
	rep(i, n) {
		if (used[i])continue;
		vector<Line> u; u.push_back(v[i]); used[i] = true;
		rep(aa, 5) {
			Rep(j, i + 1, n) {
				if (used[j])continue;
				bool f = false;
				rep(k, u.size()) {
					if (isis_ss(u[k], v[j])) {
						f = true; break;
					}
				}
				if (f) {
					u.push_back(v[j]);
					used[j] = true;
				}
			}
		}
		//cout <<"???"<< u.size() << endl;
		cnt[distingish_number(u)]++;
	}
	rep(i, 10) {
		if (i > 0)cout << " ";
		cout << cnt[i];
	}
	cout << endl;
}
signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	while (cin >> n, n) {
		solve();
	}
	//stop
	return 0;
}


Measured memory_bytes: 3388