Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the equivalent of seeded random in Swift3 (Xcode8 beta 1)

I need to start the same random number list over every execution of my app. srand/rand do not exist anymore. What should I do then?

private extension Array {
    private func randomValues(_ seed: UInt32, num: Int) -> [Element] {
        srand (seed)

        var indices = [Int]()
        indices.reserveCapacity(num)
        let range = 0..<self.count
        for _ in 0..<num {
            var random = 0
            repeat {
                random = randomNumberInRange(range)
            } while indices.contains(random)
            indices.append(random)
        }

        return indices.map { self[$0] }
    }
like image 823
Stéphane de Luca Avatar asked Jun 17 '16 03:06

Stéphane de Luca


3 Answers

You can use srand48(seed) and drand48() in Swift3.

like image 191
Lycoris Avatar answered Oct 23 '22 20:10

Lycoris


Unless you're developing with Swift for non-Apple platforms, you can get a much better randomization API in GameplayKit: several algorithms (trade randomness vs speed), seedable, distribution control, etc.

like image 5
rickster Avatar answered Oct 23 '22 22:10

rickster


I can't find a way to use seeded random in Swift 3 Beta 1. Had to write a silly wrapper function in C:

// ----------------------------------------------
// my_random.h
// ----------------------------------------------
#ifndef my_random_h
#define my_random_h

#include <stdio.h>

#endif /* my_random_h */

long next_random();


// ----------------------------------------------
// my_random.c
// ----------------------------------------------
#include <stdlib.h>
#include "my_random.h"

long next_random() {
    return random();
}

You can use the bridging header to import it into Swift. Then you can call it in Swift like this:

srandom(42)
for _ in 0..<10 {
    let x = next_random()
    print(x)
}

random is better than rand. Read the man pages for discussion on these 2 functions.


Edit:

A workaround, as @riskter suggested, is to use GameKit:

import GameKit

let seed = Data(bytes: [42]) // Use any array of [UInt8]
let source = GKARC4RandomSource(seed: seed)

for _ in 0..<10 {
    let x = source.nextInt()
    print(x)
}
like image 2
Code Different Avatar answered Oct 23 '22 22:10

Code Different