{-# LANGUAGE BangPatterns, Safe #-}
{-# Options_GHC -O2 #-}
--import qualified Data.ByteString.Char8 as C
import Data.Maybe
import Data.Int
import Control.Monad
import Control.Monad.ST
import Data.Array.ST.Safe
import Data.Array
import qualified Data.Array.Unboxed as UA
import Data.List
import Text.Printf

ri :: String -> Int
ri = read 

pmGen :: Int32 -> Int32
pmGen x = fromIntegral $! mod ((16807::Int64) * fromIntegral x) 2147483647

randoms :: Int32 -> [Int32]
randoms = iterate pmGen

randomPermutation :: [Int32] -> Int -> ([Int32], [Int32])
randomPermutation rnds n = runST $ do
  let 
    (r, t) = splitAt (n - 1) rnds
    !n32 = fromIntegral n :: Int32
  p <- newListArray (1, n) [1 .. n32] :: ST s (STUArray s Int Int32)
  forM_ (zip [n, pred n .. 2] r) $ \ (!i, !k) -> do
    let !j = succ $ mod (fromIntegral k) i
    temp <- readArray p i
    readArray p j >>= writeArray p i
    writeArray p j temp
  pe <- getElems p
  return (pe, t)

randomShuffle :: [a] -> [Int32] -> ([a], [Int32])
randomShuffle a rnds = (elems $ array (1, fromIntegral n) $ zip p a, t)
  where
    !n = length a 
    (p, t) = randomPermutation rnds n

eps :: Double 
eps = 1e-10

--(Line a b c): a * x + b * y = c
type Point = (Double, Double)
data Line = Line !Double !Double !Double
data Circle = Circle !Double !Double !Double

line :: Point -> Point -> Line
line (!x1, !y1) (!x2, !y2) = Line a b (a * x1 + b * y1)
  where
    !a = y2 - y1
    !b = x1 - x2

dist :: Point -> Point -> Double
dist (!x1, !y1) (!x2, !y2) = sqrt $! (x1 - x2) ^ 2 +  (y1 - y2) ^ 2

pointInCircle :: Point -> Circle -> Bool
pointInCircle p (Circle !x !y !r) = dist p (x, y) - r < eps

linesIntersection :: Line -> Line -> Maybe (Double, Double)
linesIntersection (Line a1 b1 c1) (Line a2 b2 c2)
  | abs d < eps = Nothing
  | otherwise = let !d' = 1.0 / d in Just ( d' * (c1 * b2 - c2 * b1), d' * (a1 * c2 - a2 * c1))
  where
    !d = a1 * b2 - a2 * b1

circle :: Point -> Point -> Circle
circle p1@(!x1, !y1) (!x2, !y2) = Circle x y (dist (x, y) p1)
  where
    !x = (x1 + x2) * 0.5
    !y = (y1 + y2) * 0.5

circumcircle ::  Point -> Point -> Point -> Maybe Circle
circumcircle p1 p2 p3 = liftM (\ p@(!x, !y) -> Circle x y (dist p p1)) $ linesIntersection (cp p1 p2) (cp p2 p3)
  where
    cp :: Point -> Point -> Line
    cp (!x1, !y1) (!x2, !y2) = Line a b (a * xm + b * ym)
      where
        !xm = (x1 + x2) * 0.5
        !ym = (y1 + y2) * 0.5
        !a = x2 - x1
        !b = y2 - y1


minimalEnclosingBallP2 :: [Point] -> Point -> Point -> Circle
minimalEnclosingBallP2 p q1 q2 = foldl' f (circle q1 q2) p 
  where
    f :: Circle -> Point -> Circle
    f c p = if pointInCircle p c then c else fromJust $ circumcircle q1 q2 p

minimalEnclosingBallP1 :: [Point] -> Point -> [Int32] -> (Circle, [Int32])
minimalEnclosingBallP1 p q1 rnds = (fst $ foldl' f ( circle q1 p', [p']) ps, rnds')
  where
    ( (p' : ps), rnds') = randomShuffle p rnds
    f :: (Circle, [Point]) -> Point -> (Circle, [Point])
    f (c, l) p = if pointInCircle p c then (c, p:l) else (minimalEnclosingBallP2 l q1 p, p:l) 

minimalEnclosingBall :: [Point] -> [Int32] -> Circle
minimalEnclosingBall p rnds = let (c, _, _) = foldl' f (circle p1 p2, [p1,p2], rnds') ps in c
  where
    ( (p1 : p2 : ps), rnds') = randomShuffle p rnds
    f :: (Circle, [Point], [Int32]) -> Point -> (Circle, [Point], [Int32])
    f (c, l, r) p = if pointInCircle p c then (c, p:l, r) else let (c', r') = minimalEnclosingBallP1 l p r in (c', p:l, r') 

solve :: [Int] -> Double
solve (n:a) 
  | n <= 1 = 0.0
  | otherwise = r
  where
    b = tuple2 $ take (2 * n) a
    tuple2 :: [Int] -> [(Double, Double)]
    tuple2 [] = []
    tuple2 (x:y:l) = (fromIntegral x, fromIntegral y) : tuple2 l
    (Circle _ _ !r) = minimalEnclosingBall b (randoms 7777)

main :: IO ()
main = printf "%.20f\n" . solve . map ri . words =<< getContents


Measured memory_bytes: 1020