Problem:
Problem H:
Viva Confetti
Do you know
confetti
? They are small discs of colored paper, and people throw them around during parties or festivals. Since people throw lots of confetti, they may end up stacked one on another, so there may be hidden ones underneath.
A handful of various sized confetti have been dropped on a table. Given their positions and sizes, can you tell us how many of them you can see?
The following figure represents the disc configuration for the first sample input, where the bottom disc is still visible.
Input
The input is composed of a number of configurations of the following form.
n
x
1
y
1
z
1
x
2
y
2
z
2
.
.
.
x
n
y
n
z
n
The first line in a configuration is the number of discs in the configuration (a positive integer not more than 100), followed by one Ine descriptions of each disc: coordinates of its center and radius, expressed as real numbers in decimal notation, with up to 12 digits after the decimal point. The imprecision margin is ±5 × 10
-13
. That is, it is guaranteed that variations of less than ±5 × 10
-13
on input values do not change which discs are visible. Coordinates of all points contained in discs are between -10 and 10.
Confetti are listed in their stacking order,
x
1
y
1
r
1
being the bottom one and
x
n
y
n
r
n
the top one. You are observing from the top.
The end of the input is marked by a zero on a single line.
Output
For each configuration you should output the number of visible confetti on a single line.
Sample Input
3
0 0 0.5
-0.9 0 1.00000000001
0.9 0 1.00000000001
5
0 1 0.5
1 1 1.00000000001
0 2 1.00000000001
-1 1 1.00000000001
0 -0.00001 1.00000000001
5
0 1 0.5
1 1 1.00000000001
0 2 1.00000000001
-1 1 1.00000000001
0 0 1.00000000001
2
0 0 1.0000001
0 0 1
2
0 0 1
0.00000001 0 1
0
Output for the Sample Input
3
5
4
2
2

Submitted solutions:

code_snippet: #include<iostream>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>

using namespace std;

#define EPS (1e-15)
#define equals(a, b) (fabs((a) - (b)) < EPS )
#define dle(a, b) (equals(a, b) || a < b )
static const double PI = acos(-1);

class Point{
public:
  double x, y;

  Point ( double x = 0, double y = 0): x(x), y(y){}

  Point operator + ( Point p ){ return Point(x + p.x, y + p.y); }
  Point operator - ( Point p ){ return Point(x - p.x, y - p.y); }
  Point operator * ( double a ){ return Point(x*a, y*a); }
  Point operator / ( double a ){ return Point(x/a, y/a); }
  Point operator / ( Point p ) { return Point((x*p.x+y*p.y)/(p.x*p.x+p.y*p.y), (y*p.x-x*p.y)/(p.x*p.x+p.y*p.y)); }
   
  double abs() { return sqrt(norm());}
  double norm() { return x*x + y*y; }

  bool operator < ( const Point &p ) const {
    return x != p.x ? x < p.x : y < p.y;
  }

  bool operator == ( const Point &p ) const {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }
};

typedef Point Vector;


class Segment{
public:
  Point p1, p2;
  Segment(Point s = Point(), Point t = Point()): p1(s), p2(t){}

};

typedef Segment Line;

static const int CIRCLE_NON = 0;
static const int CIRCLE_OUT = 1;
static const int CIRCLE_IN = 2;
static const int CIRCLE_CROSS = 3;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c = Point(), double r = 0.0): c(c), r(r){}
};

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double abs( Vector a ){ return sqrt(norm(a)); }
Point polar( double a, double r ){ return Point(cos(r)*a, sin(r)*a);}
double getDistance( Vector a, Vector b ){ return abs(a - b); }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }

Point project( Segment s, Point p ){
  Vector base = s.p2 - s.p1;
  double t = dot(p - s.p1, base)/norm(base);
  return s.p1 + base*t;
}

double getAngle(Point p){
  double polar = atan2(p.y, p.x);
  return (dle(0, polar))? polar : 2.0*acos(-1)+polar;
}

int isIntersect(Circle c1, Circle c2){
  double d = abs(c1.c - c2.c);
  if ( c1.r + c2.r < d ) return CIRCLE_NON; // no overlap
  if ( d + c2.r < c1.r ) return CIRCLE_IN;  // c1 includes c2
  if ( d + c1.r < c2.r ) return CIRCLE_OUT;  // c2 includes c1
  return CIRCLE_CROSS;
}

double getDistanceLP(Line s, Point p){
  return abs(cross(s.p2 - s.p1, p - s.p1)/abs(s.p2 - s.p1));
}

double arg(Vector p){
  return atan2(p.y, p.x);
}

pair<Point, Point> getCrossPoints(Circle c1, Circle c2){
  assert( isIntersect( c1, c2 ) );
  double d = abs(c1.c - c2.c);
  double a = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
  double t = arg(c2.c - c1.c);
  return make_pair(c1.c+polar(c1.r, t+a), c1.c+polar(c1.r, t-a));
}

bool isIntersect( Circle c1, Line l ){
  double d = getDistanceLP(l, c1.c);
  return ( equals(d, c1.r) || d < c1.r );
}

pair<Point, Point> getCrossPoints(Circle c, Line l ){
  assert( isIntersect( c, l ) );
  Vector pr = project(l, c.c);
  Vector e = (l.p2 - l.p1)/abs(l.p2 - l.p1);
  double base = sqrt(c.r*c.r - norm(pr-c.c));
  return make_pair(pr + e*base, pr - e*base);
}

Circle C[100];
int n;

void compute(){
  vector<Point> candidates;
  vector<double> Y;  

  Y.push_back(-100.0);
  Y.push_back(100.0);

  for ( int i = 0; i < n; i++ ){
    Y.push_back(C[i].c.y - C[i].r);
    Y.push_back(C[i].c.y + C[i].r);
  }
  
  for ( int i = 0; i < n-1; i++ ){
    for ( int j = i+1; j < n; j++ ){
      if ( isIntersect(C[i], C[j]) != CIRCLE_CROSS ) continue;
      pair<Point, Point> pp = getCrossPoints(C[i], C[j]);
      Y.push_back(pp.first.y);
      Y.push_back(pp.second.y);
    }
  }

  sort(Y.begin(), Y.end());

  for ( int k = 0; k < Y.size()-1; k++ ){
    double my = (Y[k+1] + Y[k])/2;
    Line l = Line(Point(-100, my), Point(100, my));
    vector<double> X;
    X.push_back(-100);
    X.push_back(100);
    for ( int i = 0; i < n; i++ ){
      if ( !isIntersect(C[i], l) ) continue;
      pair<Point, Point> pp = getCrossPoints(C[i], l);
      X.push_back(pp.first.x);
      X.push_back(pp.second.x);
    }
    sort(X.begin(), X.end());

    for ( int i = 0; i < X.size()-1; i++ ){
      candidates.push_back(Point((X[i+1]+X[i])/2, my));
    }
  }

  int ans = 0;
  for ( int i = 0; i < n; i++ ){
    for ( int c = 0; c < candidates.size(); c++ ){
      Point t = candidates[c];
      bool f = true;
      if ( abs(C[i].c - t) > C[i].r ) {
	continue;
      }
      for ( int j = i+1; j < n; j++ ){
	if ( dle(abs(C[j].c - t), C[j].r) ) {
	  f = false;
	  break;
	}
      }
      if ( f ) {
	ans++;
	break;
      }
    }
  }

  printf("%d\n", ans);
}

int main(){
  double x, y, r;
  while(1){
    cin >> n;
    if ( n == 0 ) break;
    for ( int i = 0; i < n; i++ ){
      cin >> x >> y >> r; C[i] = Circle( Point(x, y), r);
    }
    compute();
  }

  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 5544
final_rank: 5

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-14)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

pair<Point, Point> crosspointCC( Point C1, double r1, Point C2, double r2) {
  complex<double> c1(C1.x,C1.y);
  complex<double> c2(C2.x,C2.y);
  complex<double> A = conj(c2-c1), B = (r2*r2-r1*r1-(c2-c1)*conj(c2-c1)), C = r1*r1*(c2-c1);
  complex<double> D = B*B-4.0*A*C;
  complex<double> z1 = (-B+sqrt(D))/(2.0*A)+c1, z2 = (-B-sqrt(D))/(2.0*A)+c1;
  return pair<Point, Point>(Point(z1.real(),z1.imag()),Point(z2.real(),z2.imag()));
}

// ??? a ?????? b ????????????????????????
bool insideCC(Point a,double ra,Point b,double rb){
  double d = sqrt(norm(a-b));
  double r1 = max(ra,rb);
  double r2 = min(ra,rb);
  
  if(!equals(d,r1-r2) && d < r1-r2) return ra < rb; 
  return false;
}


//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}



bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //???????????°??????????????????
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}





// <---------

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }

int n;
Point ps[110];
double rs[110];

bool insideAny(int i) {
  REP(j,i+1,n) if( insideCC(ps[i],rs[i],ps[j],rs[j]) ) return true;
  return false;
}

bool trivialFail(int i) {
  if( insideAny(i) ) return true;
  REP(j,i+1,n) if( ps[i] == ps[j] && equals(rs[i],rs[j]) ) return true;
  return false;
}

Point vir;
bool comp_angle(const Point &a,const Point &b) {
  return LT(atan2(vir.y-a.y,vir.x-a.x),atan2(vir.y-b.y,vir.x-b.x));
}

bool comp_dist(Point a,Point b) {
  return LTE(abs(a-vir),abs(b-vir));
}

pair<Point,Point> crosspointCL(Point cp,double r,Line l) {
  double dist = distanceLP(l,cp);
  Vector v = (l.p1-l.p2) / abs(l.p1-l.p2);
  if( equals(dist,0) ) {
    return pair<Point,Point>(Point(cp+v*r),Point(cp-v*r));
  } else {
    double x = sqrt(r*r-dist*dist);
    return pair<Point,Point>(Point(cp+v*x),Point(cp-v*x));
  }
}

bool visibleCheckPoint(Point p,int i) {
  REP(j,i+1,n) {
    double dist = abs(p-ps[j]);
    if( LT(dist,rs[j]) ) return false;
  }
  return true;
}

bool visibleCheckSeg(Segment seg,int i) {
  deque<Point> deq;
  deq.push_back(seg.p1);
  deq.push_back(seg.p2);
  rep(j,2) {
    double dist = abs(deq[j]-ps[i]);
    if( equals(dist,rs[i]) || dist < rs[i] ) if( visibleCheckPoint(deq[j],i) ) return true;
  }
  return false;
  REP(j,i+1,n) {
    double dist = distanceLP(seg,ps[j]);
    if( LTE(rs[j],dist) ) continue;
    pair<Point,Point> pp = crosspointCL(ps[j],rs[j],seg);
    if( onSegment(seg.p1,seg.p2,pp.first)  ) deq.push_back(pp.first);
    if( onSegment(seg.p1,seg.p2,pp.second) ) deq.push_back(pp.second);
  }
  
  // sort
  vir = seg.p1;
  sort(deq.begin(),deq.end(),comp_dist);
  
  // check
  rep(j,(int)deq.size()-1) {
    Point p1 = deq[j];
    Point p2 = deq[j+1];
    Point mp = (p1+p2)/2.0;
    double dist = abs(mp-ps[i]);
    if( equals(dist,rs[i]) || dist < rs[i] ) if( visibleCheckPoint(mp,i) ) return true;
  }
  return false;
}

bool visibleCheckArcJ(int i,int j) {
  deque<Point> deq;
  REP(k,i,n) {
    if( ps[j] == ps[k] && equals(rs[j],rs[k]) ) continue;
    {
      double  dist = abs(ps[k]-ps[j]); 
      double rdist = rs[k]+rs[j];
      if( equals(dist,rdist) || dist > rdist ) continue;
    }
    pair<Point,Point> pp = crosspointCC(ps[j],rs[j],ps[k],rs[k]);
    deq.push_back(pp.first);
    deq.push_back(pp.second);
  }
  vir = ps[j];
  sort(deq.begin(),deq.end(),comp_angle);
  rep(k,(int)deq.size()) {
    Point p1 = deq[k] - ps[j];
    Point p2 = deq[(k+1)%(int)deq.size()] - ps[j];
    Point mp = ( p1 + p2 ) / 2.0;
    mp = mp + ps[j];
    Vector v = ( mp - ps[j] ) / abs( mp - ps[j] );
    Segment seg = Segment(ps[j]+v*rs[j],ps[j]-v*rs[j]);
    if( visibleCheckSeg(seg,i) ) return true;
  }
  return false;
}

void compute() {
  int cnt = 0;
  rep(i,n) { // check the i-th circle whether the circle is visible or not
    if( trivialFail(i) ) continue;
    bool success = false;
    bool success2 = true;
    REP(j,i+1,n) { 
      {
	double  dist = abs(ps[i]-ps[j]); 
	double rdist = rs[i]+rs[j];
	if( equals(dist,rdist) || dist > rdist ) continue;
      }
      if( insideCC(ps[j],rs[j],ps[i],rs[i]) ) continue; 
      success2 = false;
      if( visibleCheckArcJ(i,j) ) { success = true; break; }
    }
    if( success || success2 ) ++cnt;
  }
  cout << cnt << endl;
}

int main() {
  while( cin >> n, n ) {
    rep(i,n) cin >> ps[i].x >> ps[i].y >> rs[i];
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1360
final_rank: 1

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-14)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

pair<Point, Point> crosspointCC( Point C1, double r1, Point C2, double r2) {
  complex<double> c1(C1.x,C1.y);
  complex<double> c2(C2.x,C2.y);
  complex<double> A = conj(c2-c1), B = (r2*r2-r1*r1-(c2-c1)*conj(c2-c1)), C = r1*r1*(c2-c1);
  complex<double> D = B*B-4.0*A*C;
  complex<double> z1 = (-B+sqrt(D))/(2.0*A)+c1, z2 = (-B-sqrt(D))/(2.0*A)+c1;
  return pair<Point, Point>(Point(z1.real(),z1.imag()),Point(z2.real(),z2.imag()));
}

// ??? a ?????? b ????????????????????????
bool insideCC(Point a,double ra,Point b,double rb){
  double d = sqrt(norm(a-b));
  double r1 = max(ra,rb);
  double r2 = min(ra,rb);
  
  if(!equals(d,r1-r2) && d < r1-r2) return ra < rb; 
  return false;
}


//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}



bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //???????????°??????????????????
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}





// <---------

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }

int n;
Point ps[110];
double rs[110];

bool insideAny(int i) {
  REP(j,i+1,n) if( insideCC(ps[i],rs[i],ps[j],rs[j]) ) return true;
  return false;
}

bool trivialFail(int i) {
  if( insideAny(i) ) return true;
  REP(j,i+1,n) if( ps[i] == ps[j] && equals(rs[i],rs[j]) ) return true;
  return false;
}

Point vir;
bool comp_angle(const Point &a,const Point &b) {
  return LT(atan2(vir.y-a.y,vir.x-a.x),atan2(vir.y-b.y,vir.x-b.x));
}

bool comp_dist(Point a,Point b) {
  return LTE(abs(a-vir),abs(b-vir));
}

pair<Point,Point> crosspointCL(Point cp,double r,Line l) {
  double dist = distanceLP(l,cp);
  Vector v = (l.p1-l.p2) / abs(l.p1-l.p2);
  if( equals(dist,0) ) {
    return pair<Point,Point>(Point(cp+v*r),Point(cp-v*r));
  } else {
    double x = sqrt(r*r-dist*dist);
    return pair<Point,Point>(Point(cp+v*x),Point(cp-v*x));
  }
}

bool visibleCheckPoint(Point p,int i) {
  REP(j,i+1,n) {
    double dist = abs(p-ps[j]);
    if( LT(dist,rs[j]) ) return false;
  }
  return true;
}

bool visibleCheckSeg(Segment seg,int i) {
  deque<Point> deq;
  deq.push_back(seg.p1);
  deq.push_back(seg.p2);
  REP(j,i+1,n) {
    double dist = distanceLP(seg,ps[j]);
    if( LTE(rs[j],dist) ) continue;
    pair<Point,Point> pp = crosspointCL(ps[j],rs[j],seg);
    if( onSegment(seg.p1,seg.p2,pp.first)  ) deq.push_back(pp.first);
    if( onSegment(seg.p1,seg.p2,pp.second) ) deq.push_back(pp.second);
  }
  
  // sort
  vir = seg.p1;
  sort(deq.begin(),deq.end(),comp_dist);
  
  // check
  rep(j,(int)deq.size()-1) {
    Point p1 = deq[j];
    Point p2 = deq[j+1];
    Point mp = (p1+p2)/2.0;
    double dist = abs(mp-ps[i]);
    if( equals(dist,rs[i]) || dist < rs[i] ) if( visibleCheckPoint(mp,i) ) return true;
  }
  return false;
}

bool visibleCheckArcJ(int i,int j) {
  deque<Point> deq;
  REP(k,i,n) {
    if( ps[j] == ps[k] && equals(rs[j],rs[k]) ) continue;
    {
      double  dist = abs(ps[k]-ps[j]); 
      double rdist = rs[k]+rs[j];
      if( equals(dist,rdist) || dist > rdist ) continue;
    }
    pair<Point,Point> pp = crosspointCC(ps[j],rs[j],ps[k],rs[k]);
    deq.push_back(pp.first);
    deq.push_back(pp.second);
  }
  vir = ps[j];
  sort(deq.begin(),deq.end(),comp_angle);
  rep(k,(int)deq.size()) {
    Point p1 = deq[k] - ps[j];
    Point p2 = deq[(k+1)%(int)deq.size()] - ps[j];
    Point mp = ( p1 + p2 ) / 2.0;
    mp = mp + ps[j];
    Vector v = ( mp - ps[j] ) / abs( mp - ps[j] );
    Segment seg = Segment(ps[j]+v*rs[j],ps[j]-v*rs[j]);
    if( visibleCheckSeg(seg,i) ) return true;
  }
  return false;
}

void compute() {
  int cnt = 0;
  rep(i,n) { // check the i-th circle whether the circle is visible or not
    if( trivialFail(i) ) continue;
    bool success = false;
    bool success2 = true;
    REP(j,i+1,n) { 
      {
	double  dist = abs(ps[i]-ps[j]); 
	double rdist = rs[i]+rs[j];
	if( equals(dist,rdist) || dist > rdist ) continue;
      }
      if( insideCC(ps[j],rs[j],ps[i],rs[i]) ) continue; 
      success2 = false;
      if( visibleCheckArcJ(i,j) ) { success = true; break; }
    }
    if( success || success2 ) ++cnt;
  }
  cout << cnt << endl;
}

int main() {
  while( cin >> n, n ) {
    rep(i,n) cin >> ps[i].x >> ps[i].y >> rs[i];
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 1372
final_rank: 3

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-14)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad ????§???????????????¢?????§?????????????????¨
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// ??????????????¢????????????
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev ?????? cur ????????£??? next ????????????????§????????±???????
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

pair<Point, Point> crosspointCC( Point C1, double r1, Point C2, double r2) {
  complex<double> c1(C1.x,C1.y);
  complex<double> c2(C2.x,C2.y);
  complex<double> A = conj(c2-c1), B = (r2*r2-r1*r1-(c2-c1)*conj(c2-c1)), C = r1*r1*(c2-c1);
  complex<double> D = B*B-4.0*A*C;
  complex<double> z1 = (-B+sqrt(D))/(2.0*A)+c1, z2 = (-B-sqrt(D))/(2.0*A)+c1;
  return pair<Point, Point>(Point(z1.real(),z1.imag()),Point(z2.real(),z2.imag()));
}

// ??? a ?????? b ????????????????????????
bool insideCC(Point a,double ra,Point b,double rb){
  double d = sqrt(norm(a-b));
  double r1 = max(ra,rb);
  double r2 = min(ra,rb);
  
  if(!equals(d,r1-r2) && d < r1-r2) return ra < rb; 
  return false;
}


//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}



bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //???????????°??????????????????
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}





// <---------

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }

int n;
Point ps[110];
double rs[110];

bool insideAny(int i) {
  REP(j,i+1,n) if( insideCC(ps[i],rs[i],ps[j],rs[j]) ) return true;
  return false;
}

bool trivialFail(int i) {
  if( insideAny(i) ) return true;
  REP(j,i+1,n) if( ps[i] == ps[j] && equals(rs[i],rs[j]) ) return true;
  return false;
}

Point vir;
bool comp_angle(const Point &a,const Point &b) {
  return LT(atan2(vir.y-a.y,vir.x-a.x),atan2(vir.y-b.y,vir.x-b.x));
}

bool comp_dist(Point a,Point b) {
  return LTE(abs(a-vir),abs(b-vir));
}

pair<Point,Point> crosspointCL(Point cp,double r,Line l) {
  double dist = distanceLP(l,cp);
  Vector v = (l.p1-l.p2) / abs(l.p1-l.p2);
  if( equals(dist,0) ) {
    return pair<Point,Point>(Point(cp+v*r),Point(cp-v*r));
  } else {
    double x = sqrt(r*r-dist*dist);
    return pair<Point,Point>(Point(cp+v*x),Point(cp-v*x));
  }
}

bool visibleCheckPoint(Point p,int i) {
  REP(j,i+1,n) {
    double dist = abs(p-ps[j]);
    if( LT(dist,rs[j]) ) return false;
  }
  return true;
}

bool visibleCheckSeg(Segment seg,int i) {
  deque<Point> deq;
  deq.push_back(seg.p1);
  deq.push_back(seg.p2);
  REP(j,i+1,n) {
    double dist = distanceLP(seg,ps[j]);
    if( LTE(rs[j],dist) ) continue;
    pair<Point,Point> pp = crosspointCL(ps[j],rs[j],seg);
    if( onSegment(seg.p1,seg.p2,pp.first)  ) deq.push_back(pp.first);
    if( onSegment(seg.p1,seg.p2,pp.second) ) deq.push_back(pp.second);
  }
  
  // sort
  vir = seg.p1;
  sort(deq.begin(),deq.end(),comp_dist);
  
  // check
  rep(j,(int)deq.size()-1) {
    Point p1 = deq[j];
    Point p2 = deq[j+1];
    Point mp = (p1+p2)/2.0;
    double dist = abs(mp-ps[i]);
    if( equals(dist,rs[i]) || dist < rs[i] ) {
      if( visibleCheckPoint(mp,i) ) return true;
    }
  }
  return false;
}

bool visibleCheckArcJ(int i,int j) {
  deque<Point> deq;
  REP(k,i,n) {
    if( ps[j] == ps[k] && equals(rs[j],rs[k]) ) continue;
    {
      double  dist = abs(ps[k]-ps[j]); 
      double rdist = rs[k]+rs[j];
      if( equals(dist,rdist) || dist > rdist ) continue;
    }
    pair<Point,Point> pp = crosspointCC(ps[j],rs[j],ps[k],rs[k]);
    deq.push_back(pp.first);
    deq.push_back(pp.second);
  }
  vir = ps[j];
  sort(deq.begin(),deq.end(),comp_angle);
  //deq.erase(unique(deq.begin(),deq.end()),deq.end());
  rep(k,(int)deq.size()) {
    Point p1 = deq[k] - ps[j];
    Point p2 = deq[(k+1)%(int)deq.size()] - ps[j];
    Point mp = ( p1 + p2 ) / 2.0;
    mp = mp + ps[j];
    Vector v = ( mp - ps[j] ) / abs( mp - ps[j] );
    Segment seg = Segment(ps[j]+v*rs[j],ps[j]-v*rs[j]);
    //cout << "CHECK SEG " << seg << endl;
    if( visibleCheckSeg(seg,i) ) {
      //cout << "VISIBLE ARC " << seg << endl;
      return true;
    }
  }
  return false;
}

void compute() {
  int cnt = 0;
  rep(i,n) { // check the i-th circle whether the circle is visible or not
    //cout << i << "-th " << ps[i] << ", " << rs[i] << endl;
    if( trivialFail(i) ) {
      //cout << i << " is trivialFail" << endl;
      continue;
    }
    bool success = false;
    bool success2 = true;
    REP(j,i+1,n) { 
      //cout <<">> " << j << " " << ps[j] << "," << rs[j] << endl;
      {
	double  dist = abs(ps[i]-ps[j]); 
	double rdist = rs[i]+rs[j];
	if( equals(dist,rdist) || dist > rdist ) {
	  //puts("OVER");
	  continue;
	}
      }
      if( insideCC(ps[j],rs[j],ps[i],rs[i]) ) {
	//puts("INSIDE");
	continue;
      }
      success2 = false;
      if( visibleCheckArcJ(i,j) ) { 
	//puts("VISIBLE");
	success = true; break; 
      }
      //puts("INVISIBLE");
    }
    if( success || success2 ) ++cnt;
  }
  cout << cnt << endl;
}

int main() {
  while( cin >> n, n ) {
    rep(i,n) cin >> ps[i].x >> ps[i].y >> rs[i];
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 1372
final_rank: 2

code_snippet: #include<iostream>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>

using namespace std;

#define EPS (1e-15)
#define equals(a, b) (fabs((a) - (b)) < EPS )
#define dle(a, b) (equals(a, b) || a < b )
static const double PI = acos(-1);

class Point{
public:
  double x, y;

  Point ( double x = 0, double y = 0): x(x), y(y){}

  Point operator + ( Point p ){ return Point(x + p.x, y + p.y); }
  Point operator - ( Point p ){ return Point(x - p.x, y - p.y); }
  Point operator * ( double a ){ return Point(x*a, y*a); }
  Point operator / ( double a ){ return Point(x/a, y/a); }
  Point operator / ( Point p ) { return Point((x*p.x+y*p.y)/(p.x*p.x+p.y*p.y), (y*p.x-x*p.y)/(p.x*p.x+p.y*p.y)); }
   
  double abs() { return sqrt(norm());}
  double norm() { return x*x + y*y; }

  bool operator < ( const Point &p ) const {
    return x != p.x ? x < p.x : y < p.y;
  }

  bool operator == ( const Point &p ) const {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }
};

typedef Point Vector;


class Segment{
public:
  Point p1, p2;
  Segment(Point s = Point(), Point t = Point()): p1(s), p2(t){}

};

typedef Segment Line;

static const int CIRCLE_NON = 0;
static const int CIRCLE_OUT = 1;
static const int CIRCLE_IN = 2;
static const int CIRCLE_CROSS = 3;

class Circle{
public:
  Point c;
  double r;
  Circle(Point c = Point(), double r = 0.0): c(c), r(r){}
};

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double abs( Vector a ){ return sqrt(norm(a)); }
Point polar( double a, double r ){ return Point(cos(r)*a, sin(r)*a);}
double getDistance( Vector a, Vector b ){ return abs(a - b); }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }

Point project( Segment s, Point p ){
  Vector base = s.p2 - s.p1;
  double t = dot(p - s.p1, base)/norm(base);
  return s.p1 + base*t;
}

double getAngle(Point p){
  double polar = atan2(p.y, p.x);
  return (dle(0, polar))? polar : 2.0*acos(-1)+polar;
}

int isIntersect(Circle c1, Circle c2){
  double d = abs(c1.c - c2.c);
  if ( c1.r + c2.r < d ) return CIRCLE_NON; // no overlap
  if ( d + c2.r < c1.r ) return CIRCLE_IN;  // c1 includes c2
  if ( d + c1.r < c2.r ) return CIRCLE_OUT;  // c2 includes c1
  return CIRCLE_CROSS;
}

double getDistanceLP(Line s, Point p){
  return abs(cross(s.p2 - s.p1, p - s.p1)/abs(s.p2 - s.p1));
}

double arg(Vector p){
  return atan2(p.y, p.x);
}

pair<Point, Point> getCrossPoints(Circle c1, Circle c2){
  assert( isIntersect( c1, c2 ) );
  double d = abs(c1.c - c2.c);
  double a = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
  double t = arg(c2.c - c1.c);
  return make_pair(c1.c+polar(c1.r, t+a), c1.c+polar(c1.r, t-a));
}

bool isIntersect( Circle c1, Line l ){
  double d = getDistanceLP(l, c1.c);
  return ( equals(d, c1.r) || d < c1.r );
}

pair<Point, Point> getCrossPoints(Circle c, Line l ){
  assert( isIntersect( c, l ) );
  Vector pr = project(l, c.c);
  Vector e = (l.p2 - l.p1)/abs(l.p2 - l.p1);
  double base = sqrt(c.r*c.r - norm(pr-c.c));
  return make_pair(pr + e*base, pr - e*base);
}

Circle C[100];
int n;

void compute(){
  vector<Point> candidates;
  vector<double> Y;  

  Y.push_back(-100.0);
  Y.push_back(100.0);

  for ( int i = 0; i < n; i++ ){
    Y.push_back(C[i].c.y - C[i].r);
    Y.push_back(C[i].c.y + C[i].r);
  }
  
  for ( int i = 0; i < n-1; i++ ){
    for ( int j = i+1; j < n; j++ ){
      if ( isIntersect(C[i], C[j]) != CIRCLE_CROSS ) continue;
      pair<Point, Point> pp = getCrossPoints(C[i], C[j]);
      Y.push_back(pp.first.y);
      Y.push_back(pp.second.y);
    }
  }

  sort(Y.begin(), Y.end());

  for ( int k = 0; k < Y.size()-1; k++ ){
    double my = (Y[k+1] + Y[k])/2;
    Line l = Line(Point(-100, my), Point(100, my));
    vector<double> X;
    X.push_back(-100);
    X.push_back(100);
    for ( int i = 0; i < n; i++ ){
      if ( !isIntersect(C[i], l) ) continue;
      pair<Point, Point> pp = getCrossPoints(C[i], l);
      X.push_back(pp.first.x);
      X.push_back(pp.second.x);
    }
    sort(X.begin(), X.end());

    for ( int i = 0; i < X.size()-1; i++ ){
      candidates.push_back(Point((X[i+1]+X[i])/2, my));
    }
  }

  int ans = 0;
  for ( int i = 0; i < n; i++ ){
    for ( int c = 0; c < candidates.size(); c++ ){
      Point t = candidates[c];
      bool f = true;
      if ( abs(C[i].c - t) > C[i].r ) {
	continue;
      }
      for ( int j = i+1; j < n; j++ ){
	if ( dle(abs(C[j].c - t), C[j].r) ) {
	  f = false;
	  break;
	}
      }
      if ( f ) {
	ans++;
	break;
      }
    }
  }

  printf("%d\n", ans);
}

int main(){
  double x, y, r;
  while(1){
    cin >> n;
    if ( n == 0 ) break;
    for ( int i = 0; i < n; i++ ){
      cin >> x >> y >> r; C[i] = Circle( Point(x, y), r);
    }
    compute();
  }

  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3360
final_rank: 4