#include <bits/stdc++.h>
#define rep(i, start, end) for (long long i = start; i < end; ++i)
#define repreverse(i, start, end) for (long long i = start; i >= end; --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ((long long)(x).size())
#define lcm(a, b) ((a) / __gcd((a), (b)) * (b))
using namespace std;
using ll = long long;
using ld = long double;
using vll = vector<ll>;
using vllvll = vector<vll>;
using pll = pair<ll, ll>;
template<class T>void print1d(T x,ll n=-1){if(n==-1)n=x.size();rep(i,0,n){cout<<x[i]<<' ';}cout<<'\n';}
template<class T>void print2d(T x,ll r=-1,ll c=-1){if(r==-1)r=x.size();if(c==-1)c=x[0].size();rep(i,0,r)print1d(x[i],c);}
template<class T, class U>bool haskey(T mp, U key) { return mp.find(key) != mp.end(); }
template<class T, class U>bool isin(T el, U container) { return find(all(container), el) != container.end(); }
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T>ld deg2rad(T deg) { return M_PI * deg / 180.0; }
template<class T>ld rad2deg(T rad) { return 180.0 * rad / M_PI; }
ll intpow(ll a,ll n){ll p=1;while(n){if(n&1)p*=a;a*=a;n>>=1;}return p;}
const long double pi = M_PI;
const long long big = 1LL << 50;
const long long inf = 1LL << 60;
const long long mod = 1e9 + 7;

class UnionFind
{   
public:
    static const int N_MAX = 1000000;
    int par[N_MAX];
    int n;
    
    UnionFind(int n)
        : n{n}
    {
        for (int i = 0; i < n; ++i) {
            par[i] = i;
        }
    }
    
    int root(int x)
    {
        if (par[x] == x) {
            return x;
        }
        return par[x] = root(par[x]);
    }
    
    bool same(int x, int y)
    {
        return root(x) == root(y);
    }
    
    void unite(int x, int y)
    {
        int rx = root(x);
        int ry = root(y);
        if (rx == ry) {
            return;
        }
        par[ry] = root(x);
        return;
    }
    
    int groups()
    {
        int cnt = 0;
        for (int i = 0; i < n; ++i) {
            if (root(i) == i)
            ++cnt;
        }
        return cnt;
    }
};


class Edge
{
public:
    ll from;
    ll to;
    ld cost;
    Edge() : to{0}, cost{0} {}
    Edge(ll to, ld cost) : to{to}, cost{cost} {}
    Edge(ll from, ll to, ld cost) : from{from}, to{to}, cost{cost} {}
    bool operator<(const Edge& rhs) const {
        return cost < rhs.cost;
    }
};

ld kruskal(vector<Edge>& edges, long long n)
{
    sort(edges.begin(), edges.end());
    UnionFind uf(n);
    ld min_cost = 0;

    for (Edge e : edges) {
        if (! uf.same(e.from, e.to)) {
            uf.unite(e.from, e.to);
            min_cost += e.cost;
        }
    }
    return min_cost;
}


ld calc(ld x1, ld y1, ld z1, ld x2, ld y2, ld z2)
{
        ld res = powl(x1-x2, 2) + powl(y1-y2, 2) + powl(z1-z2, 2);
        return sqrtl(res);
}

int main()
{
        ll n = 1000;
        do {
                cin >> n;
                if (n == 0) break;
                vector<ld> x(n), y(n), z(n), r(n);
                vector<Edge> edges;
                rep(i, 0, n) {
                        cin >> x[i] >> y[i] >> z[i] >> r[i];
                }

                rep(i, 0, n) {
                        rep(j, i+1, n) {
                                ld dist = calc(x[i], y[i], z[i], x[j], y[j], z[j]);
                                if (r[i] + r[j] > dist) {
                                        dist = 0.0;
                                } else {
                                        dist -= r[i] + r[j];
                                }
                                Edge e(i, j, dist);
                                edges.push_back(e);
                        }
                }
                ld ans = kruskal(edges, n);
                cout << fixed << setprecision(3) << ans << endl;

        } while (n);
}


Measured memory_bytes: 3540