#include <bits/stdc++.h>
 
#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)
 
#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)
 
#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(arg),key)-begin(arg)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
 
using namespace std;
 
template<class T>void reg(vector<T> &ary,const T &elem){ary.emplace_back(elem);}
template<class T>bool chmin(T &a, const T &b) {return (b<a)?(a=b,1):0;}
template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
 
using R=long double; // __float128
const R EPS = 1E-11; // [-1000:1000]->EPS=1e-8 [-10000:10000]->EPS=1e-7
const R INF = 1E40;
constexpr R PI = acos(R(-1));
inline int sgn(const R& r){ return (r > EPS) - (r < -EPS);}
inline int sgn(const R& a, const R &b){ return sgn(a-b); }
inline R sq(R x){return sqrt(max<R>(x,0.0));}
 
using P=complex<R>;
using VP=vector<P>;
using L=struct{P s,t;};
using VL=vector<L>;
using C=struct{P c;R r;};
using VC=vector<C>;
using vi=vector<int>;
 
constexpr P O = P(0,0);
istream& operator >> (istream& is,P& p){ R x,y;is >> x >> y; p=P(x,y); return is;}
ostream& operator << (ostream& os,P& p){ os << real(p) << " " << imag(p); return os;}
 
namespace std{
    bool operator <  (const P& a,const P& b){ return sgn(real(a-b))?real(a-b)<0:sgn(imag(a-b))<0;}
    bool operator == (const P& a,const P& b){ return sgn(real(a-b))==0 && sgn(imag(a-b))==0;}
}
 
inline bool cmp_x(const P& p,const P& q){return sgn(real(p-q))?real(p)<real(q):sgn(imag(p-q));}
inline bool cmp_y(const P& a, const P& b){return sgn(imag(a-b)) ? imag(a-b)<0 : sgn(real(a-b))<0;}
inline bool cmp_a(const P& a, const P& b){return sgn(arg(a)-arg(b)) ? arg(a)-arg(b)<0 : sgn(norm(a)-norm(b))<0;}
bool operator <  (const L& a,const L& b){ return a.s==b.s?a.t<b.t:a.s<b.s;}
bool operator == (const L& a,const L& b){ return a.s==b.s&&a.t==b.t;}
 
//?????? dot ?????? det
inline R dot(P o,P a,P b){a-=o,b-=o; return real(conj(a)*b);}
inline R det(P o,P a,P b){a-=o,b-=o; return imag(conj(a)*b);}
inline P vec(L l){return l.t-l.s;}
 
// ?°???± verify AOJ CGL_1_A
P proj(P o,P a,P b){ a-=o,b-=o; return a*real(b/a);}
P proj(L l,P p){l.t-=l.s,p-=l.s;return l.s+l.t*real(p/l.t);}
// ????°? verify AOJ CGL_1_B
P refl(L l,P p){ return R(2.0)*proj(l,p)-p;}
// CCW verify AOJ CGL_1_C
enum CCW{ LEFT = 1,RIGHT = 2,BACK = 4,FRONT = 8,ON = 16};
inline int ccw(P o,P a, P b) {//???a??¨???b???????????????????????????
    if (sgn(det(o,a,b)) > 0) return LEFT;    // counter clockwise
    if (sgn(det(o,a,b)) < 0) return RIGHT;   // clockwise
    if (sgn(dot(o,a,b)) < 0) return BACK;    // b--base--a on line
    if (sgn(norm(a-o)-norm(b-o)) < 0) return FRONT;   // base--a--b on line
    return ON;// base--b--a on line  a??¨b????????????????????????
}
 
// ?????´ ?????? verify AOJ CGL_2_A
bool vertical(L a, L b) {return sgn(dot(O,vec(a),vec(b)))==0;}
bool parallel(L a, L b) {return sgn(det(O,vec(a),vec(b)))==0;}

// ???????????????verify AOJ CGL_2_B ???????????????????????´??????1,????????´??????0
bool ill(L a,L b){ return parallel(a,b)==false;}
bool ils(L l,L s,int end=0){ return sgn(det(l.s,l.t,s.s)*det(l.s,l.t,s.t))<=-end;}
bool iss(L a,L b,int end=0){
    int s1=ccw(a.s,a.t,b.s)|ccw(a.s,a.t,b.t);
    int s2=ccw(b.s,b.t,a.s)|ccw(b.s,b.t,a.t);
    if(end) return (s1&s2)==(LEFT|RIGHT);
    return (s1|s2)&ON || (s1&s2)==(LEFT|RIGHT);
}

R dsp(L s,P p){
    if(sgn(dot(s.s,s.t,p))<=0) return abs(p-s.s);
    if(sgn(dot(s.t,s.s,p))<=0) return abs(p-s.t);
    return abs(det(s.s,s.t,p))/abs(s.t-s.s);
}

struct UnionFind {
    vector<int> data;
    UnionFind(int size) : data(size, -1) { }
    bool unionSet(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool findSet(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};

inline bool share(L& a, L& b){
    return (a.s == b.s or a.s == b.t or a.t == b.s or a.t == b.t);
}

int check(VL& ls){
    int n = ls.size();

    if(n == 1) return 1;
    if(n == 3 or n == 4){
        int cnt = 0;
        rep(i, n){
            rep(j, i + 1, n){
                if(share(ls[i], ls[j])){
                    cnt++;
                }
            }
        }
        if(n == 3){
            if(cnt == 1) return 4;
            else if(cnt == 2) return 7;
            else assert(false);
        }
        if(n == 4){
            if(cnt == 2) return 3;
            else if(cnt == 3) return 9;
            else if(cnt == 4) return 0;
            else assert(false);
        }
    }
    if(n == 5){
        rep(i, n){
            bool ok = false;
            rep(j, n){
                if(j == i) continue;
                if(share(ls[i], ls[j])){
                    ok = true;
                    break;
                }
            }
            if(not ok) return 8;
        }

        P s;
        [&]{
            rep(i, n){
                for(P p : {ls[i].s, ls[i].t}){
                    bool ok = true;
                    rep(j, n){
                        if(j == i) continue;
                        if(dsp(ls[j], p) < EPS){
                            ok = false;
                            break;
                        }
                    }
                    if(ok){
                        s = p;
                        return;
                    }
                }
            }
        }();

        VP ps = {s};
        vi used(n);
        rep(loop, n){
            rep(i, n){
                if(used[i]) continue;
                if(ls[i].s == ps.back()){
                    ps.emplace_back(ls[i].t);
                    used[i] = true;
                    break;
                }
                if(ls[i].t == ps.back()){
                    ps.emplace_back(ls[i].s);
                    used[i] = true;
                    break;
                }
            }
        }
        vi dirs(4);
        rep(i, 4){
            dirs[i] = sgn(det(O, ps[i + 1] - ps[i], ps[i + 2] - ps[i + 1]));
        }
        if(dirs[0] == dirs[1] and dirs[1] == dirs[2] and dirs[2] == dirs[3]){
            return 6;
        }
        if(dirs[0] == 1 and dirs[1] == 1 and dirs[2] == -1 and dirs[3] == -1){
            return 5;
        }
        if(dirs[0] == -1 and dirs[1] == -1 and dirs[2] == 1 and dirs[3] == 1){
            return 2;
        }
        assert(false);
    }

    assert(false);
}

int main(void){
    cin.tie(0);
    ios::sync_with_stdio(false);

    for(int n; cin >> n, n;){
        VL ls(n);
        for(auto& e : ls) cin >> e.s >> e.t;

        UnionFind uf(n);
        rep(i, n){
            rep(j, i + 1, n){
                if(iss(ls[i], ls[j])){
                    uf.unionSet(i, j);
                }
            }
        }

        vi used(n);
        vi res(10);
        rep(i, n){
            if(used[i]) continue;

            VL cur;
            rep(j, i, n){
                if(uf.findSet(i, j)){
                    cur.emplace_back(ls[j]);
                    used[j] = true;
                }
            }

            res[check(cur)]++;
        }

        rep(i, 10){
            cout << (i ? " ":"") << res[i];
        }
        cout << endl;
    }

    return 0;
}

Measured memory_bytes: 3348