### constants

DELTA = 1e-7
MAX_CAN = 100000

SIGNS = [
  [ 1, 1, 1], [ 1, 1, -1], [ 1, -1, 1], [ 1, -1, -1],
  [-1, 1, 1], [-1, 1, -1], [-1, -1, 1], [-1, -1, -1]
]

### subroutines

def max_r(pts, x, y, z)
  max_r2 = 0.0

  pts.each do |x0, y0, z0|
    r2 = (x - x0) ** 2 + (y - y0) ** 2 + (z - z0) ** 2
    max_r2 = r2 if max_r2 < r2
  end

  Math.sqrt(max_r2)
end

def solve_by_partition(pts)
  candidate = []
  candidate << [0.0, 50.0, 50.0, 50.0]

  count = 1
  size = 100.0
  min_sofar = 1e50
  root3 = Math.sqrt(3.0)

  while size > DELTA
    size = size / 2
    k = 0
    new_candidate = []
    for i in (0...count)
      SIGNS.each do |dx ,dy, dz|
        r0, x0, y0, z0 = candidate[i]
        sizeh = size / 2
        x0 += dx * sizeh
        y0 += dy * sizeh
        z0 += dz * sizeh
        r = max_r(pts, x0, y0, z0)
        min_sofar = r if min_sofar > r
        next if r > min_sofar + sizeh * root3
        break if k >= MAX_CAN

        new_candidate[k] = [r, x0, y0, z0]
        k += 1
      end
      break if k >= MAX_CAN
    end
    count = k
    (0...count).each{|i| candidate[i] = new_candidate[i]}
    candidate.sort
  end

  min_sofar
end

### main

loop do
  n = gets.to_i
  break if n == 0

  pts = n.times.map{gets.split.map(&:to_f)}
  #p pts

  puts "%.5f" % solve_by_partition(pts)
end