4 , module Voting.Protocol.Utils
6 , Monad(..), forM, mapM, replicateM, unless, when
8 , Either(..), either, isLeft, isRight
9 , ($), (.), id, const, flip
13 , Monoid(..), Semigroup(..)
18 , Num, Fractional(..), Integral(..), Integer, fromIntegral
33 import Control.Applicative (Applicative(..))
35 import Control.Monad.Trans.Class
36 import Control.Monad.Trans.Except
37 import Control.Monad.Trans.State.Strict
39 import Data.Either (Either(..), either, isLeft, isRight)
40 import Data.Eq (Eq(..))
42 import Data.Functor ((<$>))
44 import Data.Maybe (Maybe(..))
45 import Data.Monoid (Monoid(..))
46 import Data.Ord (Ord(..))
47 import Data.Semigroup (Semigroup(..))
48 import Data.String (String)
49 import Data.Text (Text)
50 import Data.Word (Word8)
52 import Prelude (Num(..), Fractional(..), Integral(..), Integer, undefined, fromIntegral)
53 import System.Random (mkStdGen)
55 import Text.Show (Show(..))
57 import Voting.Protocol.Utils
59 debug :: Show a => String -> a -> a
60 debug msg x = trace (msg<>": "<>show x) x
62 -- | @'nCk' n k@ returns the number of combinations
63 -- of size 'k' from a set of size 'n'.
65 -- Computed using the formula:
66 -- @'nCk' n (k+1) == 'nCk' n (k-1) * (n-k+1) / k@
67 nCk :: Integral i => i -> i -> i
68 n`nCk`k | n<0||k<0||n<k = undefined
71 go i acc = if k' < i then acc else go (i+1) (acc * (n-i+1) `div` i)
72 -- Use a symmetry to compute over smaller numbers,
73 -- which is more efficient and safer
74 k' = if n`div`2 < k then n-k else k
76 -- | @'combinOfRank' n k r@ returns the @r@-th combination
77 -- of @k@ elements from a set of @n@ elements.
78 -- DOC: <http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf>, p.26
79 combinOfRank :: Integral i => i -> i -> i -> [i]
80 combinOfRank n k rk | rk<0||n`nCk`k<rk = undefined
81 | otherwise = for1K 1 1 rk
83 for1K i j r | i < k = uptoRank i j r
84 | i == k = [j+r] -- because when i == k, nbCombs is always 1
86 uptoRank i j r | nbCombs <- (n-j)`nCk`(k-i)
87 , nbCombs <= r = uptoRank i (j+1) (r-nbCombs)
88 | otherwise = j : for1K (i+1) (j+1) r