#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>

using namespace std;
const double EPS = 1e-8;

struct Point {
	double x, y;
	Point() : x(0), y(0) { }
	Point(double x, double y) : x(x), y(y) { }
	Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
	Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
	Point operator*(double s) const { return Point(x * s, y * s); }
	Point operator/(double s) const { return Point(x / s, y / s); }
	Point &operator+=(const Point &p){ x += p.x; y += p.y; return *this; }
	Point &operator-=(const Point &p){ x -= p.x; y -= p.y; return *this; }
	Point &operator*=(double s){ x *= s; y *= s; return *this; }
	Point &operator/=(double s){ x /= s; y /= s; return *this; }
	bool operator==(const Point &p) const { return x == p.x && y == p.y; }
	bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
	bool operator<(const Point &p) const {
		return (x == p.x) ? (y < p.y) : (x < p.x);
	}
};
inline Point operator*(double s, const Point &p){ return p * s; }

inline double norm(const Point &p){ return p.x * p.x + p.y * p.y; }
inline double abs(const Point &p){ return sqrt(norm(p)); }
inline Point unit(const Point &p){ return p / abs(p); }
inline Point ortho(const Point &p){ return Point(-p.y, p.x); }
inline double cross(const Point &a, const Point &b){
	return a.x * b.y - a.y * b.x;
}
inline double dot(const Point &a, const Point &b){
	return a.x * b.x + a.y * b.y;
}
inline int ccw(const Point &a, const Point &b, const Point &c){
	const Point d = b - a, e = c - a;
	if(cross(d, e) > 0.0){ return 1; }
	if(cross(d, e) < 0.0){ return -1; }
	if(dot(d, e) < 0.0){ return 2; }
	if(abs(d) < abs(e)){ return -2; }
	return 0;
}

struct Line {
	Point a, b;
	Line() : a(), b() { }
	Line(const Point &a, const Point &b) : a(a), b(b) { }
	bool operator==(const Line &l) const { return a == l.a && b == l.b; }
	bool operator!=(const Line &l) const { return a != l.a || b != l.b; }
	bool operator<(const Line &l) const {
		return (a == l.a) ? (b < l.b) : (a < l.a);
	}
};

struct Segment : public Line {
	Segment() : Line() { }
	Segment(const Point &a, const Point &b) : Line(a, b) { }
};

int main(){
	ios_base::sync_with_stdio(false);
	map< vector<int>, int > table;
	const int TABLE0[] = { 2, 2, 2, 2 };
	const int TABLE1[] = { 0 };
	const int TABLE2[] = { 1, 1, 2, 2, 2 };
	const int TABLE3[] = { 1, 1, 1, 12 };
	const int TABLE4[] = { 1, 2, 10 };
	const int TABLE6[] = { 1, 2, 2, 2, 12 };
	const int TABLE7[] = { 1, 1, 2 };
	const int TABLE8[] = { 2, 2, 2, 12, 12 };
	const int TABLE9[] = { 2, 2, 2, 11 };
	table.insert(make_pair(vector<int>(TABLE0, TABLE0 + 4), 0));
	table.insert(make_pair(vector<int>(TABLE1, TABLE1 + 1), 1));
	table.insert(make_pair(vector<int>(TABLE2, TABLE2 + 5), 2));
	table.insert(make_pair(vector<int>(TABLE3, TABLE3 + 4), 3));
	table.insert(make_pair(vector<int>(TABLE4, TABLE4 + 3), 4));
	table.insert(make_pair(vector<int>(TABLE6, TABLE6 + 5), 6));
	table.insert(make_pair(vector<int>(TABLE7, TABLE7 + 3), 7));
	table.insert(make_pair(vector<int>(TABLE8, TABLE8 + 5), 8));
	table.insert(make_pair(vector<int>(TABLE9, TABLE9 + 4), 9));
	while(true){
		int n;
		cin >> n;
		if(n == 0){ break; }
		vector<Segment> segments(n);
		for(int i = 0; i < n; ++i){
			Segment &s = segments[i];
			cin >> s.a.x >> s.a.y >> s.b.x >> s.b.y;
		}
		vector< vector<int> > conn(n);
		vector<int> score(n);
		for(int i = 0; i < n; ++i){
			const Segment &s = segments[i];
			for(int j = 0; j < n; ++j){
				if(i == j){ continue; }
				const Segment &t = segments[j];
				if(s.a == t.a || s.a == t.b || s.b == t.a || s.b == t.b){
					conn[i].push_back(j);
					score[i] += 1;
				}else if(ccw(s.a, s.b, t.a) == 0 || ccw(s.a, s.b, t.b) == 0){
					conn[i].push_back(j);
					conn[j].push_back(i);
					score[i] += 10;
					score[j] += 1;
				}
			}
		}
		vector<int> answer(10);
		vector<int> vis(n);
		for(int i = 0; i < n; ++i){
			if(vis[i]){ continue; }
			queue<int> q;
			q.push(i);
			vis[i] = 1;
			vector<int> t;
			int edge = -1;
			while(!q.empty()){
				const int u = q.front();
				q.pop();
				t.push_back(score[u]);
				if(score[u] == 1){ edge = u; }
				for(int j = 0; j < conn[u].size(); ++j){
					const int v = conn[u][j];
					if(vis[v]){ continue; }
					vis[v] = 1;
					q.push(v);
				}
			}
			sort(t.begin(), t.end());
			int x = table[t];
			if(x == 2){
				Segment a = segments[edge];
				Segment b = segments[conn[edge][0]];
				if(a.a == b.a){
					swap(a.a, a.b);
				}else if(a.a == b.b){
					swap(a.a, a.b);
					swap(b.a, b.b);
				}else if(a.b == b.b){
					swap(b.a, b.b);
				}
				if(ccw(a.a, a.b, b.b) > 0){ x = 5; }
			}
			++answer[x];
		}
		for(int i = 0; i < 10; ++i){
			if(i != 0){ cout << " "; }
			cout << answer[i];
		}
		cout << endl;
	}
	return 0;
}

Measured memory_bytes: 1356