Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module Main where
- import Data.List
- import Data.Ord
- -- For testing purpose
- import Test.QuickCheck
- import Test.QuickCheck.Gen
- import System.Random
- type Z = Integer
- type Pt = (Z,Z)
- type Dir = Pt
- type Cost = Z
- sumV :: [Pt] -> Pt
- sumV = foldr addV (0,0)
- addV :: Pt -> Pt -> Pt
- addV (x,y) (u,v) = (x+u,y+v)
- divV :: Pt -> Z -> Pt
- divV (x,y) d = (x `div` d,y `div` d)
- second :: (a,b,c) -> b
- second (_,y,_) = y
- third :: (a,b,c) -> c
- third (_,_,z) = z
- mean :: [Pt] -> Pt
- mean xs = sumV xs `divV` genericLength xs
- dir0 :: [Dir]
- dir0 = [(-1,1) ,(0,1) ,(1,1)
- ,(-1,0) ,(1,0)
- ,(-1,-1),(0,-1),(1,-1)]
- -- Tweaking this would result 2x speed-up
- restrict :: Dir -> [Dir] -> [Dir]
- restrict d ds = ds
- d :: Pt -> Pt -> Z
- d (x,y) (u,v) = max (abs (x-u)) (abs (y-v))
- costAt :: [Pt] -> Pt -> Cost
- costAt xs p = sum $ map (d p) xs
- cand :: Pt -> [Dir] -> [Pt]
- cand p ds = map (addV p) ds
- step :: [Pt] -> (Pt,Cost,[Dir]) -> (Pt,Cost,[Dir])
- step xs (p,c,ds)
- | c' < c = (p',c', restrict d ds)
- | otherwise = (p ,c , [])
- where
- (p',c',d) = minimumBy (comparing second) $ map (look xs p) ds
- look :: [Pt] -> Pt -> Dir -> (Pt,Cost,Dir)
- look xs p d = (p',costAt xs p',d)
- where p' = p `addV` d
- -- seems like a reasonable guess
- start :: [Pt] -> (Pt,Cost,[Dir])
- start xs = (p0,c0,dir0)
- where
- p0 = mean xs
- c0 = costAt xs p0
- opt :: [Pt] -> (Pt,Cost,[Dir])
- opt xs = head $ dropWhile (not . null . third) $ iterate (step xs) $ start xs
- optDebug :: [Pt] -> (Bool,[(Pt,Cost,[Dir])])
- optDebug xs = (check xs p,head ns : ms)
- where
- (ms,ns) = span (not . null . third) $ iterate (step xs) $ start xs
- (p,c,_) = head ns
- -------------------------------------------------
- -- test code
- -------------------------------------------------
- check :: [Pt] -> Pt -> Bool
- check xs p = costAt xs p <= minimum (map (costAt xs) (cand p dir0))
- prop_opt :: [Pt] -> Bool
- prop_opt xs = let (p,c,_) = opt xs
- in check xs p
- rollDice :: IO Int
- rollDice = getStdRandom random
- randomPts :: Int -> IO [Pt]
- randomPts n = do rollDice
- gen <- getStdGen
- return $ unGen (vectorOf n arbitrary) gen 1000
- main = do xs <- randomPts 100000
- print $ optDebug xs
- sample0,sample1,sample2 :: [Pt]
- sample0 = [(0,0)]
- sample1 = [(0,0),(1,1)]
- sample2 = [(0,2),(1,2),(2,2)
- , (1,1)
- , (2,0) ]
- sample3 = [(0,3)
- ,(0,2),(1,2)
- ,(0,1),(1,1),(2,1)
- ,(0,0),(1,0),(2,0),(3,0)]
- sample4 = [(0,3)
- ,(0,2),(1,2)
- ,(0,1),(1,1),(2,1)
- ,(0,0),(1,0),(2,0),(3,0)]
- sample5 = [ (-3, 0), (-2, 0), (-1, 0), (0, 0), (10, 0), (50, 0) ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement