#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
FOR(it,t) {if(it!=t.begin()) os<<" "; os<<*it;} return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

const int INF = 1<<28;
const double EPS = 1e-8;
const int MOD = 1000000007;

#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { P pos, dir; };
 
// 多角形
typedef vector<P> G;
 
// 円
struct C { P p; double r; };

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).real();
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).imag();
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.real()*b.real() < -EPS || a.imag()*b.imag() < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

// ベクトルpをベクトルbに射影したベクトルを計算する
inline P proj(const P& p, const P& b) {
	return b*inp(p,b)/norm(b);
}
 
// 点pから直線lに引いた垂線の足となる点を計算する
inline P perf(const L& l, const P& p) {
	L m = {l.pos - p, l.dir};
	return (p + (m.pos - proj(m.pos, m.dir)));
}
double sp_distance(const L& s, const P& p) {
    const P r = perf(s, p);
    const double pos = ((r-s.pos)/s.dir).real();
    if (-EPS <= pos && pos <= 1 + EPS)
        return abs(r - p);
    return min(abs(s.pos - p),
               abs(s.pos+s.dir - p));
}
int n;
vector<L> l;
vector< vector<pii> > g;

vector<int> used, ans;
void check(int i, vector<pii> &ret){
	if(used[i]) return ;
	used[i] = 1;
	int sum = 0;
	FOR(v, g[i]){
		sum += v->second;
		check(v->first, ret);
	}
	ret.push_back(pii(sum, i));
}
void check(int i){
	vector<pii> ret;
	if(used[i]) return ;
	else check(i, ret);
	sort(RALL(ret));
	if(ret[0].first == 0) ans[1] ++;
	else if(ret[0].first == 11) ans[9] ++;
	else if(ret[1].first == 12) ans[8] ++;
	else if(ret[0].first+ret[1].first == 12) ans[4] ++;
	else if(ret[0].first+ret[1].first == 3) ans[7] ++;
	else if(ret[0].first+ret[1].first == 13) ans[3] ++;
	else if(ret[0].first+ret[1].first == 14) ans[6] ++;
	else if(ret.size() == 4) ans[0] ++;
	else{
		L u = l[ret[4].second];
		L v = l[g[ret[4].second][0].first];
		P p1 = u.pos, p2 = u.pos+u.dir;
		P q1 = v.pos, q2 = v.pos+v.dir;
		if(signum(norm(p1 - q1)) == 0){
			swap(p1, p2);
		}
		if(signum(norm(p2 - q2)) == 0){
			swap(q1, q2);
		}
		if(signum(norm(p1 - q2)) == 0){
			swap(p1, p2);
			swap(q1, q2);
		}
		if(ccw(p1, p2, q2) == -1) ans[2] ++;
		else if(ccw(p1, p2, q2) == 1) ans[5] ++;
		else{
			cerr << "unknown: " << ret << endl;
		}
	}
//	cout << ret << " -> " << ans << endl;
}

/*
1 0
7 2 1 1
0 2 2 2 2
2 2 2 2 1 1
5 2 2 2 1 1
4 10 2 1
9 11 2 2 2
3 12 1 1 1
6 12 2 2 2 1
8 12 12 2 2 2

*/

bool samep(P p, P q){
	return !signum(norm(p-q));
}

main(){
	int i,j;
	while(cin >> n, n){
		l.clear();
		g = vector< vector<pii> >(n);
		REP(i, n){
			int x,y,z,w;
			cin >> x >> y >> z >> w;
			l.push_back((L){P(x, y), P(z-x, w-y)});
		}
		REP(i, n)REP(j, i){
			if(samep(l[i].pos, l[j].pos) || samep(l[i].pos+l[i].dir, l[j].pos+l[j].dir) ||
			   samep(l[i].pos+l[i].dir, l[j].pos) || samep(l[i].pos, l[j].pos+l[j].dir)){
				g[i].push_back(pii(j, 1));
				g[j].push_back(pii(i, 1));
			}else if(!signum(sp_distance(l[j], l[i].pos)) || 
					 !signum(sp_distance(l[j], l[i].pos+l[i].dir))){
				g[i].push_back(pii(j, 1));
				g[j].push_back(pii(i, 10));
			}else if(!signum(sp_distance(l[i], l[j].pos)) || 
					 !signum(sp_distance(l[i], l[j].pos+l[j].dir))){
				g[i].push_back(pii(j, 10));
				g[j].push_back(pii(i, 1));
			}
		}
		ans = vector<int>(10);
		used = vector<int>(n);
		REP(i, n) check(i);
		cout << ans << endl;
	}
	return 0;
}

Measured memory_bytes: 1368