比較しないソートの作成
Posted feedbacks - Haskell
クイックソート的にやりました。
しかし、終了条件が悪いので遅いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import Data.List (group,sort)
main :: IO ()
main = print $ qsort (-1) 10 [-1,9,4,8,9,6,3,9,5,2]
uniq :: Ord a => [a] -> [a]
uniq ns = map head $ group $ sort ns
qsort :: Integral a => a -> a -> [a] -> [a]
qsort _ _ [] = []
qsort _ _ ns | length (uniq ns) == 1 = ns
qsort min max ns = let mid = div (max + min) 2
in qsort min mid [y | y <- ns, y < mid] ++ qsort mid max [y | y <- ns, y >=mid ]
|
データのレンジがわかっているのであらかじめ順番に並んでいる結果のリストから入力リストにはいっているものだけ残すという方法です…
入力リストの要素数は必要ありません…
1 2 3 4 5 6 | module Main where
sort_noComp :: (Num a, Ord a, Enum a)=> a -> a -> Int -> [a] -> [a]
sort_noComp min max len xs = filter (\x -> elem x xs) [min..max]
main = print $ sort_noComp 1 9 8 [4, 8, 9, 6, 3, 9, 5, 2]
|
短くする方向で書いてみました。個数は要りません。
1 | mysort min max ns = concat [filter (== x) ns | x <- [min..max]]
|
あぁ、情けなし。
1 2 3 4 5 6 7 8 9 10 11 | module Main where
sort_noComp min max xs = foldr (addCount) (map (flip (,) $ 0) [min..max]) xs >>= \(x, c) -> replicate c x
where
addCount :: Int -> [(Int, Int)] -> [(Int, Int)]
addCount i [] = []
addCount i ((j, x):xs)
| i == j = (j, x + 1) : xs
| otherwise = (j, x) : addCount i xs
main = print $ sort_noComp 1 9 [4, 8, 9, 6, 3, 9, 5, 2]
|
counting sortを実装しました。 > ghc --make -O2 CountingSort.hs > ./CountingSort
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import qualified Data.Map as M
import Control.Monad.State
counter min max xs = recur (M.fromAscList $ zip [min..max] (repeat 0)) xs
where recur ctr [] = M.toAscList ctr
recur ctr (x:xs) = recur (M.update (\v -> Just (succ v)) x ctr) xs
countingSort :: (Ord a, Enum a, Num a) => a -> a -> [a] -> [a]
countingSort min max xs = let ctr = counter min max xs
result = M.fromAscList $ zip [0..len] (repeat 0)
in evalState (countingSort_S min ctr) (0,result)
where len = fromIntegral $ length xs - 1
countingSort_S :: (Ord a, Enum a, Num a) => a -> [(a,a)] -> State (a,M.Map a a) [a]
countingSort_S _ [] = get >>= return . M.elems . snd
countingSort_S min ((x,y):xs) = do
forM_ [1..y] update
countingSort_S min xs
where update _ = do
(index,result) <- get
put (succ index, M.update f index result)
f _ = Just x
main :: IO ()
main = do
print $ countingSort (-1) 10 [-1,9,4,8,9,6,3,9,5,2]
print $ countingSort (-100000) 100000 [-100000..100000]
|
ちょっと修正しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import qualified Data.Map as M
import Control.Monad.State
counter min max xs = recur (M.fromAscList $ zip [min..max] (repeat 0)) xs
where recur ctr [] = M.toAscList ctr
recur ctr (x:xs) = recur (M.update (\v -> Just (succ v)) x ctr) xs
countingSort :: (Ord a, Enum a, Num a) => a -> a -> [a] -> [a]
countingSort min max xs = let ctr = counter min max xs
in evalState (countingSort_S min ctr) []
where len = fromIntegral $ length xs - 1
countingSort_S :: (Ord a, Enum a, Num a) => a -> [(a,a)] -> State [a] [a]
countingSort_S _ [] = get >>= return . reverse
countingSort_S min ((x,y):xs) = do
forM_ [1..y] (\_ -> get >>= \xs -> put $ x:xs)
countingSort_S min xs
main :: IO ()
main = do
print $ countingSort (-1) 10 [-1,9,4,8,9,6,3,9,5,2]
print $ countingSort (-100000) 100000 [-100000..100000]
|
counting sort 配列を使って素朴に。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import Array
import List
countingSort lower upper n xs = elems $ array (1,n) ys where
lower1 = lower - 1
-- キーの出現回数
a = accumArray (+) 0 (lower1,upper) [(x,1)| x <- xs]
-- 出現回数の累計
b = array (lower1,upper) $ (lower1,0): [(i,b!(i-1)+a!i)| i <- [lower..upper]]
-- ソート後のキーの位置の計算
(_,ys) = mapAccumL f b xs
f c x = (c//[(x,(c!x)-1)], (c!x,x))
{-
> countingSort (-1) 10 10 [-1,9,4,8,9,6,3,9,5,2]
[-1,2,3,4,5,6,8,9,9,9]
-}
|





sweetie089 #6628() Rating3/3=1.00
[ reply ]