#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;

const double EPS = 1e-8;

typedef complex<int> Point;
struct Line : public vector<Point> {
    Line() {}
    Line(Point a, Point b){
        push_back(a);
        push_back(b);
    }
    Point vector() const {
        return back() - front();
    }
};

double dot(Point a, Point b){
    return a.real() * b.real() + a.imag() * b.imag();
}
double cross(Point a, Point b){
    return a.real() * b.imag() - a.imag() * b.real();
}

bool intersectSP(Line s, Point p) {
    Point b = s.vector(), c = p - s[0];
    return cross(b, c) == 0 && dot(b, c) > 0 && norm(c) < norm(b);
}
int get_number(vector<Line>& lv){
    int n = lv.size();

    /*
    vector<int> compv;
    REP(i, n) REP(j, 2) {
        compv.push_back(lv[i][j].real());
        compv.push_back(lv[i][j].imag());
    }
    sort(compv.begin(), compv.end());
    compv.erase(unique(compv.begin(), compv.end()), compv.end());
    map<int, int> comp;
    REP(i, compv.size()) comp[ compv[i] ] = i;
    */

    vector<Point> vp;
    REP(i, n){
        vp.push_back(lv[i][0]);
        vp.push_back(lv[i][1]);
    }
    int cnt1 = 0, cnt2 = 0; // cnt1 - point, cnt2 - midpoint
    REP(i, vp.size()){
        bool unique = true;
        REP(j, i){
            if(vp[i] == vp[j]) unique = false;
        }
        if(!unique) continue;

        cnt1++;
        bool midpoint = false;
        REP(j, n) if(intersectSP(lv[j], vp[i])){
            midpoint = true;
        }
        if(midpoint) cnt2++;
    }
    if(n == 1) return 1;
    if(n == 3 && cnt1 == 4) return 7;
    if(n == 3 && cnt1 == 5) return 4;
    if(n == 4 && cnt1 == 4) return 0;
    if(n == 4 && cnt1 == 5) return 9;
    if(n == 4 && cnt2 == 1) return 3;
    if(n == 5 && cnt2 == 1) return 6;
    if(n == 5 && cnt2 == 2) return 8;
    // 2 or 5 ? 
    assert(n == 5);
    assert(cnt1 == 6);
    assert(cnt2 == 0);
    Line l1, l2;
    REP(i, n) {
        bool f1 = false, f2 = false;
        int cj = 0;
        REP(j, n) REP(k, 2) if(i != j && lv[i][0] == lv[j][k]) f1 = true, cj = j;
        REP(j, n) REP(k, 2) if(i != j && lv[i][1] == lv[j][k]) f2 = true, cj = j;
        if(!f1 || !f2) {
            l1 = lv[i];
            l2 = lv[cj];
            if(f1) swap(l1[0], l1[1]);
            if(l1[1] == l2[1]) swap(l2[0], l2[1]);
            if(cross(l1.vector(), l2[1] - l1[0]) > 0) {
                return 5;
            }else{
                return 2;
            }
        }
    }
    assert(false);
}

int main(){
    int n;
    while(cin >> n && n){
        vector<Line> lv(n);
        REP(i, n){
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            lv[i] = Line(Point(x1, y1), Point(x2, y2));
        }

        bool connect[1000][1000] = {};
        REP(i, n) connect[i][i] = true;
        REP(i, n) REP(j, n){
            bool c = false;
            REP(ki, 2) REP(kj, 2) {
                if(lv[i][ki] == lv[j][kj]) c = true;
                if(intersectSP(lv[i], lv[j][kj])) c = true;
                if(intersectSP(lv[j], lv[i][ki])) c = true;
            }
            connect[i][j] = c;
        }

        REP(k, n) REP(i, n) REP(j, n)
            if(connect[i][k] && connect[k][j])
                connect[i][j] = true;

        bool used[1000] = {};
        int ans[10] = {};
        REP(i, n) if(!used[i]){
            vector<Line> local_lv;
            REP(j, n) if(connect[i][j]) {
                used[j] = true;
                local_lv.push_back(lv[j]);
            }
            ans[ get_number(local_lv) ]++;
        }

        REP(i, 10){
            cout << ans[i];
            if(i == 9) cout << endl;
            else cout << " ";
        }
    }
    return 0;
}

Measured memory_bytes: 2240