#include<cmath>
#include<queue>
#include<cstdio>

using namespace std;

double hypot3(double x,double y,double z){
	return sqrt(x*x+y*y+z*z);
}

struct Cell{
	double x,y,z,r;
};

struct Edge{
	int u,v;
	double cost;
	Edge(int _u,int _v,double c):u(_u),v(_v),cost(c){}
	bool operator<(const Edge &e)const{ return cost<e.cost; }
};

int uf[100];
int UF_Root(int i){ return ~uf[i]?uf[i]=UF_Root(uf[i]):i; }
bool UF_Find(int i,int j){ return UF_Root(i)==UF_Root(j); }
void UF_Union(int i,int j){ uf[UF_Root(j)]=UF_Root(i); }

int main(){
	for(int n;scanf("%d",&n),n;){
		Cell c[100];
		for(int i=0;i<n;i++){
			scanf("%lf%lf%lf%lf",&c[i].x,&c[i].y,&c[i].z,&c[i].r);
			uf[i]=-1;
		}

		priority_queue<Edge> pq;
		for(int i=0;i<n;i++)for(int j=i+1;j<n;j++){
			double d=hypot3(c[i].x-c[j].x,c[i].y-c[j].y,c[i].z-c[j].z)-(c[i].r+c[j].r);
			if(d<0)	d=0;
			pq.push(Edge(i,j,-d));
		}

		int cnt=0;
		double total=0;
		while(!pq.empty() && cnt<n-1){
			Edge e=pq.top();	pq.pop();
			if(!UF_Find(e.u,e.v)){
				UF_Union(e.u,e.v);
				total+=-e.cost;
				cnt++;
			}
		}

		printf("%.3f\n",total);
	}

	return 0;
}