Branch
Branch

Reputation: 387

Random Generator slightly less random

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"category == %@", selectedCategory];
NSArray *filteredArray = [self.Quotes filteredArrayUsingPredicate:predicate];
// Get total number in filtered array
int array_tot = (int)[filteredArray count];
// As a safeguard only get quote when the array has rows in it
if (array_tot > 0) {
    // Get random index
    int index = (arc4random() % array_tot);
    // Get the quote string for the index
    NSString *quote = [[filteredArray objectAtIndex:index] valueForKey:@"quote"];
    // Display quote
    self.quote_text.text = quote;
    // Update row to indicate that it has been displayed
    int quote_array_tot = (int)[self.Quotes count];
    NSString *quote1 = [[filteredArray objectAtIndex:index] valueForKey:@"quote"];
    for (int x=0; x < quote_array_tot; x++) {
        NSString *quote2 = [[Quotes objectAtIndex:x] valueForKey:@"quote"];
        if ([quote1 isEqualToString:quote2]) {
            NSMutableDictionary *itemAtIndex = (NSMutableDictionary *)[Quotes objectAtIndex:x];
            [itemAtIndex setValue:@"DONE" forKey:@"source"];
        }
    }

Above is the code I use in my app for generating a random quote from one of two categories stored in a plist (in arrays, where the first line is category, and second is quote). However, it seems to have a preference of repeating ones it's already shown. I'd prefer it have a preference (but not exclusively) show ones it hasn't shown before.

Upvotes: 0

Views: 50

Answers (1)

Michael
Michael

Reputation: 6517

Your question is an algorithm question. What you want is a sequence of numbers that seems random but is more uniform.

What you are looking for is called a low-discrepancy sequence. A simple form of this is a "shuffle bag", often used in game development, as described here or here.

With a shuffle bag, you basically generate all the indices (e.g. 0 1 2 3 4 5), shuffle them (e.g. 2 3 5 1 0 4) and then display the elements in this order. At the end, you generate another sequence (e.g. 4 1 0 2 3 5). Note that it is possible that the same element appears twice in the sequence, although it is rare. E.g. in this case, the "4" is a duplicate, because the full sequence is 2 3 5 1 0 4 4 1 0 2 3 5.

arc4random() is a good PRNG on Apple platforms, so it doesn't give you a "low discrepancy sequence". But: you can use it as a primitive to generate "low discrepancy sequences", you can also use it as a primitive to create a shuffle bag implementation.

Upvotes: 1

Related Questions