#include<iostream>
#include<vector>
#include<map>
#include<set>

using namespace std;

typedef pair<int,int> vert;
typedef pair<vert,vert> edge;

#define make_edge(a,b) (a)<(b)?make_pair((a),(b)):make_pair((b),(a))
#define foreach(it,o) for(__typeof((o).begin()) it=(o).begin(); it != (o).end(); ++it)
const int MAXP = 16;
enum CCW{BACK,FRONT,OVER,LEFT,RIGHT};

int last_ccw;
map<vert, set<vert> > G;

inline int cross(const vert &a, const vert &b)
{
  return a.first * b.second - a.second * b.first;
}

inline int dot(const vert &a, const vert &b)
{
  return a.first * b.first + a.second * b.second;
}

inline int lenv(const vert &a){
  return dot(a,a);
}



inline int ccw(vert a, vert b, vert c)
{
  b.first -= a.first;
  b.second -= a.second;
  c.first -= a.first;
  c.second -= a.second;

  int cr = cross(b,c);
  if( cr ==0 && dot(b,c) < 0 ) return BACK;
  if( cr == 0 && lenv(b)<lenv(c) ) return FRONT;
  if( cr == 0 ) return OVER;
  if( cr > 0 ) return LEFT;
  if( cr < 0 ) return RIGHT;
}

void check(vert cur,
           set<vert> &v, // vertex
           vert path[], int depth){
  foreach(it,G[cur]){
    if( v.find(*it) == v.end() ){
      v.insert(*it);
      path[depth] = *it;
      if( depth >= 2 && last_ccw == -1 ){
        last_ccw = ccw(path[depth-2], path[depth-1], path[depth]);
      }
      check(*it,v,path,depth+1);
    }
  }
  return ;
}

int check_over(const set<edge> &E,
                const set<vert> &v){
  int ret = 0;
  vector<vert> _v;
  foreach(it,v)_v.push_back(*it);
  
  for(int i = 0; i < (int)_v.size(); ++i){
    for(int j = i+1; j < (int)_v.size(); ++j){
      edge e = make_edge(_v[i],_v[j]);
      if( E.find(e) != E.end() ){
        foreach(it,v){
          if( e.first != *it && e.second != *it ){
            if( ccw(e.first,e.second,*it) == OVER ) ++ret;
          }
        }
      }
    }
  }
  return ret;
}

int count_edge(const set<edge> &E,
               const set<vert> &v){
  vector<vert > _v;
  foreach(it,v)_v.push_back(*it);
  int ret = 0;
  
  for(int i = 0; i < (int)_v.size(); ++i){
    for(int j = i+1; j < (int)_v.size(); ++j){
      edge e = make_edge(_v[i],_v[j]);
      if( E.find(e) != E.end() ){
        ++ret;
      }
    }
  }
  return ret;
}

int main()
{
  int n;
  while(cin>>n){
    if( n == 0 ) break;

    int res[10] = {0,};

    G.clear();
    set<vert> V;
    set<edge> E;
    for(int i = 0; i < n; ++i){
      int x,y,s,t;
      cin >> x >> y >> s >> t;
      vert P1(x,y);
      vert P2(s,t);
      V.insert(P1);
      V.insert(P2);
      G[P1].insert(P2);
      G[P2].insert(P1);
      E.insert(make_edge(P1,P2));
    }

    foreach(it,E){
      foreach(itt,V){
        if( it->first != *itt && it->second != *itt ){
          if( ccw( it->first,it->second, *itt)==OVER ){
            G[*itt].insert(it->first);
            G[*itt].insert(it->second);
            G[it->first].insert(*itt);
            G[it->second].insert(*itt);
          }
        }
      }
    }

    set<vert> vis;
    bool reset = false;
    foreach(it,G){
      if(reset){it=G.begin();reset=false;}
      if( vis.find(it->first) == vis.end() ){
        vis.insert(it->first);
        int len;
        set<vert> v;
        vert path[MAXP];
        
        for(int i = 0; i < MAXP; ++i) path[i] = make_pair(-1,-1);
        path[0] = it->first;
        v.insert(it->first);
        check( it->first, v, path, 1 );
        foreach( itt, v ) vis.insert(*itt);
        for(int i = 0; i < MAXP; ++i) if( path[i].first < 0 ){ len = i; break; }
        
        if( v.size() == 2 ){ // 1
          res[1]++;
        }else if( v.size() == 4 ){ // 0,7
          if( count_edge(E,v) == 4 ) res[0]++;
          else res[7]++;
        }else if( v.size() == 5 ){ // 4, 9
          if( count_edge(E,v) == 3 ) res[4]++;
          else res[9]++;
        }else if( v.size() == 6 ){
          int co = check_over(E,v);
          if( co ){ //3,6,8
            if( count_edge(E,v) == 4 ) res[3]++;
            else {
              if(co==2)res[8]++;
              else res[6]++;
            }
          }else{ // 2,5
            set<vert> tv;
            path[0]=path[len-1];
            tv.insert(path[len-1]);
            last_ccw= -1;
            check(path[len-1],tv,path,1);

            if( last_ccw == RIGHT ) res[2]++;
            else res[5]++;
          }
        }

        /* debug 
        cout << v.size() << endl;
        for(int i = 0; i < 8; ++i){
          cout << path[i].first << ' ' << path[i].second << endl;
        }
        cout << "-"<<endl;
        */

        reset = true;
      }
    }
    // cout << "---" << endl;

    for(int i = 0; i < 10; ++i){
      if( i ) cout << ' ';
      cout << res[i];
    }
    cout << endl;
    

  }
  return 0;
}

Measured memory_bytes: 1160