#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;

template <typename T>
struct Kruskal {
  struct UnionFind {
    int n;
    vector<int> rank, par;
    UnionFind() {}
    UnionFind(int n) : n(n), rank(n, 1), par(n) {
      iota(par.begin(), par.end(), 0);
    }
    int root(int x) {
      return par[x] == x ? x : par[x] = root(par[x]);
    }
    bool merge(int x, int y) {
      if ((x = root(x)) == (y = root(y))) return false;
      if (rank[x] < rank[y]) swap(x, y);
      rank[x] += rank[y];
      par[y] = x;
      return true;
    }
    bool same(int x, int y) {
      return root(x) == root(y);
    }
    int size(int x) {
      return rank[root(x)];
    }
  };
  struct edge {
    int from, to; T cost;
    edge() {}
    edge(int f, int t, T c) : from(f), to(t), cost(c) {}
    friend ostream& operator<<(ostream& os, edge &e) {
      return os << e.from << " " << e.to << " " << e.cost;
    }
  };

  int n;
  vector<edge> es;
  Kruskal() {}
  Kruskal(int n) : n(n) {}

  void add_edge(int from, int to, T cost) {
    es.emplace_back(from, to, cost);
  }
  T mst() {
    T res = 0;
    UnionFind uf(n);
    sort(es.begin(), es.end(), [&](edge a, edge b) {
      return a.cost < b.cost;
    });
    for (auto &e : es) if (uf.merge(e.from, e.to)) {
      res += e.cost;
    }
    return res;
  }
};

double len(double x, double y, double z) {
  return sqrt(x * x + y * y + z * z);
}

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(3);
  
  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];
    }

    Kruskal<double> K(n);
    for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (j != i) {
        K.add_edge(i, j, max(0., len(x[i] - x[j], y[i] - y[j], z[i] - z[j]) - r[i] - r[j]));
    }
    cout << K.mst() << endl;
  }

  return 0;
}
