Skip to main content
edited tags
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
Source Link

Create a collection of binaries with random set positions

I would like to create a collection of binaries with n set bits and total length should be between n and 31; also those set bits should be randomly positioned. For example if n = 3, then [1;0;1;0;1], [1;0;0;1;1;] and [1;1;1;0;0] should all be possible with equal chance. Below is my implementation and any feedback is welcome.

/// <summary>
/// Create a random collection of binaries, between n and 31 elements, with n bits are set. 
/// The set positions should be random too.
/// </summary>
/// <param name="n">The number of set bits in the collection; must be positive and less than 32</param>
let createRandomBinary (n : int) = 
    if n > 31 || n < 0 then ArgumentException("invalid input: must be positive and less than 32", "n") |> raise
    let ran = new Random()
    let mutable totalLength = ran.Next(n, 32) // [n, 32)
    match totalLength with
    | x when x = n -> Array.init n (fun _-> 1) // all bits are set case
    | _ ->  let res : int array = Array.zeroCreate totalLength // initialise a result with all 0s.
            let indices = ResizeArray(seq{0..totalLength - 1}) 
            let mutable counter = n
            let rec shuffle = function
                            | 0 ->  res // all n 1s have been set randomly so return the result
                            | _ ->  counter <- counter - 1
                                    let i = ran.Next(0, totalLength) // randomly pick an index and set to 1
                                    res.[indices.[i]] <- 1
                                    indices.RemoveAt(i) // remove the chosen index so it won't be set twice
                                    totalLength <- totalLength - 1 // decrease the length for next random index pick
                                    shuffle counter
            shuffle counter