2

Does swift by default has a random number generator that returns the same number only once?

For example it picks a number in range 1,2,3,4,5. Return that random number (lets say 3). In the next loop, it picks only from 1,2,4,5 and so on.

EDIT: This is what I ended up using. It returns an array of integers from 0-5 and was tested in playground. Note that this is meant to be used when you are picking from a large set of Integers and not just 6.

func generateRandomArray() -> [Int]{
    var randomImages: [Int] = [Int]()

    var newRandomNumber = Int(arc4random_uniform(UInt32(6)))

    while (randomImages.count < 6) {
        if (randomImages.contains(newRandomNumber) == false){
            randomImages.append(newRandomNumber)
        }
        newRandomNumber = Int(arc4random_uniform(UInt32(6)))
    }

    return randomImages

}
ABakerSmith
  • 22,759
  • 9
  • 68
  • 78
potato
  • 4,479
  • 7
  • 42
  • 99
  • are u checking out the random in a loop or something? – Saheb Roy Sep 05 '15 at 09:28
  • Most probably. Decided to do a little research before implementing – potato Sep 05 '15 at 09:29
  • 1
    Just store the last number in a temporary variable and check the next random number against it in a `while` loop. While the number is the same as the last, generate a new number. Once the number generated is not the same update your temporary variable. – Daniel Storm Sep 05 '15 at 09:31
  • Should the next random number have the same probability of occurrence as the previous generated number? – user523234 Sep 05 '15 at 09:34
  • @ user523234 well, since it picks from a fewer number of items it shouldnt – potato Sep 05 '15 at 09:36
  • 1
    possible duplicate of [How do I shuffle an array in Swift?](http://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift) – Luca Angeletti Sep 05 '15 at 13:43

4 Answers4

4

This kind of generator is not called a "random number" generator, but usually a "Shuffle" or "Permute". You have to tell it how many items there are first. Otherwise what you are proposing doesn't make any sense!

see answer here: How do I shuffle an array in Swift?

Community
  • 1
  • 1
Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
1

You can do this trick, Add the range of numbers from which you want to get the random result..to an NSMutableArray or NSMutableSet(to make sure there is only 1 of it). Iterate through the array-

 for(int i=0;i<myMutableArray .count;i++){
  int randomIndex = arc4random_uniform(myMutableArray.count);
  int myNumber = [[myMutableArray objectAtIndex:randomIndex]intValue]; // edited 
  NSLog(@"My random number-%i",myNumber);//this is your generated random number
 [myMutableArray removeObjectAtIndex:randomIndex];
}

I guess this would do the tric, But if you do rmember NSMutableArray cannot take Primitive data type, just Objects like NSNumber.

EDIT

this line is not written and is justifying that why i am converting the NSNumber back to an interger because while adding the integer in the Array it has to be converted to a NSNumber|

[ myMutableArray addObject:[NSNumber numberWithInt:2]];

So in the for loop when i am getting the object from myMutableArray i am getting an NSNumber and to simplify it i casted that Object (NSNumber object) back to an integer.

Community
  • 1
  • 1
Saheb Roy
  • 5,899
  • 3
  • 23
  • 35
  • Since `NSMutableArray`, as you correctly say, cannot take primitive data why are you casting the content of an `NSMutableArray` to `(int)`? – Luca Angeletti Sep 05 '15 at 13:44
  • If you populated `myMutableArray` with `NSNumber`(s) then you are making a cast from `a pointer to NSNumber` to an `Int`. Why? – Luca Angeletti Sep 05 '15 at 13:52
  • @appzYourLife i edited the answer for the explanation as to why i converted the object of nsnumber back to an integer – Saheb Roy Sep 05 '15 at 15:18
  • Still wrong. You cannot perform a cast from `NSNumber` to `int`. Please try your code to understand what is happening. – Luca Angeletti Sep 05 '15 at 15:26
  • `[NSNumber numberWithInt: ]` is NOT casting an `int` to an `NSNumber` its creating an `NSNumber` object with that value of that of the `int` – Saheb Roy Sep 05 '15 at 15:28
  • Infact I am talking about this the 3rd line of your first block of code `int myNumber = (int)[myMutableArray objectAtIndex:randomIndex];` – Luca Angeletti Sep 05 '15 at 15:29
  • casting to int like that works the compiler wont give any notice, anyways i have edited to the code that you "wanted" to see – Saheb Roy Sep 05 '15 at 15:31
  • Now it should be fine. Did you check what was happening with the previous code? – Luca Angeletti Sep 05 '15 at 15:34
  • Right now am on a windows machine so cannot check that, anyways thanks for pointing it out. :) cheers – Saheb Roy Sep 05 '15 at 15:36
1

From Apple's documentation:

A set stores distinct values of the same type in a collection with no defined ordering.

This seems to be exactly what you are after, so making an array seems a bit ill-advised...

    var values : Set<Int> = []
    var value : Int {
        return Int(arc4random() % 6 + 1)
    }
    while values.count < 6 {
        values.insert(value)
    }

And you probably want to have a look at those values somewhere down the line:

    for value in values {
        println(value)
    } 
T. Benjamin Larsen
  • 6,373
  • 4
  • 22
  • 32
0

Just store the last random number in a variable and check the next random number against it in a while loop. While the new random number is the same as the last random number, generate a new random number. Once the new random number generated is not the same as the last random number the while loop ends and we update the last random number.

var lastRandomNumber = 0
var newRandomNumber = 0

func gernerateRandomNumber() {
    newRandomNumber = Int(arc4random_uniform(5)+1)

    while newRandomNumber == lastRandomNumber {
        newRandomNumber = Int(arc4random_uniform(5)+1)
    }

    lastRandomNumber = newRandomNumber
}
Daniel Storm
  • 18,301
  • 9
  • 84
  • 152
  • 1
    This is great. I will be working with arrays and use array.contains test in the while loop – potato Sep 05 '15 at 09:40
  • I don't understand. This code could produce the following output: 0,1,0,1,0,1... It does look wrong to me. – Luca Angeletti Sep 05 '15 at 09:42
  • @appzYourLife the example given in the original question allows for this behavior. *For example it picks a number in range 1,2,3,4,5. Return that random number (lets say 3). In the next loop, it picks only from 1,2,4,5 and so on.* And this will actually never produce a random number of 0. – Daniel Storm Sep 05 '15 at 09:43
  • 1
    The question ask how to produce a list of **random numbers without repetition**. Your code can produce the following output: `1,2,1,2,1,2` so it is wrong. The example in the question does refer to the first iteration of the algorithm but obviously the OP wants a list of random numbers without repetitions. – Luca Angeletti Sep 05 '15 at 09:47
  • The answer does not 100% apply to my question, but with only a slight tweak it fits perfectly. – potato Sep 05 '15 at 09:49
  • 2
    could you show us the tweak you used, for reference of other people who read this? (e.g. add at the end of the question). Note that on the linked article for my answer, there are a number of caveats about the algorithm used to shuffle a list! – Sanjay Manohar Sep 05 '15 at 10:10
  • 1
    No problem. there you go. – potato Sep 05 '15 at 11:16
  • @krompir2: your final approach (based on the one suggested in this answer) is usually used when you want to tech someone how NOT to write bad code. Please note that it is very expensive by a computational point of view and could produce an **infinite loop**. You are free to use it in your project but other users should avoid adopting this solution. It's just wrong. – Luca Angeletti Sep 05 '15 at 11:25
  • Please suggest improvements – potato Sep 05 '15 at 11:27
  • @krompir2: As Sanjay Manohar suggested, just look at here http://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift This is a very good approach. More specifically just look at the last block of code in the answer by Nate Cook (the `shuffled` extension) it is exactly what you are looking for and there is not risk of an **infinite loop**. – Luca Angeletti Sep 05 '15 at 11:42