Select random element from a set, faster than linear time (Haskell)

前端 未结 8 1627
清酒与你
清酒与你 2021-01-17 11:38

I\'d like to create this function, which selects a random element from a Set:

randElem :: (RandomGen g) => Set a -> g -> (a, g)

Si

8条回答
  •  深忆病人
    2021-01-17 11:52

    If you don't need to modify your set or need to modify it infrequently you can use arrays as lookup table with O(1) access time.

    import qualified Data.Vector 
    import qualified Data.Set
    
    newtype RandSet a = RandSet (V.Vector a)
    
    randElem :: RandSet a -> RandomGen -> (a, RandomGen)
    randElem (RandSet v) g
      | V.empty v = error "Cannot select from empty set" 
      | otherwise = 
        let (i,g') = randomR (0, V.length v - 1) g
        in (v ! i, g')
    
    -- Of course you have to rebuild array on insertion/deletion which is O(n)
    insert :: a -> RandSet a -> RandSet a
    insert x = V.fromList . Set.toList . Set.insert x . Set.fromList . V.toList`
    

提交回复
热议问题