How to create a random number apart from one without using a while loop?

Let's say I want to create a random number from 1 to 100, but I do not want to include 42. How would I do this without repeating the random method until it is 42.

+5
source share
2 answers

Exception 1 value

var nums = [Int](1...100) nums.removeAtIndex(42) let random = Int(arc4random_uniform(UInt32(nums.count))) print(nums[random]) 

Excluding multiple values

This Range extension provides a solution if you want to exclude more than 1 value.

 extension Range where Element: Hashable { func random(without excluded:[Element]) -> Element { let valid = Set(self).subtract(Set(excluded)) let random = Int(arc4random_uniform(UInt32(valid.count))) return Array(valid)[random] } } 

Example

 (1...100).random(without: [40,50,60]) 

I believe that the complexity of computing this second solution is O(n) , where n is the number of elements included in the range.

It is assumed that no more than n excluded values ​​are called.

+7
source

appzYourLife has some excellent general-purpose solutions, but I want to solve a specific problem in an easy way.

Both of these approaches work in approximately the same way: Limit the range to a random number generator to remove the impossible answer (99 answers instead of 100), then compare the result so that it is not illegal.

None of the approaches increases the likelihood of an outcome relative to another outcome. That is, assuming that your random number function is completely random, the result will still be random (and has no equal chance of 43 relative to 5, for example).

Approach 1: Supplement.

Get a random number from 1 to 99. If it is greater than or equal to the number you want to avoid, add it to it.

 func approach1()->Int { var number = Int(arc4random_uniform(99)+1) if number >= 42 { number = number + 1 } return number } 

As an example, trying to create a random number from 1-5, not 3, take a random number from 1 to 4 and add it if it is greater than or equal to 3.

  • rand (1..4) gives 1, +0, = 1
  • rand (1..4) gives 2, +0, = 2
  • rand (1..4) produces 3, +1, = 4
  • rand (1..4) gives 4, +1, = 5

Approach 2: Avoidance.

Another simple way would be to get a number from 1 to 99. If it is exactly the amount you are trying to avoid, make it 100.

 func approach2()->Int { var number = Int(arc4random_uniform(99)+1) if number == 42 { number = 100 } return number } 

Using this algorithm and again narrowing the range to 1-5 (avoiding 3), we get the following possible results:

  • rand (1..4) produces 1; allowed, therefore Result = 1
  • rand (1..4) produces 2, allowed, so Result = 2
  • rand (1..4) produces 3; not allowed, therefore Result = 5
  • rand (1..4) produces 4, allowed, so Result = 4
+4
source

Source: https://habr.com/ru/post/1238567/


All Articles