Given a list of points in two-dimensional space, you want to execute a function in Haskell to find the distance between the two nearest points. example: Input: project [(1,5), (3,4), (2,8), (-1,2), (-8,6), (7,0), (1,5), (5.5), (4.8), (7.4)] Output: 2.0
Suppose that the distance between the two farthest points in the list does not exceed 10,000.
Here is my code:
import Data.List import System.Random sort_ :: Ord a => [a] -> [a] sort_ [] = [] sort_ [x] = [x] sort_ xs = merge (sort_ left) (sort_ right) where (left, right) = splitAt (length xs `div` 2) xs merge [] xs = xs merge xs [] = xs merge (x:xs) (y:ys)= if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys project :: [(Float,Float)] -> Float project [] = 0 project (x:xs)= if null (xs) then error "The list have only 1 point" else head(sort_(dstList(x:xs))) distance :: (Float,Float)->(Float,Float) -> Float distance (x1,y1) (x2,y2) = sqrt((x1 - x2)^2 + (y1 - y2)^2) dstList :: [(Float,Float)] -> [Float] dstList (x:xs)= if length xs == 1 then (dstBetween x xs):[] else (dstBetween x xs):(dstList xs) dstBetween :: (Float,Float) -> [(Float,Float)] -> Float dstBetween pnt (x:xs)= if null (xs) then distance pnt x else minimum ((distance pnt ):((dstBetween pnt xs)):[]) {- Calling generator to create a file created at random points -} generator = do putStrLn "Enter File Name" file <- getLine g <- newStdGen let pts = take 1000 . unfoldr (Just . (\([a,b],c)->((a,b),c)) . splitAt 2) $ randomRs(-1,1) g :: [(Float,Float)] writeFile file . show $ pts {- Call the main to read a file and pass it to the function of project The function of the project should keep the name 'project' as described in the statement -} main= do putStrLn "Enter filename to read" name <- getLine file <- readFile name putStrLn . show . project $ readA file readA::String->[(Float,Float)] readA = read
I can run the program, as in the example, or using the generator as follows:
the haskell should type โgeneratorโ in the interpreter, the program will request here a file name containing a thousand points. and after the file is generated in the Haskell interpreter, it should write main and ask for the name of the file, which is the name of the file created with the "generator".
The problem is that for 1000 points randomly created by my program, it takes a lot of time, about 3 minutes, on a computer with a dual-core processor. What am I doing wrong? How can I optimize my code to work faster?