Comment detail

議席数をドント方式で (Nested Flatten)
たまには合成モナドをつかって。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Data.List
import Control.Monad.State
import Control.Monad.Writer

data Vote = V {idx::Int, num::Double, poll::Double} deriving Show
type Votes = [Vote]
type Proc a = StateT Votes (Writer [Int]) a

runProc :: Proc () -> Votes -> [Int]
runProc proc vs = fmt $ group $ sort $ snd $ runWriter $ evalStateT proc vs
  where fmt  = map length . fmt' 1 . map (\x -> (head x, x))
        fmt' _ [] = []
        fmt' n ((x,y):xs) = if n == x then y:fmt' (n + 1) xs else []:fmt' (n + 1) ((x,y):xs)

mkProc :: Int -> Proc ()
mkProc seats = if seats == 0 then return ()
               else do vs <- get
                       let (V i n p:ts) = sortBy (\x y -> f y `compare` f x) vs
                         in tell [i] >> put ((V i (n + 1) p):ts) >> mkProc (seats - 1)
  where f x = poll x / (num x + 1)

f x xs = runProc (mkProc x) (zipWith (\x y -> V x 0 y) [1..(length xs)] xs)

Index

Feed

Other

Link

Pathtraq

loading...