#include <cstdio>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>

using namespace std;

#define EPS (1e-10)
#define EQ(a,b) (abs((a) - (b)) < EPS)
#define EQV(a,b) (EQ((a).real(),(b).real()) && EQ((a).imag(),(b).imag()))

typedef complex<double> P;
typedef pair<P,P> Edge;
typedef long long ll;

const double PI=4*atan(1.0);
const int MAX_SIZE = 10000;

// 内積
double dot(P a, P b) {
  return (a.real() * b.real() + a.imag() * b.imag());
}
// 外積
double cross(P a, P b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}
// 点cが直線ab上にあるかないか
int is_point_on_line(P a, P b, P c) {
  return EQ( cross(b-a, c-a), 0.0 );
}
// 2直線の直行判定
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ( dot(a1-a2, b1-b2), 0.0 );
}
// 2直線の平行判定
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ( cross(a1-a2, b1-b2), 0.0 );
}
// 点a,bを通る直線と点cの間の距離
double distance_l_p(P a, P b, P c) {
  return abs(cross(b-a, c-a)) / abs(b-a);
}
// 点a,bを端点とする線分と点cとの距離
double distance_ls_p(P a, P b, P c) {
  if ( dot(b-a, c-a) < EPS ) return abs(c-a);
  if ( dot(a-b, c-b) < EPS ) return abs(c-b);
  return abs(cross(b-a, c-a)) / abs(b-a);
}

int n;
P lines[1001][2];
bool passed[1001];

class Point{
public:
  P p;
  bool operator<(const Point &o)const{
    if(EQ(p.real(),o.p.real())){
      if(EQ(p.imag(),o.p.imag()))return false;
      else return p.imag()<o.p.imag();
    }
    return p.real()<o.p.real();
  }
  Point(P _p){
    p=_p;
  }
  Point(){}
};
set<Point> tp;
set<Point> cp;

void dfs(int now,int &connect,int &touch
	 ,int &lineCnt,vector<P> &tmp,bool fst,int prv){
  lineCnt++;
  passed[now]=true;
  bool isMove=false;
  bool used[2];
  used[0]=used[1]=false;
  // どちらの端点を見るか
  for(int j=0;j<2;j++){
    for(int i=0;i<n;i++){
      if(i==prv||i==now)continue;
      // 交点を持つ線分に移動
      for(int k=0;k<2;k++){
	if(EQV(lines[now][j],lines[i][k])){
	  //connect++;
	  cp.insert(Point(lines[i][k]));
	  if(!passed[i]){
	    dfs(i,connect,touch,lineCnt,tmp,false,now);
	    isMove=true;
	  }
	}
      }
      if(EQ(distance_ls_p(lines[i][0],lines[i][1],
			  lines[now][j]),0)
	 &&!EQV(lines[i][0],lines[now][j])
	 &&!EQV(lines[i][1],lines[now][j])){
	tp.insert(Point(lines[now][j]));
	//touch++;
	if(!passed[i]){
	  dfs(i,connect,touch,lineCnt,tmp,false,now);
	  isMove=true;
	}
      }
    }
  }
  for(int i=0;i<n;i++){
    if(i==now||i==prv)continue;
    for(int j=0;j<2;j++){
      if(EQ(distance_ls_p(lines[now][0],lines[now][1],
			  lines[i][j]),0)
	 &&!EQV(lines[now][0],lines[i][j])
	 &&!EQV(lines[now][1],lines[i][j])){
	tp.insert(Point(lines[i][j]));
	//touch++;
	if(!passed[i]){
	  dfs(i,connect,touch,lineCnt,tmp,false,now);
	  isMove=true;
	}
      }
    }
  }
  
  // これ以上動くことができないならば,
  if(!isMove&&prv!=-1){
    tmp.clear();
    // for(int i=0;i<2;i++)
    //   cout<<lines[now][i]<<" ";
    // cout<<endl;
    // for(int i=0;i<2;i++)
    //   cout<<lines[prv][i]<<" ";
    // cout<<endl;
    // cout<<endl;
    if(EQV(lines[now][0],lines[prv][0])){
      tmp.push_back(lines[now][1]);
      tmp.push_back(lines[now][0]);
      tmp.push_back(lines[prv][1]);
    }
    else if(EQV(lines[now][1],lines[prv][0])){
      tmp.push_back(lines[now][0]);
      tmp.push_back(lines[now][1]);
      tmp.push_back(lines[prv][1]);
    }
    if(EQV(lines[now][0],lines[prv][1])){
      tmp.push_back(lines[now][1]);
      tmp.push_back(lines[now][0]);
      tmp.push_back(lines[prv][0]);
    }
    else if(EQV(lines[now][1],lines[prv][1])){
      tmp.push_back(lines[now][0]);
      tmp.push_back(lines[now][1]);
      tmp.push_back(lines[prv][0]);
    }
  }
}

int main(){
  while(cin>>n&&n){
    for(int i=0;i<n;i++){
      int x1,x2,y1,y2;
      cin>>x1>>y1>>x2>>y2;
      lines[i][0]=P(x1,y1);
      lines[i][1]=P(x2,y2);
    }
    int ans[11];
    memset(ans,0,sizeof(ans));
    memset(passed,0,sizeof(passed));
    for(int i=0;i<n;i++){
      if(passed[i])continue;
      int connect=0;
      int touch=0;
      int lineCnt=0;
      vector<P> tmp;
      tp.clear();
      cp.clear();
      dfs(i,connect,touch,lineCnt,tmp,true,-1);
      connect=cp.size();
      touch=tp.size();
      //cout<<lineCnt<<" "<<connect<<" "<<touch<<endl;
      if(lineCnt==1)ans[1]++;
      else if(lineCnt==3){
	if(connect==2)ans[7]++;
	else ans[4]++;
      }
      else if(lineCnt==4){
	if(connect==4)
	  ans[0]++;
	else if(connect==2&&touch==1)
	  ans[3]++;
	else if(connect==3)
	  ans[9]++;
      }
      else{
	if(connect==4&&touch==2)
	  ans[8]++;
	else if(connect==4&&touch==1)
	  ans[6]++;
	else{
	  // for(int i=0;i<3;i++)
	  //   cout<<tmp[i]<<" ";
	  // cout<<endl;
	  // cout<<tmp[0]-tmp[1]<<endl;
	  // cout<<tmp[2]-tmp[1]<<endl;
	  if(cross(tmp[0]-tmp[1],tmp[2]-tmp[1])<0)
	    ans[5]++;
	  else
	    ans[2]++;
	}
      }
    }
    for(int i=0;i<10;i++){
      cout<<ans[i];
      if(i==9)cout<<endl;
      else cout<<" ";
    }
  }

  return 0;
}

Measured memory_bytes: 968