#include <bits/stdc++.h>
using namespace std;
using ld = long double;

struct edge {
	int from, to;
	ld cost;
	edge() {}
	edge(int from, int to, ld cost) : from(from), to(to), cost(cost) {}
};

bool operator<(const edge& l, const edge& r){
	return l.cost < r.cost;
}

class UnionFind {
	vector<int> data;
	vector<int> rank;
	int root(int a) {
		return data[a] < 0 ? a : data[a] = root(data[a]);
	}
public:
	UnionFind(int n) : data(n, -1), rank(n, 1) {}
	bool Find(int a, int b) {
		return root(a) == root(b);
	}
	void Union(int a, int b) {
		a = root(a);
		b = root(b);
		if (a == b) return;
		if (rank[a] < rank[b]) {
			data[a] += data[b];
			data[b] = a;
		}
		else {
			data[b] += data[a];
			data[a] = b;
			if (rank[a] == rank[b]) rank[b]++;
		}
	}
	int Size(int a) {
		return -data[root(a)];
	}
	int Rank(int a) {
		return rank[root(a)];
	}
};

int main()
{
	cin.sync_with_stdio(false);
	cout << fixed << setprecision(3);
	int n;
	while (cin >> n, n) {
		vector<ld> 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<edge> es;
		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++) {
				ld dx = x[j] - x[i], dy = y[j] - y[i], dz = z[j] - z[i];
				es.emplace_back(i, j, max((ld)0, sqrtl(dx * dx + dy * dy + dz * dz) - r[i] - r[j]));
			}
		}
		sort(es.begin(), es.end());
		ld res = 0;
		UnionFind uf(n);
		for (auto e : es) {
			if (uf.Find(e.from, e.to)) {
				continue;
			}
			res += e.cost;
			uf.Union(e.from, e.to);
		}
		cout << res << endl;
	}
	return 0;
}