Problem: A crop circle suddenly appeared on the vast agricultural land of Argentina. A total of n crop circles were confirmed, including overlapping, popping, large, and small ones.

When a mystery hunter tried to capture the whole picture of a crop circle from the air, he found it difficult to show the beautiful pattern in the image because the outline of each circle was not clear.

Therefore, the mystery hunter proposed to emphasize the contour by installing a string of special material along the contour.

The part where the string is installed is the part on the circumference of one crop circle that is not included in any other crop circle.

The film crew asked you to create a program to measure the required string length. Enter the center coordinates and radius of each crop circle and create a program to report the length of the string to be installed.

For reference, the first and second cases of the input / output examples are shown in FIGS. 1 and 2, respectively. The part of the string is shown by a thick line.


<image>


Figure 1



<image>


Figure 2



Constraints

* n ≤ 100
* -1000 ≤ xi, yi ≤ 1000
* 0 <ri ≤ 100

Input

Multiple datasets are given as input. Each dataset is given in the following format:

n (number of crop circles: integer)
x1 y1 r1 (center coordinates and radius of the first circle: real numbers separated by blanks)
x2 y2 r2 (center coordinates and radius of the second circle: real numbers separated by blanks)
..
..
xn yn rn (center coordinates and radius of the nth circle: real numbers separated by blanks)


When n is 0, it indicates the end of input.

Output

Output the string length on one line for each dataset. The output may contain an error of 0.000001 or less.

Example

Input

4
6 4 2
4 7 3
7 10 3
13 6 1
4
7 4 2
4 7 3
7 10 3
11 6 3
0


Output

39.664699289572
45.627024663706

Solution (in CPP):

Solution:
#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_DEPRECATE

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>
#include <iomanip>
#include <fstream>


using namespace std;
const int MOD = 1000000009; // check!!!
const int INF = 100000000; //1e8

typedef long long ll;
typedef pair<int,int> Pii;
typedef pair<ll,ll> Pll;

#define FOR(i,n) for(int i = 0; i < (n); i++)
#define sz(c) ((int)(c).size())
#define ten(x) ((int)1e##x)
#define tenll(x) ((ll)1e##x)


const double EPS (1e-8);
const double PI=acos(-1.0);

#pragma region 基本要素(struct,typedef)

template<class T>
struct point{
    T x,y;
    point() : x(0), y(0) {}
    point(const T& x,const T& y) : x(x), y(y) {}
    point operator+(const point &a)const{ return point(x+a.x,y+a.y); }
    point& operator+=(const point &a){x += a.x; y += a.y; return *this;}
    point operator-(const point &a)const{ return point(x-a.x,y-a.y); }
    point& operator-=(const point &a){x -= a.x; y -= a.y; return *this;}
    point operator*(const double a)const{ return point(a*x,a*y); }
    point& operator*=(const double a){ x *= a; y *= a; return *this;}
    point operator/(const double a)const{ return point(x/a,y/a); }
    point& operator/=(const double a){ x /= a; y /= a; return *this;}
	
	//比較用
	bool operator<(const point &a)const{return (x != a.x) ? (x < a.x) : (y < a.y);}
 
};

template<class T>
struct segment{
    point<T> a,b;
    segment() : a(point<T>()), b(point<T>()) {}
    segment(const point<T>& a,const point<T>& b) : a(a), b(b) {}
};

template<class T>
struct line{
    point<T> a,b;
    line() : a(point<T>()), b(point<T>()) {}
    line(const point<T>& a,const point<T>& b) : a(a), b(b) {}
};

template<class T>
struct circle{
	point<T> c;
	T r;
	circle(){}
	circle(const point<T> &c, T& r) : c(c),r(r) {}
};

typedef point<double> P;
typedef segment<double> S;
typedef line<double> L;
typedef circle<double> C;

#pragma endregion 

#pragma region 基本要素(関数)

template<class T> T SQ(T x){ return x*x; }
template<class T> T dist2(const point<T> &a,const point<T> &b){return SQ(a.x-b.x)+SQ(a.y-b.y);}
template<class T> T abs2(const point<T>& p){return SQ(p.x) + SQ(p.y);}
template<class T> T abs(const point<T>& p){return sqrt(abs2(p));}
template<class T> T dot(const point<T>& a,const point<T>& b)
{return a.x*b.x + a.y*b.y;}
template<class T> T cross(const point<T>& a,const point<T>& b)
{return a.x*b.y - a.y*b.x;}
template<class T> point<T> rot(const point<T>& a,const double theta){
        return point<T>(a.x*cos(theta)-a.y*sin(theta),
			a.x*sin(theta)+a.y*cos(theta));
}
template<class T>
double arg(const point<T> &a){	double t=atan2(a.y,a.x); return t<0?t+2*PI:t; }

enum{CCW=1,CW=-1,ON=0};
template<class T>
int ccw(const point<T> &a,point<T> b,point<T> c){
	b -= a; c -= a;
    double rdir=cross(b,c);
    double len = abs(b) * abs(c); //誤差対策 (速度がやばい時は外すか、二乗に置き換える)
    if(rdir> EPS * len) return CCW; //cがabより上(反時計周り)
    if(rdir<-EPS * len) return CW; // cがabより下(時計周り)
    return ON; // a,b,cが一直線上
}

#pragma endregion

#pragma region 入出力

std::ostream& operator<<(std::ostream& os, const P& point){return ( os << '(' << point.x << ',' << point.y << ')' );}
std::ostream& operator<<(std::ostream& os, const S& seg){return ( os << '{' << seg.a << ',' << seg.b << '}' );}
std::istream& operator>>(std::istream& is, P& point){return ( is >> point.x >> point.y );}

#pragma endregion

//交点が存在するかどうか
bool intersected(const S &S1,const S &S2){
    if(max(S1.a.x,S1.b.x)+EPS<min(S2.a.x,S2.b.x)
    || max(S1.a.y,S1.b.y)+EPS<min(S2.a.y,S2.b.y)
    || max(S2.a.x,S2.b.x)+EPS<min(S1.a.x,S1.b.x)
    || max(S2.a.y,S2.b.y)+EPS<min(S1.a.y,S1.b.y)) return false;
    return ccw(S1.a,S1.b,S2.a)*ccw(S1.a,S1.b,S2.b)<=0
        && ccw(S2.a,S2.b,S1.a)*ccw(S2.a,S2.b,S1.b)<=0;
}

#pragma region 距離

//線分と点の距離(2乗)
double dist2(const S &S,const P &p){
    if(dot(S.b-S.a,p-S.a)<=0) return dist2(p,S.a);
    if(dot(S.a-S.b,p-S.b)<=0) return dist2(p,S.b);
    return (double)SQ(cross(S.b-S.a,p-S.a)) / dist2(S.a,S.b);
}

//線分と点の距離
double dist(const S &S,const P &p){ return sqrt(dist2(S,p)); }

//線分と線分の距離
double dist(const S &S1,const S &S2){
    if(intersected(S1,S2)) return 0;
    return sqrt(min(min(dist2(S1,S2.a),dist2(S1,S2.b)),
                    min(dist2(S2,S1.a),dist2(S2,S1.b))));
}

//直線と点の距離
double dist(const L &L,const P &p){
    return sqrt((double)SQ(cross(L.b-L.a,p-L.a)) / dist2(L.a,L.b));
}

//a -- bの間の円が入った時の、a - b間の距離
//円の間に
double geodist(P a,P b,const C &c){
	double r=c.r;
	S s(a,b);
	if(dist(s,c.c)>r) 
		return abs(a-b);

	a-=c.c;
	b-=c.c;

	double L1=abs(a);
	double t1=arg(a)+acos(r/L1); if(t1<0) t1+=2*PI;
	double t2=arg(a)-acos(r/L1); if(t2<0) t2+=2*PI;

	double L2=abs(b);
	double t3=arg(b)+acos(r/L2); if(t3<0) t3+=2*PI;
	double t4=arg(b)-acos(r/L2); if(t4<0) t4+=2*PI;

	double theta=2*PI;
	theta=min(theta,min(abs(t1-t4),2*PI-abs(t1-t4)));
	theta=min(theta,min(abs(t2-t3),2*PI-abs(t2-t3)));
	return sqrt(L1*L1-r*r)+sqrt(L2*L2-r*r)+r*theta;
}

#pragma endregion

#pragma region 面積

//多角形の面積
double area(const vector<P>& v){
	double ans = 0;
	for (int i = 2; i < (int)v.size(); i++){
		ans += cross(v[i-1] - v[0],v[i] - v[0]);
	}
	return abs(ans) / 2;
}

//三角形の面積
double area(const P &a,const P &b,const P &c){
	return abs(cross(b-a,c-a)) / 2;
}

#pragma endregion

#pragma region 包含

//凸包
vector<P> convex_hull(vector<P>& ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  vector<P> ch(2*n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;

  for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;

  ch.resize(k-1);

  return ch;
}

//三角形abcにpが含まれているかどうか(線上の場合も含む)
bool cover(const P& a,const P& b,const P& c,const P& p){
	return area(a,b,c) + EPS >= area(a,b,p) + area(a,c,p) + area(b,c,p);
}

#pragma endregion

#pragma region 交点

//円同士の交点
int intersect(const C &C1,const C &C2,P* p = NULL,P *q = NULL){
	double r1=C1.r,r2=C2.r;
	P p1=C1.c,p2=C2.c;

	double d=abs(p1-p2);
	if(d<EPS && abs(r1-r2)<EPS){ // C1==C2
		return -1;
	}
	else if(r1+r2<d-EPS || d+EPS<abs(r1-r2)){
		return 0;
	}
	else{
		double a=(r1*r1-r2*r2+d*d)/(2*d);
		double h=sqrt(max(r1*r1-a*a,0.0));
		P tmp1=p1+(p2-p1)*a/d;
		P tmp2=(p2-p1)*h/d;
		if(abs(tmp2)<EPS){
			if(p&&q) *p = *q = tmp1;
			return 1;
		}
		else{
			if(p&&q){
				*p = P(tmp1.x-tmp2.y,tmp1.y+tmp2.x);
				*q = P(tmp1.x+tmp2.y,tmp1.y-tmp2.x);
			}
			return 2;
		}
	}
}

// l : ax+by+c=0 に変換
inline void calc_abc(const L &l,double &a,double &b,double &c){
    a=l.a.y-l.b.y;
    b=l.b.x-l.a.x;
    c=l.a.x*l.b.y-l.b.x*l.a.y;
}
 
//PからLへの垂線の足
P perp_foot(const P &p,const L &l){
    double a,b,c;
    calc_abc(l,a,b,c);
    return p-P(a,b) * ((a*p.x+b*p.y+c)/(a*a+b*b));
}
 
//円と直線の交点
int intersect(const C &c,const L &l,P *p=NULL,P *q=NULL){
    P m=perp_foot(c.c,l);
    double d2=abs2(c.c-m);
    if(c.r*c.r+EPS<d2)   return 0;
    else if(abs(c.r*c.r-d2)<EPS){
        if(p&&q)    *p=*q=m;
        return 1;
    }
    else{
        if(p&&q){
            P v;
            double n0=abs2(l.a-m),n1=abs2(l.b-m);
            if(n0<n1)    v=l.b-m,n0=n1;
            else        v=l.a-m;
            v*=sqrt((c.r*c.r-d2)/n0);
            *p=m+v,*q=m-v;
        }
        return 2;
    }
}

//円と線分の交点
int intersect(const C &c,const S &s,P *p=NULL,P *q=NULL){
    P pp,qq;
    int n=intersect(c,L(s.a,s.b),&pp,&qq);
    if(n==0)    return 0;
    else if(n==1){
        if(dot(pp-s.a,pp-s.b)<EPS){
            if(p&&q)    *p=*q=pp;
            return 1;
        }
        return 0;
    }
    else{
        bool bp=(dot(pp-s.a,pp-s.b)<EPS);
        bool bq=(dot(qq-s.a,qq-s.b)<EPS);
        if(bp&&bq){
            if(p&&q)    *p=pp,*q=qq;
            return 2;
        }
        if(bp||bq){
            if(p&&q)    *p=(bp?pp:qq);
            return 1;
        }
        return 0;
    }
}

//直線の交点
P intersect(const L &L1,const L &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a;
	return L2.a+(L2.b-L2.a) * (a2/a1);
}

#pragma endregion

class CMP{
	C c;
public:
	CMP(const C& c) : c(c) {}
	bool operator()(const P& p,const P& q) const{
		double parg = arg(p-c.c);
		double qarg = arg(q-c.c);
		return parg < qarg;
	}
};

int main(){
	int n;
	while(cin>>n,n){
		vector<C> vc(n);
		FOR(i,n) cin>>vc[i].c>>vc[i].r;

		double ans = 0;

		FOR(i,n){
			vector<P> vp;
			FOR(j,n) if(i != j) {
				P p,q;
				int a = intersect(vc[i],vc[j],&p,&q);
				if(a==1) vp.push_back(p);
				else if(a==2) vp.push_back(p),vp.push_back(q);
			}

			sort(vp.begin(),vp.end(),CMP(vc[i]));

			ans += 2 * PI * vc[i].r;

			double dbg = 0;

			if(sz(vp) >= 2){
				FOR(j,sz(vp)){
					P &p = vp[j],&q = vp[(j+1)%sz(vp)];
					double parg = arg(p-vc[i].c);
					double qarg = arg(q-vc[i].c);
					double dist,md;
					if(qarg < parg) dist = (qarg-parg+2*PI);
					else dist = qarg-parg;
					md = parg + dist / 2;

					P a(cos(md),sin(md));
					a = a * vc[i].r + vc[i].c;

					bool covered = false;
					FOR(k,n) if(i != k){
						if(abs2(a-vc[k].c) < SQ(vc[k].r)){
							covered = true;
						}
					}

					if(covered){
						ans -= dist * vc[i].r;
					}

					dbg += dist;
				}
			} else {
				const double dist = 2*PI;
				P a(vc[i].c.x + vc[i].r,vc[i].c.y);
				bool covered = false;
				FOR(k,n) if(i != k){
					if(abs2(a-vc[k].c) < SQ(vc[k].r)){
						covered = true;
					}
				}

				if(covered){
					ans -= dist * vc[i].r;
				}
			}

			//assert(abs(dbg - 2*PI) < EPS);
		}

		printf("%.12f\n",ans);
	}

	return 0;
}