Language: C++

#include<iostream>
#include<complex>
#include<csdtlib>
#include<vector>
#include<cmath>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define pb         push_back

typedef complex<int> P;

const double eps = 1e-10;

namespace std{
  bool operator==(const P &a,const P &b){
    return a.real()==b.real() && a.imag()==b.imag();
  }
}

class DisjointSet{
public:
  vector<int> rank,p;
  DisjointSet(){}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
  }

  void makeset(int x){
    p[x]=x;
    rank[x]=0;
  }
  void merge(int x,int y){
    link(findset(x),findset(y));
  }
  void link(int x,int y){
    if ( rank[x] > rank[y]){
      p[y]=x;      
    }else {
      p[x]=y;
      if ( rank[x] == rank[y])rank[y]++;
    }
  }
  int findset(int x){
    if ( x != p[x])p[x] = findset(p[x]);
    return p[x];
  }
  
};

class Line{
public:
  P d[2];
  vector<P> mid;
  int cp[2];//connection Line
  vector<int> cm;
  Line(){
    cp[0]=-1;cp[1]=-1;cm.clear();
  }
  void clear(){
    cp[0]=-1;
    cp[1]=-1;
    cm.clear();
    mid.clear(); 
  }
};

double myabs(P a){
  return sqrt((double)a.real()*a.real()+a.imag()*a.imag());
}

bool isp(P a,P b,P c){
  return myabs(a-c)+myabs(b-c) < myabs(a-b) + eps;
}

vector<int> in[1000];

void output(int me,Line *inp){
  cout <<"output begin"<<endl;
  
  //  visualize
  rep(i,in[me].size()){
    cout << "[" <<inp[in[me][i]].d[0]<<"," <<inp[in[me][i]].d[1] << "],"<<endl;
  }
  cout << endl;
  
  /*
  rep(i,in[me].size()){
    cout <<in[me][i] << endl;
    cout << inp[in[me][i]].d[0] << " " << inp[in[me][i]].d[1] <<endl;
    cout << inp[in[me][i]].cp[0] <<" " << inp[in[me][i]].cp[1] << endl;
    cout << inp[in[me][i]].mid.size() <<endl;
    cout << endl;
  }
  cout << endl;
  */  
}

int cross(P a,P b){
  return a.real()*b.imag()-a.imag()*b.real();
}

#define RIGHT 0
#define LEFT  1
int ccw(P a,P b){
  if (cross(a,b) < -1)return RIGHT;
  else return LEFT;
}

bool iszero(int me,Line *inp){
  if (in[me].size() != 4)return false;
  if (inp[in[me][0]].cp[0] != -1 && inp[in[me][0]].cp[1] != -1 &&
      inp[in[me][0]].mid.size() == 0){
    int tar[4]={inp[in[me][0]].cp[0],inp[in[me][0]].cp[1]};
    tar[2]=-1;tar[3]=-1;
    rep(i,2){
      if (inp[tar[i]].cp[0] == -1||inp[tar[i]].cp[1] == -1||
	  inp[tar[i]].mid.size() != 0)return false;
      if (inp[tar[i]].cp[0] != in[me][0])tar[2+i]=inp[tar[i]].cp[0];
      else tar[2+i]=inp[tar[i]].cp[1];
    }
    if (tar[2] != -1 && tar[2] == tar[3] &&
	inp[tar[2]].cp[0]!=-1 && inp[tar[2]].cp[1] != -1 && 
	inp[tar[2]].mid.size() == 0)return true;
  }
  return false;
}

bool isone(int me,Line *inp){
  return in[me].size() == 1;
}

bool istwo(int me,Line *inp){
  static int pattern[]={RIGHT,RIGHT,LEFT,LEFT};
  if (in[me].size() != 5)return false;
  int cur=-1,prev=-1;
  rep(i,5){
    if (inp[in[me][i]].mid.size() != 0)return false;
    if (inp[in[me][i]].cp[0]==-1&&inp[in[me][i]].cp[1]!=-1)
      prev=in[me][i],cur=inp[in[me][i]].cp[1];
    else if (inp[in[me][i]].cp[0]!=-1 && inp[in[me][i]].cp[1]==-1){
      prev=in[me][i],cur=inp[in[me][i]].cp[0];
    }
  }
  if (cur ==-1)return false;
  rep(i,4){
    if (inp[cur].d[0]       == inp[prev].d[0]){
      if (ccw(inp[cur].d[0]-inp[prev].d[1],inp[cur].d[1]-inp[prev].d[1]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[1];
    }else if (inp[cur].d[0] == inp[prev].d[1]){
      if (ccw(inp[cur].d[0]-inp[prev].d[0],inp[cur].d[1]-inp[prev].d[0]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[1];
    }else if (inp[cur].d[1] == inp[prev].d[0]){
      if (ccw(inp[cur].d[1]-inp[prev].d[1],inp[cur].d[0]-inp[prev].d[1]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[0];
    }else if (inp[cur].d[1] == inp[prev].d[1]){
      if (ccw(inp[cur].d[1]-inp[prev].d[0],inp[cur].d[0]-inp[prev].d[0]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[0];
    }
  }
  return true;
}

bool isthree(int me,Line *inp){
  if (in[me].size() != 4)return false;
  rep(i,4){
    if (inp[in[me][i]].cp[0] != -1 && inp[in[me][i]].cp[1] != -1 && 
	inp[in[me][i]].mid.size() == 1){
      int tar[3]={inp[in[me][i]].cp[0],inp[in[me][i]].cp[1],
		  inp[in[me][i]].cm[0]};
      int cnt=0;
      rep(j,3){
	if (inp[tar[j]].cp[0] != -1 && inp[tar[j]].cp[1] != -1)return false;
	if (inp[tar[j]].mid.size() != 0)return false;
	if (isp(inp[in[me][i]].d[0],inp[in[me][i]].d[1],inp[tar[j]].d[0])){
	  cnt+=ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],
		   inp[tar[j]].d[1]-inp[in[me][i]].d[0]);
	}else if (isp(inp[in[me][i]].d[0],inp[in[me][i]].d[1],inp[tar[j]].d[1])){ 
	  cnt+=ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],
		   inp[tar[j]].d[0]-inp[in[me][i]].d[0]);
	}
      }
      if (cnt ==0||cnt==3)return true;
      return false;
    }
  }
  return false;
}


bool isfour(int me,Line *inp){
  if (in[me].size() != 3)return false;
  rep(i,3){
    if (inp[in[me][i]].cp[0] == -1 && inp[in[me][i]].cp[1] == -1 && 
	inp[in[me][i]].mid.size() == 1){
      int tar = inp[in[me][i]].cm[0];
      int tar2=-1;
      if (inp[tar].cp[0]==-1 || inp[tar].cp[1] == -1||
	  inp[tar].mid.size() != 0)return false;
      if (inp[tar].cp[0] != in[me][i]){
	tar2=inp[tar].cp[0];
	if (inp[tar2].mid.size() != 0)return false;
	if (inp[tar2].cp[0]!=-1&&inp[tar2].cp[0]!=-1)return false;
	if (inp[tar].d[0] == inp[tar2].d[0]){
	  if (ccw(inp[tar2].d[0]-inp[tar].d[1],inp[tar2].d[1]-inp[tar].d[1])==RIGHT)return true;
	}else if (inp[tar].d[0] == inp[tar2].d[1]){
	  if (ccw(inp[tar2].d[1]-inp[tar].d[1],inp[tar2].d[0]-inp[tar].d[1])==RIGHT)return true;
	}
      }else {
	tar2=inp[tar].cp[1];
	if (inp[tar2].mid.size() != 0)return false;
	if (inp[tar2].cp[0]!=-1&&inp[tar2].cp[1]!=-1)return false;
	if (inp[tar].d[1] == inp[tar2].d[0]){
	  if (ccw(inp[tar2].d[0]-inp[tar].d[0],inp[tar2].d[1]-inp[tar].d[0])==RIGHT)return true;
	}else if (inp[tar].d[1] == inp[tar2].d[1]){
	  if (ccw(inp[tar2].d[1]-inp[tar].d[0],inp[tar2].d[0]-inp[tar].d[0])==RIGHT)return true;
	}
      }    
      return false;
    }
  }
  return false;
}

bool isfive(int me,Line *inp){
  static int pattern[]={LEFT,LEFT,RIGHT,RIGHT};
  if (in[me].size() != 5)return false;
  int cur=-1,prev=-1;
  rep(i,5){
    if (inp[in[me][i]].mid.size() != 0)return false;
    if (inp[in[me][i]].cp[0]==-1&&inp[in[me][i]].cp[1]!=-1)
      prev=in[me][i],cur=inp[in[me][i]].cp[1];
    else if (inp[in[me][i]].cp[0]!=-1 && inp[in[me][i]].cp[1]==-1){
      prev=in[me][i],cur=inp[in[me][i]].cp[0];
    }
  }
  if (cur ==-1 )return false;
  rep(i,4){
    if (inp[cur].d[0]       == inp[prev].d[0]){
      if (ccw(inp[cur].d[0]-inp[prev].d[1],inp[cur].d[1]-inp[prev].d[1]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[1];
    }else if (inp[cur].d[0] == inp[prev].d[1]){
      if (ccw(inp[cur].d[0]-inp[prev].d[0],inp[cur].d[1]-inp[prev].d[0]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[1];
    }else if (inp[cur].d[1] == inp[prev].d[0]){
      if (ccw(inp[cur].d[1]-inp[prev].d[1],inp[cur].d[0]-inp[prev].d[1]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[0];
    }else if (inp[cur].d[1] == inp[prev].d[1]){
      if (ccw(inp[cur].d[1]-inp[prev].d[0],inp[cur].d[0]-inp[prev].d[0]) != pattern[i])return false;
      prev=cur;
      cur=inp[cur].cp[0];
    }
  }
  return true;
}

bool issix(int me,Line *inp){
  if (in[me].size() != 5)return false;
  rep(i,5){
    if (inp[in[me][i]].cp[0] != -1 && inp[in[me][i]].cp[1] != -1 &&
	inp[in[me][i]].mid.size() == 1){
      int tar[5]={inp[in[me][i]].cp[0],inp[in[me][i]].cp[1],inp[in[me][i]].cm[0]};
      int cnt=0;

      if (inp[tar[0]].cp[0]!=-1&&inp[tar[0]].cp[1]!=-1){
	swap(tar[0],tar[1]);
	REP(j,1,3){
	  if (inp[tar[j]].cp[0]==-1||inp[tar[j]].cp[1]==-1||
	      inp[tar[j]].mid.size() != 0)return false;
	  if (inp[tar[j]].cp[0] != in[me][i])tar[2+j]=inp[tar[j]].cp[0];
	  else tar[2+j]=inp[tar[j]].cp[1];
	  
	}

	if (tar[3] != tar[4])return false;
	if (!(inp[tar[3]].cp[0]!=-1&&inp[tar[3]].cp[1]!=-1))return false;
	if (inp[tar[3]].mid.size() != 0)return false;
	if (inp[tar[0]].cp[0]!=-1&&inp[tar[0]].cp[1]!=-1)return false;
	if (inp[tar[0]].mid.size() != 0)return false;
	rep(j,3){
	  if (inp[tar[j]].cp[0] == in[me][i]){
	    if (ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],
		    inp[tar[j]].d[1]-inp[in[me][i]].d[0]) == LEFT)return false;
	  }else if (inp[tar[j]].cp[1] == in[me][i]){
	    if (ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],
		    inp[tar[j]].d[0]  -inp[in[me][i]].d[0])==LEFT)return false;
	  }
	}
	return true;
      }else if (inp[tar[1]].cp[0]!=-1 && inp[tar[1]].cp[1] != -1){
	REP(j,1,3){
	  if (inp[tar[j]].cp[0] == -1 || inp[tar[j]].cp[1] == -1 ||
	      inp[tar[j]].mid.size() != 0)return false;
	  if (inp[tar[j]].cp[0] != in[me][i])tar[2+j]=inp[tar[j]].cp[0];
	  else tar[2+j]=inp[tar[j]].cp[1];
	}
	if (tar[3] != tar[4])return false;
	if (!(inp[tar[3]].cp[0]!=-1&&inp[tar[3]].cp[1]!=-1))return false;
	if (inp[tar[3]].mid.size() != 0)return false;
	if (inp[tar[0]].cp[0]!=-1&&inp[tar[0]].cp[1]!=-1)return false;
	if (inp[tar[0]].mid.size() != 0)return false;
	rep(j,3){
	  if (inp[tar[j]].cp[0] == in[me][i]){
	    if (ccw(inp[in[me][i]].d[0]-inp[in[me][i]].d[1],
		    inp[tar[j]].d[1]  -inp[in[me][i]].d[1]) == LEFT)return false;
	  }else if (inp[tar[j]].cp[1] == in[me][i]){
	    if (ccw(inp[in[me][i]].d[0]-inp[in[me][i]].d[1],
		    inp[tar[j]].d[0]  -inp[in[me][i]].d[1])==LEFT)return false;
	  }
	}
	return true;
      }
      return false;
    }
  }
  return false;
}

bool isseven(int me,Line *inp){//ok??
  if (in[me].size() != 3)return false;
  rep(i,3){
    if (inp[in[me][i]].cp[0] != -1 && inp[in[me][i]].cp[1] != -1 &&
	inp[in[me][i]].mid.size()==0){
      int tar[2]={inp[in[me][i]].cp[0],inp[in[me][i]].cp[1]};
      int cnt=0;
      rep(j,2){
	if (inp[tar[j]].cp[0]!=-1&&inp[tar[j]].cp[1]!=-1)return false;
	if (inp[tar[j]].mid.size()!=0)return false;
	if (inp[tar[j]].cp[0] == -1){
	  cnt+=ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],inp[tar[j]].d[0]-inp[in[me][i]].d[0]);
	}else if (inp[tar[j]].cp[1] == -1){
	  cnt+=ccw(inp[in[me][i]].d[1]-inp[in[me][i]].d[0],inp[tar[j]].d[1]-inp[in[me][i]].d[0]);
	}
      }
      if (cnt==0||cnt==2)return true;
      else return false;
    }
  }
  return false;
}

bool iseight(int me,Line *inp){
  if (in[me].size() != 5)return false;
  rep(i,5){
    if (inp[in[me][i]].cp[0] != -1 && inp[in[me][i]].cp[1] != -1 &&
	inp[in[me][i]].mid.size() == 1){
      int tar[6]={inp[in[me][i]].cp[0],inp[in[me][i]].cp[1],
		  inp[in[me][i]].cm[0]};
      int cnt=0;
      rep(j,3){
	if (inp[tar[j]].cp[0] ==-1 || inp[tar[j]].cp[1] == -1||
	    inp[tar[j]].mid.size() != 0)return false;
	if (inp[tar[j]].cp[0] == in[me][i]){
	  cnt+=ccw(inp[tar[j]].cp[0]-inp[in[me][i]].d[0],inp[tar[j]].cp[1]-inp[in[me][i]].d[0]);
	  tar[3+j]=inp[tar[j]].cp[1];
	}else if (inp[tar[j]].cp[1] == in[me][i]){
	  cnt+=ccw(inp[tar[j]].cp[1]-inp[in[me][i]].d[0],inp[tar[j]].cp[0]-inp[in[me][i]].d[0]);
	  tar[3+j]=inp[tar[j]].cp[0];
	}
      }
      if (tar[3] == tar[4] && tar[4] == tar[5] &&
	  (cnt==3||cnt==0))return true;
      return false;
    }
  }
  return false;
}

bool isnine(int me,Line *inp){
  if (in[me].size() != 4)return false;
  rep(i,4){
    if (inp[in[me][i]].cp[0] == -1 && inp[in[me][i]].cp[1] != -1 &&
	inp[in[me][i]].mid.size() == 1){
      int tar[4]={inp[in[me][i]].cp[1],inp[in[me][i]].cm[0]};
      rep(j,2){
	if (inp[tar[j]].cp[0] == -1 || inp[tar[j]].cp[1] == -1 ||
	    inp[tar[j]].mid.size() != 0)return false;
	if (inp[tar[j]].cp[0] == in[me][i]){
	  if (ccw(inp[tar[j]].d[0]-inp[in[me][i]].d[0],inp[tar[j]].d[1]-inp[in[me][i]].d[0]) == RIGHT)return false;
	  tar[2+j]=inp[tar[j]].cp[1];
	}else if (inp[tar[j]].cp[1] == in[me][i]){
	  if (ccw(inp[tar[j]].d[1]-inp[in[me][i]].d[0],inp[tar[j]].d[0]-inp[in[me][i]].d[0])==RIGHT)return false;
	  tar[2+j]=inp[tar[j]].cp[0];
	}
      }
      if (tar[2] == tar[3])return true;
      return false;
    }else if (inp[in[me][i]].cp[0] != -1 && inp[in[me][i]].cp[1] == -1 &&
	      inp[in[me][i]].mid.size() == 1){
      int tar[4]={inp[in[me][i]].cp[0],inp[in[me][i]].cm[0]};
      rep(j,2){
	if (inp[tar[j]].cp[0] == -1 || inp[tar[j]].cp[1] == -1 ||
	    inp[tar[j]].mid.size() != 0)return false;
	if (inp[tar[j]].cp[0] == in[me][i]){
	  if (ccw(inp[tar[j]].d[0]-inp[in[me][i]].d[1],inp[tar[j]].d[1]-inp[in[me][i]].d[1]) == RIGHT)return false;
	  tar[2+j]=inp[tar[j]].cp[1];
	}else if (inp[tar[j]].cp[1] == in[me][i]){
	  if (ccw(inp[tar[j]].d[1]-inp[in[me][i]].d[1],inp[tar[j]].d[0]-inp[in[me][i]].d[1])==RIGHT)return false;
	  tar[2+j]=inp[tar[j]].cp[0];
	}
      }
      
      if (tar[2] ==tar[3])return true;
      return false;
    }
  }
  return false;
}

void solve(int n,Line *inp){
  DisjointSet dj(n);
  rep(i,n)dj.makeset(i);

  rep(i,n){
    rep(j,n){
      if (i == j)continue;
      rep(k,2){
	rep(l,2){
	  if (inp[i].d[k] == inp[j].d[l]){
	    dj.merge(i,j);
	    inp[i].cp[k]=j;
	  }
	}
      }
      
      rep(l,2){
	if (isp(inp[i].d[0],inp[i].d[1],inp[j].d[l]) &&
	    !(inp[i].d[0]==inp[j].d[l]) &&!(inp[i].d[1]==inp[j].d[l])){
	  dj.merge(i,j);
	  inp[i].mid.pb(inp[j].d[l]);
	  inp[i].cm.pb(j);
	  inp[j].cp[l]=i;
	}
      }
    }
  }
  

  int ans[10]={0};
  rep(i,n){
    in[dj.findset(i)].pb(i);
  }

  rep(i,n){
    if (in[i].size() == 0)continue;
    //    output(i,inp);
    if (iszero(i,inp)){
      ans[0]++;
    }
    else if (in[i].size() == 1){//isone
      ans[1]++;
    }
    else if (istwo(i,inp)){
      ans[2]++;
    }
    else if (isthree(i,inp)){
      ans[3]++;
    }
    else if (isfour(i,inp)){
      ans[4]++;
    }
    else if (isfive(i,inp)){
      ans[5]++;
    }
    else if (issix(i,inp)){
      ans[6]++;
    }
    else if (isseven(i,inp)){
      ans[7]++;
    }
    else if (iseight(i,inp)){
      ans[8]++;
    }
    else if (isnine(i,inp)){
      ans[9]++;
    }else exit(1);

  }

  rep(i,10){
    if (i)cout <<" ";
    cout << ans[i];
  }
  cout << endl;

}

main(){
  int n;
  Line inp[2000];
  while(cin>>n && n){
    rep(i,n)inp[i].clear();
    rep(i,n)in[i].clear();
    
    rep(i,n){
      rep(j,2)cin>>inp[i].d[j].real()>>inp[i].d[j].imag();
      swap(inp[i].d[0],inp[i].d[1]);
    }
    
    
    solve(n,inp);
  }
}

Compiler output:
a.cc:3:9: fatal error: csdtlib: No such file or directory
    3 | #include<csdtlib>
      |         ^~~~~~~~~
compilation terminated.