#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <iomanip>

typedef long long ll;
const ll MOD = 1e9 + 7;
const long long INF = 1LL<<60;
const double PI=3.14159265358979323846;
const int NMAX=100005;
using namespace std;

struct UnionFind{
    int root[101];
    
    UnionFind(){
        for(int i = 0; i < 101; i++){
            root[i] = i;
        }
    }

    int getRoot(int x){
        if(root[x] == x) return x;
        root[x] = getRoot(root[x]);
        return root[x];
    }

    bool isSame(int x, int y){
        int px = getRoot(x);
        int py = getRoot(y);
        if(px == py) return true;
        else return false;
    }

    void unite(int x, int y){
        if(isSame(x,y)) return;
        int px = getRoot(x);
        int py = getRoot(y);
        root[py] = px;
    }
};

void solve(int 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];
    }
    vector<pair<double, pair<int,int> > > edge;
    for(int i = 0; i < n; i++){
        for(int j = i+1; j < n; j++){
            double d = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
            d = sqrt(d);
            d = d - r[i] - r[j];
            if(d < 0) d = 0;
            edge.push_back(make_pair(d,make_pair(i,j)));
        }
    }
    sort(edge.begin(), edge.end());
    
    UnionFind uf;

    double ans = 0;
    for(int i = 0; i < edge.size(); i++){
        auto d = edge[i].first;
        auto path = edge[i].second;
        if(uf.isSame(path.first, path.second) == true) continue;
        uf.unite(path.first, path.second);
        ans += d;
    }

    cout << std::fixed << std::setprecision(3) <<  ans << endl;
    return;
}

int main(){
    while(true){
        int n;
        cin >> n;
        if(n == 0) break;
        solve(n);
    }
    return 0;
}
