#include #include #include #include #include using namespace std; #define cin fin ifstream fin("squares.txt"); #define NSQUARE_MAX 1000 typedef unsigned long long ullong; class Rational { public: ullong n, d; Rational( ullong ng, ullong dg ) { const ullong g = gcd(ng, dg); n = ng/g; d = dg/g; } static Rational average( const Rational &a, const Rational &b ) { return Rational(a.n*b.d + b.n*a.d, 2*a.d*b.d); } bool operator < ( const Rational &r ) const { return (n*r.d < r.n*d); } bool operator == ( const Rational &r ) const { return (n == r.n && d == r.d); } private: static ullong gcd( ullong m, ullong n ) { return (n == 0)? m : gcd(n, m%n); } }; class Square { public: int x, y, length; // 正方形と原点からの光との衝突をみるとなると (x, y+length), (x+length, y) を通る // 直線の y 切片 (x+y+length) がソート基準に使える. bool operator < ( const Square &s ) const { return (x+y+length < s.x+s.y+s.length); } }; int nsquare; Square S[NSQUARE_MAX]; bool visible[NSQUARE_MAX]; bool collision( const Rational &l, const Square &s ) { const Rational ymin = Rational(l.n*s.x, l.d); const Rational ymax = Rational(l.n*(s.x+s.length), l.d); const Rational yubound = Rational(s.y+s.length, 1); const Rational ylbound = Rational(s.y, 1); return (ymin < yubound && ylbound < ymax); } bool tangent( const Rational &l, const Square &s ) { const Rational ymin = Rational(l.n*s.x, l.d); const Rational ymax = Rational(l.n*(s.x+s.length), l.d); const Rational yubound = Rational(s.y+s.length, 1); const Rational ylbound = Rational(s.y, 1); return (ymin == yubound || ymax == ylbound); } void compute( const Rational &l1, const Rational &l2 ) { // l1 と l2 のどちらにも接するまたは衝突すれば見えている. for ( int i = 0; i < nsquare; i++ ) { const bool c1 = collision(l1, S[i]); const bool t1 = tangent(l1, S[i]); const bool c2 = collision(l2, S[i]); const bool t2 = tangent(l2, S[i]); if ( (c1||t1) && (c2||t2) ) visible[i] = true; if ( c1 || c2 ) break; } } int main() { while ( cin >> nsquare, nsquare ) { for ( int i = 0; i < nsquare; i++ ) cin >> S[i].x >> S[i].y >> S[i].length; sort(S, S+nsquare); set RS; for ( int i = 0; i < nsquare; i++ ) { RS.insert(Rational(S[i].y+S[i].length, S[i].x)); RS.insert(Rational(S[i].y, S[i].x+S[i].length)); } for ( int i = 0; i < nsquare; i++ ) visible[i] = false; for ( set::iterator curr = RS.begin(); curr != RS.end(); curr++ ) { set::iterator prev = curr; prev--; set::iterator next = curr; next++; if ( curr != RS.begin() ) compute(*curr, Rational::average(*curr, *prev)); if ( next != RS.end() ) compute(*curr, Rational::average(*curr, *next)); } int nvisible = 0; for ( int i = 0; i < nsquare; i++ ) if ( visible[i] ) nvisible++; cout << nvisible << endl; } return 0; }