#include <bits/stdc++.h>
#define ll long long
using namespace std;

struct UnionFind {
    vector<int> par;
    int cnt;
    UnionFind(int n) : par(n, -1), cnt(n) {}
    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x != y) {
            if (par[y] < par[x]) swap(x, y);
            par[x] += par[y];
            par[y] = x;
            cnt--;
        }
    }
    int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return -par[find(x)]; }
    int size() { return cnt; }
};

struct Edge {
    int from, to;
    double cost;
    Edge(int s, int t, double c) : from(s), to(t), cost(c) {}
};

bool operator<(const Edge &a, const Edge &b) { return a.cost < b.cost; }

int main() {
    int n;
    while (cin >> n, 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);
        vector<Edge> g;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                double dx = x[i] - x[j];
                double dy = y[i] - y[j];
                double dz = z[i] - z[j];
                double dr = -r[i] - r[j];
                double d1 = dx * dx + dy * dy + dz * dz;
                double d2 = dr * dr;
                double d = max(0.0, dr + sqrt(d1));
                g.push_back(Edge(i, j, d));
            }
        }
        sort(g.begin(), g.end());
        double res = 0.0;
        for (int i = 0; i < g.size(); i++) {
            Edge e = g[i];
            if(!uf.same(e.from, e.to)){
                uf.unite(e.from, e.to);
                res += e.cost;
            }
        }
        cout << fixed << setprecision(3);
        cout << res << endl;
    }
    return 0;
}
