3

I am attempting to substitute arc4random in linux using the randr function from Glibc. Although I managed to shuffle an Array of integers, I failed to do so with an Array of string.

The code below works as expected:

import Foundation

extension MutableCollection {
    /// Shuffles the contents of this collection.
    mutating func shuffle() {
        let c = count
        guard c > 1 else { return }

        for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
            let d: IndexDistance = numericCast(Int(random() % numericCast(unshuffledCount) + 1 ))
            let i = index(firstUnshuffled, offsetBy: d)
            swapAt(firstUnshuffled, i)
        }
    }
}

extension Sequence {
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Element] {
        var result = Array(self)
        result.shuffle()
        return result
    }
}

let x = [1, 2, 3].shuffled()
print(x)
// [3, 1, 2]

But if I do the same to an Array of string:

let fiveStrings = ["20", "45", "70", "30"].map(String.init).shuffled()
print(fiveStrings)

It fails with Index out of range. The error is the same with

var numbers = [1, 2, 3, 4]
print(numbers.shuffle())
  • How do I shuffle the strings using random()?

1 Answer 1

3

The code

 let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))

in How do I shuffle an array in Swift? creates a random number in the between 0 and unshuffledCount-1. To achieve the same with random() use

 let d: IndexDistance = numericCast(Int(random() % numericCast(unshuffledCount)))

without the +1.

Note that in contrast to arc4random_uniform():

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the thorough answer. I know about the modulo bias, but that has to do for now. How do I solve the problem in the line: var numbers = [1, 2, 3, 4]; print(numbers.shuffle())?
What problem? shuffle() has no return value, it mutates the argument. What you probably want is var numbers = [1, 2, 3, 4] ; numbers.shuffle() ; print(numbers)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.