//  atcodder.xcode
//  main.cpp
//  Created by conan1024hao on 2019/11/07.
//  Copyright © 2019 conan1024hao. All rights reserved.
//  専用ライブラリ
#pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
using namespace std;
typedef long long int ll;
typedef pair<ll,ll>P;
#define INF 10e16
#define MOD 1000000007
#define rep(i, a, n) for (ll i = a; i < (ll)(n); i++)
#define fi first
#define se second
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define PI acos(-1.0)
long long GCD(long long a, long long b) { return b ? GCD(b, a%b) : a; }
long long LCM(long long a, long long b)  {return a/GCD(a,b)*b;}
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int cmp(P a,P b){
        if(a.fi!=b.fi)
        return a.fi>b.fi;
        else
        return a.se<b.se;
}
//---------------------------------------------------------------------------
struct unionfind{
    vector<int> rank,parent,size;
    unionfind(int n){
        for(int i=0;i<n;i++){
            rank.push_back(1);//树的高度
            parent.push_back(i);//根
            size.push_back(1);//树大小
        }
    }
    int getroot(int x){
        if(parent[x]==x)
            return x;
        return parent[x]=getroot(parent[x]);//押平路径加速以后的查找
    }
    bool issame(int a,int b){
        return getroot(a)==getroot(b);
    }
    void unite(int a,int b){
        a=getroot(a);
        b=getroot(b);
        if(a==b)
            return;
        else if(rank[a]>rank[b]){ //合并到高的树下
            parent[b]=a;
            size[a]+=size[b];
        }
        else if(rank[a]==rank[b]){
            parent[b]=a;
            rank[a]++;
            size[a]+=size[b];
        }
        else{
            parent[a]=b;
            size[b]+=size[a];
        }
    }
};
//---------------------------------------------------------------------------
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------
    int n;
    cin>>n;
    while(n){
        vector<double> x(n),y(n),z(n),r(n);
        for(int i=0;i<n;i++){
            cin>>x[i]>>y[i]>>z[i]>>r[i];
        }
        unionfind uf(n);
        double sum2=0;
        vector<pair<double,pair<int,int> > > rx;
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                double minx=INF;
                chmin(minx,mmax(0,sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]))-r[i]-r[j]));
                rx.push_back(make_pair(minx,make_pair(i,j)));
            }
        }
        sort(all(rx));
        for(int i=0;i<rx.size();i++){
            if(!uf.issame(rx[i].se.fi,rx[i].se.se)){
                sum2+=rx[i].fi;
                uf.unite(rx[i].se.fi,rx[i].se.se);
            }
        }
        printf("%.3lf\n",sum2);
        cin>>n;
    }
    //-------------------------------
    return 0;
}
//---------------------------------------------------------------------------



Measured memory_bytes: 3312