#include <algorithm>
#include <cmath>
#include <cstdio>
#include <tuple>
#include <vector>

#define int long long
#define dotimes(i, n) for (int i : range(n))

using namespace std;

class range {
  class iterator {
    int i, s;
  public:
    iterator(int i, int s): i(i), s(s) {}
    int& operator*() {
      return i;
    }
    void operator++() {
      i += s;
    }
    bool operator!=(iterator const& that) {
      return i < that.i;
    }
  };
  iterator b, e;
public:
  range(int e): b({0, 1}), e({e, 1}) {}
  range(int b, int e): b({b, 1}), e({e, 1}) {}
  range(int b, int e, int s): b({b, s}), e({e, s}) {}
  iterator begin() {
    return b;
  }
  iterator end() {
    return e;
  }
};

int rint() {
  int n;
  scanf("%lld", &n);
  return n;
}

void wint(int n) {
  printf("%lld\n", n);
}

template<typename T>
inline int size(T container) {
  return static_cast<int>(container.size());
}

template<typename T>
inline bool maxs(T& a, T const& b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template<typename T>
inline bool mins(T& a, T const& b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template<typename T>
inline T sq(T const &x) {
  return x * x;
}

struct union_find {
  vector<int> p;
  union_find(int n): p(n) {
    dotimes(x, n)
      p[x] = x;
  }
  int find(int x) {
    while (x != p[x]) {
      int y = p[x];
      p[x] = p[y];
      x = y;
    }
    return x;
  }
  bool eqv(int x, int y) {
    int a = find(x), b = find(y);
    return a == b;
  }
  bool unite(int x, int y) {
    int a = find(x), b = find(y);
    if (a == b)
      return false;
    if (!(a < b))
      swap(a, b);
    p[b] = a;
    return true;
  }
};

signed main() {
  for (;;) {
    const int n = rint();
    if (!n)
      break;
    struct {
      double x, y, z, r;
    } cells[n];
    dotimes(i, n)
      scanf("%lf%lf%lf%lf", &cells[i].x, &cells[i].y, &cells[i].z, &cells[i].r);
    union_find uf(n);
    double dists[n][n];
    dotimes(j, n) dotimes(i, j) {
      dists[j][i] = sqrt(sq(cells[i].x - cells[j].x) + sq(cells[i].y - cells[j].y) + sq(cells[i].z - cells[j].z));
      if (dists[j][i] <= cells[i].r + cells[j].r)
        uf.unite(i, j);
    }
    pair<int, int> p[n];
    dotimes(i, n) {
      p[i].first = i;
      p[i].second = uf.find(i);
    }
    sort(p, p + n, [](auto const &a, auto const &b) { return a.second < b.second; });
    int x = p[0].second;
    int c = 0;
    p[0].second = 0;
    dotimes(i, n-1) {
      int y = p[i+1].second;
      if (x != y) {
        c++;
        x = y;
      }
      p[i+1].second = c;
    }
    sort(p, p + n);
    c++;
    double ds[c][c];
    dotimes(j, c) dotimes(i, j) ds[j][i] = 200;
    dotimes(j, n) dotimes(i, j) if (p[i].second != p[j].second) {
      int a = p[i].second, b = p[j].second;
      if (a > b)
        swap(a, b);
      mins(ds[b][a], dists[j][i] - (cells[i].r + cells[j].r));
    }
    vector<tuple<double, int, int>> edges;
    edges.reserve(n * (n - 1) / 2);
    dotimes(j, c) dotimes(i, j) edges.emplace_back(ds[j][i], i, j);
    sort(edges.begin(), edges.end());
    int k = c;
    double r = 0;
    union_find uf2(c);
    for (auto &&e : edges) {
      if (k == 1)
        break;
      if (uf2.unite(get<1>(e), get<2>(e))) {
        r += get<0>(e);
        k--;
      }
    }
    printf("%.3lf\n", r);
  }
  return 0;
}



Measured memory_bytes: 2916