Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialswiftfun
4,039 PointsGenerating a Random Number (non repeating)
How can I generate a random non-repeating number? To avoid showing the same fact twice (until all facts have been shown first)
The current code sometimes repeats number (hence repeating duplicate facts before going through the whole array:\
import GameKit // for the GKRandom function
struct QuoteProvider {
let quoteArray = [quote1, quote2, quote3, quote4, quote5]
func randomQuote() -> Quote { // Generate a random number to choose from the array
let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count)
return quoteArray[randomNumber]
}
}
3 Answers
Steven Parker
231,184 PointsI'm not an iOS programmer, but I'm familiar with the strategy for such a task. To avoid repeating, each time you choose a random item from a list, move that item out of that list and add it to a "used items" list. Then, when the list you pick from is completely empty, you can move all the items from the "used items" list back into it. Only then will any item be seen again.
swiftfun
4,039 PointsI would still appreciate anyone proficient with Swift to provide a solution based on this exercise and the code provided.
Xavier D
Courses Plus Student 5,840 PointsHi swiftfun,
I took some advice of what Steven Parker said and decided to create list as a stored property array, and I had to add the mutating keyword to the randomFact method in order to modify the list. To avoid creating an optional, I assigned an arbitrary number to the property. Coupled with a couple of loops and if statements each, as well as changing randomNumber to a variable, I believe that I was able to avoid the same fact from being displayed twice in a row, as well as avoid showing a duplicated fact until all the facts are displayed...
import GameplayKit
struct QuoteProvider
{
let quoteArray = [
"Ants stretch when they wake up in the morning.",
"Ostriches can run faster than horses.",
"Olympic gold medals are actually made mostly of silver.",
"You are born with 300 bones; by the time you are an adult you will have 206.",
"It takes about 8 minutes for light from the Sun to reach Earth.",
"Some bamboo plants can grow almost a meter in just one day.",
"The state of Florida is bigger than England.",
"Some penguins can leap 2-3 meters out of the water.",
"On average, it takes 66 days to form a new habit.",
"Mammoths still walked the Earth when the Great Pyramid was being built."
]
var list:[Int]=[999]
mutating func randomQuote()->String
{
var random=GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count)
while random==list[list.count-1]{random=GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count)}
while list.contains(random){random=GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count)}
list.append(random);if list[0]==999{list.removeFirst()};print(list)
if list.count==quoteArray.count{list.removeAll();list.append(GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count))};return quoteArray[list[list.count-1]]
}
}
I checked using the print statement on the list and the loops worked well without a counter and infinite looping. I hope that I achieved all objectives.
Xavier D
Courses Plus Student 5,840 PointsBTW...I believe the first while can be omitted without affecting behavior.
XD
Xavier D
Courses Plus Student 5,840 PointsAhh,
I noticed that I still may get a duplicate. It occurs after all the facts are displayed, the list is refreshes, and the new list starts. It appears whatever fact appears last in the old list, may be the first to appear in the new list, thus appearing twice in a row. Therefore, I created another property to hold that last number and compare it to the first number of the new list, and if they are the same, then generate another number. I used a repeat while so that a number is generated at least once regardless if condition is true, which should avoid an out of bounds error after emptying the list and starting over (I think...)
import GameplayKit
struct QuoteProvider
{
let quoteArray = [
"Ants stretch when they wake up in the morning.",
"Ostriches can run faster than horses.",
"Olympic gold medals are actually made mostly of silver.",
"You are born with 300 bones; by the time you are an adult you will have 206.",
"It takes about 8 minutes for light from the Sun to reach Earth.",
"Some bamboo plants can grow almost a meter in just one day.",
"The state of Florida is bigger than England.",
"Some penguins can leap 2-3 meters out of the water.",
"On average, it takes 66 days to form a new habit.",
"Mammoths still walked the Earth when the Great Pyramid was being built."
]
var list=[999];var last=999
mutating func randomQuote() -> String
{
var random=GKRandomSource.sharedRandom().nextInt(upperBound:quoteArray.count)
while list.contains(random){random = GKRandomSource.sharedRandom().nextInt(upperBound:quoteArray.count)}
list.append(random)
if list[0]==999{list.removeFirst()}
if list.count==quoteArray.count
{
print(list);last=list[list.count-1];print(last)
repeat
{list.removeAll();list.append(GKRandomSource.sharedRandom().nextInt(upperBound: quoteArray.count))}
while last==list[0];print(list[0])};return quoteArray[list[list.count-1]]
}
}
I also modified the test print statements. Now the list only prints if all facts are displayed. I then print the last number of the list before it refreshes as well as print the first number of the next list, to confirm that the pertaining number is not duplicated.
Everything looks okay now...I think...
XD
swiftfun
4,039 Pointsswiftfun
4,039 PointsThank you!
swiftfun
4,039 Pointsswiftfun
4,039 PointsCould you provide a code example please?
Steven Parker
231,184 PointsSteven Parker
231,184 PointsAs I said, I'm not an iOS/Swift programmer. I've just done similar things in other languages so I am familiar with the concepts.