1

I have a random number generator using arc4Random and integers with three numbers, number1, number2, number3, in the range 1 - 3. A zero is not permitted. That part I have sorted due to a previous request on here, however, when the test button is pressed, I want to ensure the random numbers are not the same, i.e. if number1 displays 2, then number2 and number3 can not display 2 etc. I tried to do this longhand below, but there must be a simpler way of doing it. How would this be written in code as I have only been learning Xcode for about 6 weeks? Regards. Del Hinds

@IBAction func testButtonPressed(sender: UIButton) {

var str = "Hello, playground"

var number1 = Int(arc4random() % UInt32(4))

if number1 == 0 {
number1 = 1
}

var number2 = Int(arc4random() % UInt32(4))

if number2 == 0 {
if number1 == 1 {
    number2 = 2
}
else if number1 == 2 {
    number2 = 3
}
else if number1 == 3 {
    number2 = 1
}
number2 = 1
}

label2TextLabel.text = "\(number2)"

var number3 = Int(arc4random() % UInt32(4))

if number3 == 0 {
if number2 == 1 {
    number3 = 2
}
else if number2 == 2 {
    number3 = 3
}
else if number2 == 3 {
    number3 = 1
}
number3 = 1
}

label3TextLabel.text = "\(number3)"
Del Hinds
  • 2,887
  • 4
  • 12
  • 12
  • 1
    if you're just generating in a range 1-3 and can't have repeats, just make an array `[1,2,3]`, shuffle it, and boom - instant non-repeating "random" values. – Marc B Jul 29 '15 at 14:28
  • Hi Mark, Thanks for your answer. Not sure I understand the answer though, but I will work on it. Many Thanx. Del – Del Hinds Jul 29 '15 at 19:44

3 Answers3

3

A crude way of doing this is to start with an array of the possible number set {1, 2, 3} in your case, and, swap random elements in the array a few times, using the built-in random generator.

If however you require the shuffling to have the statistical property that the probability of a given number occurring conditional on it having not already occurred is 1 / (numbers remaining), then adopt the more rigorous Fisher-Yates shuffle.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Hi Bathsheba, Thanks for your answer. Not sure I understand the answer though, but I will work on it. Many Thanx. Del – Del Hinds Jul 29 '15 at 19:45
3

If you are using ios9's GameplayKit, consider GKShuffledDistribution.
Playground example:

  import GameplayKit
  let distribution = GKShuffledDistribution(lowestValue: 1, highestValue: 3)
  for i in 1...36 {  // Do 12 groups of 3
      print(distribution.nextInt(), appendnewline: false)
      if i % 3 == 0 { print(" ", appendnewline: false ) }
   }

Sample result: 213 132 321 312 213 132 132 123 132 231 132 123


Or consider GKRandomSource:

  import GameplayKit
  blocks : [AnyObject] = ["A","B","C"]
  for  _ in  1...5 {  // do 5 shuffles
     blocks = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(blocks)
     print(blocks)
   }

Sample result: [A, C, B] [B, C, A] [B, A, C] [C, A, B] [B, A, C]

Swift 3:

GKShuffledDistribution - No real change, modified print usage.

  import GameplayKit
  let distribution = GKShuffledDistribution(lowestValue: 1, highestValue: 3)
  for i in 1...36 {
      print(distribution.nextInt(), terminator: "")
      if i % 3 == 0 { print(" ", terminator: "" ) }
  }

GKRandomSource usage revision

  • Replaced AnyObject with Any
  • Now use arrayByShufflingObjects(in: blocks)

gives

  import GameplayKit
  blocks : [Any] = ["A","B","C"]
  for  _ in  1...5 {  // do 5 shuffles
     blocks = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: blocks)
     print(blocks)
   }
Refactor
  • 524
  • 1
  • 11
  • 20
  • Hi Refactor, Thanks for your replies. Those are interesting options and thanks for the coding. I will look into them. Thanx again. Del – Del Hinds Jul 30 '15 at 19:25
0

Create an array (or set) of assigned numbers. When assigning a new number, check to see if the number is already in the array. If it is then assign a new random number. Repeat.

Once a number is assigned, add it to the array. Check if the array size is greater than or equal to the range of permitted numbers. If the number of random numbers is exhausted then throw an error and don't allow more numbers to be randomly assigned.

If you're doing this for large sets of numbers, you should check to make sure the size of the array of used numbers is not larger than about half the size of the range of assignable numbers.

If you're doing this for a small set of numbers, then it would be better to add the numbers in the range to an array and remove them from the array as you assign them.

Fennelouski
  • 2,411
  • 1
  • 18
  • 26
  • Hi Fennelouski, Thanks for your answer. Not sure I understand the answer though, but I will work on it. Many Thanx. Del – Del Hinds Jul 29 '15 at 19:45