Sascha Held
Sascha Held

Reputation: 336

Generating random weighted numbers in Objective C

We have a Dictionary with the following structure:

_availableCharacterClasses = [[NSMutableDictionary alloc] init];
[_availableCharacterClasses setObject:[NSNumber numberWithFloat:[DefaultNova characterSpawnProbability]] forKey:NSStringFromClass([DefaultNova class])];

where probability has a value between 0 (low) and 100 (height)

now i want to pick a random key (weighted) from the _availableCharacterClasses-Dictionary.
How can i archive this using objective c?

Upvotes: 0

Views: 596

Answers (3)

Artemiy Sobolev
Artemiy Sobolev

Reputation: 494

If you want to pick random key for given value you can do something like:

float value = 3;    
NSArray * keys = [_availableCharacterClasses.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@[self].floatValue == %f", _availableCharacterClasses, value]];
NSString *anykey = keys[arc4random_uniform(keys.count)];

Upvotes: 0

robert
robert

Reputation: 2842

Ah I think now I've got your question correct. I assume the probabilities sum up to 100?

int random = arc4random%100;

NSArray *probabilities = [_availableCharacterClasses allObjects];
NSArray *keys = [_availableCharacterClasses allKeys];
CGFloat currentValue = 0;
int index=0;
for(NSNumber *p in probabilities){
    currentValue+=[p floatValue];
    if(random<currentValue){
        //found now get the key
        return keys[index];
    }
    index++;
}

Upvotes: 1

Sascha Held
Sascha Held

Reputation: 336

@Robert i have modified your solution slightly and came up with the following result

- (NSUInteger)randomIndexByProbability:(NSArray *)probabilities
{
  CGFloat randomNumber= arc4random_uniform(100) + (float)arc4random_uniform(101)/100;
  NSUInteger weightedIndex = 0;
  CGFloat totalProbability = 0.0;

  for(NSUInteger i=0; i<probabilities.count; i++)
  {
    totalProbability += [probabilities[i] floatValue];

    if(totalProbability >= randomNumber)
    {
      break;
    }
    weightedIndex++;
  }
  return weightedIndex;
}

Upvotes: 0

Related Questions