How to Generate Random Numbers Without Repetition in Swift

How to generate a random number in Swift without repeating the previous random number?

Store the previous generated number in a variable and compare the generated number to the previous number. If they match generate a new random number. Repeat the generation of new numbers until they don't match.

var previousNumber: UInt32? // used in randomNumber() 

func randomNumber() -> UInt32 {
var randomNumber = arc4random_uniform(10)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(10)
}
previousNumber = randomNumber
return randomNumber
}

Random number without repeat in swiftUI

This approach uses an extra observable class. It copies the 6 numbers into a temporary array. On tap one random number is removed from the array (this number is being displayed) so each number is only used once. If the array is empty the cycle starts over.

class Random : ObservableObject {
var array = [Int]()

@Published var randomNumber = 0

func next() {
if array.isEmpty { array = [1,2,3,4,5,6] }
let index = Int.random(in: 0..<array.count)
randomNumber = array.remove(at: index)
}
}

struct RanNum: View {

@StateObject private var random = Random()

var body: some View {
VStack{

Text(random.randomNumber == 0 ? "" : "\(random.randomNumber)")
.padding()
.multilineTextAlignment(.center)
.background(Color.white.opacity(0.5))
.cornerRadius(10)
.frame(width: 390, alignment: .center)

Button(action: {
random.next()
}) {
Image(systemName: "arrow.counterclockwise.circle.fill")
.foregroundColor(.black)
.font(.system(size: 30))
.padding()
}
}
}
}

How to generate random number without repeating in Swift

You can store last random number or last fact in a variable and check it in your randomFact function. Like this:

var lastRandomNumber = -1

func randomFact() -> String {
let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: facts.count)

if randomNumber == lastRandomNumber {
return randomFact()
} else {
lastRandomNumber = randomNumber
return facts[randomNumber]
}
}

How to randomly generate numbers that don't repeat?

How does one generate a random number in Apple's Swift language?

check this answer, you can then write an easy function to check your array or data structure for duplicate numbers.

How to generate random numbers without repetition in Swift?

You can create a function that returns a random-number generating closure, like this:

func randomSequenceGenerator(min: Int, max: Int) -> () -> Int {
var numbers: [Int] = []
return {
if numbers.isEmpty {
numbers = Array(min ... max)
}

let index = Int(arc4random_uniform(UInt32(numbers.count)))
return numbers.remove(at: index)
}
}

To use it, first call the generator once to create the random sequence generator, then call the return value as many times as you like. This will print out random values between one and six, cycling through all of them before starting over:

let getRandom = randomSequenceGenerator(min: 1, max: 6)
for _ in 1...20 {
print(getRandom())
}

How to make a list of random numbers that never repeat (consecutively) in swift ui

First, I'd move your numbers into their own model (I'm using NumberModel) so that they can have unique IDs, which will make them more convenient to use in the List/ForEach (especially if they end up changing values over time). This will also allow you to just use ForEach(numbers) and not deal with the indices at all.

You don't need @State variables for previousNumber and randomNumber because they're just used within onAppear. I've refactored your onAppear a bit, but you could definitely go further with it.

struct NumberModel : Identifiable {
var id = UUID()
var number : Int

var stringValue : String {
number.description
}
}

struct ContentView: View {
@State var numbers: [NumberModel] = []
var body: some View {
List{
ForEach(numbers) { i in
Text(i.stringValue)
}
}
.navigationTitle("numbers")
.onAppear() {
var previousNumber : Int? = nil
for _ in 0 ..< 100 {
while true {
let randomNumber = Int.random(in: 0...9)
guard randomNumber != previousNumber else {
continue
}
previousNumber = randomNumber
numbers.append(NumberModel(number: randomNumber))
break
}
}
}
}
}

How do I generate a random number not including one without using a while loop?


Updated for Swift 5.1

Excluding 1 value

var nums = [Int](1...100)
nums.remove(at: 42)

let random = Int(arc4random_uniform(UInt32(nums.count)))
print(nums[random])

Excluding multiple values

This extension of Range does provide a solution when you want to exclude more than 1 value.

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

Example

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

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

The assumption here is the no more than n excluded values are provided by the caller.



Related Topics



Leave a reply



Submit