0

I have an NSArray with 4 objects, let's say 1, 2, 3 and 4. I want to sort this array in ascending order, but with a randomly selected starting number. For instance; 2, 3, 4 and 1 or 4, 1, 2 and 3.

How can I do this?

What I have thus far:

NSArray *playersArray = [_players allKeys];
NSSortDescriptor *sortPlayerArray = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES];
playersArray = [playersArray sortedArrayUsingDescriptors:@[sortPlayerArray]];

This results in 1, 2, 3, 4, obviously. I am also able to randomly order the players, like so:

activePlayersArray = [_players allKeys];
NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:activePlayersArray];

int count = (int)[temp count];

for (int i = 0; i < count; ++i) {
    int nElements = count - i;
    int n = (arc4random() % nElements) + i;
    [temp exchangeObjectAtIndex:i withObjectAtIndex:n];
}

activePlayersArray = [NSArray arrayWithArray:temp];

So how can I "combine" these two to get the results I want?

Hope you guys can help me.

Thanks!

Niels
  • 115
  • 11

3 Answers3

2

This is really an algorithm problem, not an iOS problem. Here are the steps to follow


Another solution is to create a circular array of sorted elements and then traverse the array in reverse order.

Community
  • 1
  • 1
Konsol Labapen
  • 2,424
  • 2
  • 15
  • 12
  • I miss ascending for descending: the fix is simple: don't do descending when you apply the alforithm. Also if you choose to use a circular array, don't read it in reverse order. – Konsol Labapen Sep 17 '14 at 20:56
1

I think this is what @Konsol intends, with a couple fixes: (1) it looks like the OP wants the order to be ascending, and (2) the array split in the other answer is at the midpoint. But I think the spirit is correct...

// Start with an unsorted (immutable?) input array of numbers (or any object
// that implements compare:.
// Pick a random location and produce an output array as described by the OP

NSMutableArray *mutableArray = [inputArray mutableCopy]; // if its not mutable already
[mutableArray sortUsingSelector:@selector(compare:)];

NSInteger inputIndex=arc4random_uniform(mutableArray.count);    
NSArray *start = [mutableArray subarrayWithRange:NSMakeRange(inputIndex, mutableArray.count-inputIndex)];
NSArray *end = [mutableArray subarrayWithRange:NSMakeRange(0, inputIndex)];

NSArray *outputArray = [start arrayByAddingObjectsFromArray:end];
NSLog(@"%@", outputArray);
danh
  • 62,181
  • 10
  • 95
  • 136
  • You are aware that your answer adds **Nothing** to what @KonsolLabapen said, right? If the person who asks the question truly needs more help than what Konsol said, then maybe this is not the site for them. Konsol's answer can be implemented in so many different order. So should I go change the order, provide some code, and call it a different answer? :) Actually I believe you mean well. I just want to prevent more of the same answer from yet others. – Katedral Pillon Sep 17 '14 at 20:49
  • @KatedralPillon I left the answer because I thought it adds *something*. No disrespect to @ Konsol, but that algorithmic suggestion ("sort & split"), as quite like a restatement of the question. The OP appears to need help on how to sort, split/join, uniform randoms, NSRange etc. The code I supplied is concise and novel on this thread so far. You might be saying the question is too remedial for SO, and you might be right. That's a tough line to judge, but it passed a threshold for me. Anyway, I did indeed mean well. – danh Sep 17 '14 at 21:37
  • I plus one. Great argument. – Katedral Pillon Sep 17 '14 at 22:18
0
int count = (int)[activePlayersArray count];
int n = (arc4random() % nElements) + i;
NSMutableArray *temp = [[NSMutableArray alloc] init];
for (int i = 0; i < count; ++i) {
    int nElements = count - i;
    [temp addObject:[activePlayersArray objectAtIndex:(n-i)%count]];
}
activePlayersArray = [NSArray arrayWithArray:temp];

Hope it works!

dmerlea
  • 894
  • 4
  • 12