SSブログ

Haskell でドント方式の議席数配分 [Haskell]

「どう書く?org - 議席数をドント方式で」 [1] 用に、これは無限リストだなーと思って Haskell で書いたのだけど書いているうちに先を越されて、それより発想が違うわけでも短いわけでもなかったので(でも読みやすいかも)投稿せずにこっちにおいておくことにした。

type Party = Int
type Votes = (Rational, Party)

merge :: Ord a => [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x > y = x:merge xs (y:ys)
merge (x:xs) (y:ys) | x < y = y:merge (x:xs) ys
merge (x:xs) (y:ys) | x == y = x:y:merge xs ys

mergeList :: Ord a => [[a]] -> [a]
mergeList = foldl merge []

voteSeq :: Votes -> [Votes]
voteSeq (v, n) = [((v / x), n) | x <- [1..]]

toVotes :: [Rational] -> [Votes]
toVotes vs = zip vs [1..]

dhondtSeq :: Int -> [Votes] -> [Votes]
dhondtSeq limit vs = take limit $ mergeList [voteSeq x | x <- vs]

numSeat :: Party -> [Votes] -> Int
numSeat p vs = length [x | (x, n) <- vs, n == p]

dhondt :: Int -> [Rational] -> [Int]
dhondt limit vs =
  [numSeat n ds | n <- [1..length vs]]
     where vs' = toVotes vs
           ds = dhondtSeq limit vs'

merge と mergeList はひょっとしたら標準関数を再発明しているかもしれない。
あと Haskell で有理数を使うのは単に Rational って型を書けばよいだけだということを知ったので前回の小町算も Float じゃなくて Rational にすればよかった。

[1] http://ja.doukaku.org/26/


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

Haskell で小町算F# で STUDENT ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。