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 trial

iOS

Simple Fact App: How do I write code so the fact does not repeat itself consecutively?

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

That is the code for randomizing the facts. However, how can I modify the code so the fact does not repeat itself till all the other facts are displayed?

2 Answers

Magnus Hållberg
Magnus Hållberg
17,232 Points

A simple solution would be to do something like this:

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

if facts.count == 0 {
   facts = [...] // here you have to restore the facts array to its original state
   return facts.remove(at: randomNumber)
} else {
       return facts.remove(at: randomNumber)
       }
}

The problem with this approach is that it could create the same result twice once in a while when you restore the array. But its guarantied to be more random than before since you always remove the latest result.

Gavin Hobbs
Gavin Hobbs
5,205 Points

Here's my solution... it's a little lengthy but it's guaranteed to NOT repeat 'facts'.

After hours of scratching my head about this problem I finally was telling a friend about it (unconsciously rubberducking) and I found the error in my code. Anyways, that's beside the point. Here's the resulting code...

// Initialize: Get a fact to test
        var currentFact = factProvider.randomFact()
        var currentFactIndex = factProvider.getIndex(ofFact: currentFact)
 //       var newFact: String

        // Create a counter
        var y = 0
        var counter = 0

        // If all the facts have been displayed...
        if  displayedFactsIndexes.count > factProvider.facts.count {
            // Do nothing
        } else {
            if displayedFactsIndexes.count != factProvider.facts.count {
                while y < displayedFactsIndexes.count {
                    if currentFactIndex == displayedFactsIndexes[y] {
                        // Get new fact
                        currentFact = factProvider.randomFact()
                        currentFactIndex = factProvider.getIndex(ofFact: currentFact)

                        // Set y back to 0 to retry all possibilities
                        y = 0
                    } else {
                        // DEBUG
                        print("This fact: \(currentFact) has made it through \(y) tries.")
                        print("This loop has repeated \(counter) times!")
                        y += 1
                    }

                    counter += 1
                }
                // Set the current fact to the text
                funFactLabel.text = currentFact

                // Add the fact index to the displayed array
                displayedFactsIndexes.append(currentFactIndex)

            } else {
                funFactLabel.text = "All out of fun facts!"
            }
        }

Basically I kept an array of the indexes of the 'used' facts. So the array would look something like this...

displayedFactsIndexes = [2, 5, 10, 3]
// The array would look like this if you saw the index numbers first...
// 0: 2, 1: 5, 2: 10, 3: 3

This array enabled me to check the generated fact's index number with the already used facts array numbers. I did this instead of checking the generated fact with an array of the already used facts just because it seemed simpler and dealt with a smaller unit (integer rather than a string), but this would work just as well check the strings with one another.

y is the starting index number for the used facts array... for when the generated fact is being compared to all the used facts. y increases by 1 for every time the generated fact is comfirmed that it's not equal to the used fact the if function is checking. y is set back to zero if the generated fact and one of the used facts are equal. Then a new fact is generated and the process is started all over again.

That's pretty much it. There's some debugging code in there that might make things a little confusing. Let me know if you have any questions.

G'day!

  • Gavin Hobbs