views:

217

answers:

2

I thought I had it with,

void shiftArray(NSMutableArray *mutableArray, NSUInteger shift)
{
 for (NSUInteger i = 0; i < [mutableArray count]; i++) {
  NSUInteger newIndex = (i + shift) % [mutableArray count];
  [mutableArray exchangeObjectAtIndex:i withObjectAtIndex:newIndex];
 }
}

which turns 0,1,2,3,4 into 0,2,3,4,1 when I shift by one.

The expected result is 4,0,1,2,3

I feel like I'm missing something obvious...

Update: Thanks Matthieu, this is what my function looks like now.

void shiftArrayRight(NSMutableArray *mutableArray, NSUInteger shift) {
    for (NSUInteger i = shift; i > 0; i--) {
     NSObject *obj = [mutableArray lastObject];
     [mutableArray insertObject:obj atIndex:0];
     [mutableArray removeLastObject];
    }
}

I didn't know you could make a generic NSObject and put some subclass in it. It's all just pointers so I guess it's OK, right?

It's hard to break the habit of thinking of these objects as bags of stuff rather than pointers to the bag.

+4  A: 

Try something like

for (NSUInteger i = shift; i > 0; i--) {
   NSObject* obj = [mutableArray lastObject];
   [mutableArray insertObject:obj atIndex:0];
   [mutableArray removeLastObject];
}

CAVEAT -- I haven't tested that code, but that should help you solve the problem.

Matthieu Cormier
+3  A: 

You need to look again at your algorithm. Each time through the loop, you exchange one item with (in the case of shift=1) the next one.

0,1,2,3,4
1,0,2,3,4
1,2,0,3,4
1,2,3,0,4
1,2,3,4,0
0,2,3,4,1

You can do the operation you want to do, but you need to think about how to order the steps and their dependencies to get the right result. In the trivial case, you can just work backward from the end.

0,1,2,3,4
4,1,2,3,0
4,1,2,0,3
4,1,0,2,3
4,0,1,2,3

masto
Also, it's worth pointing out that while you can do it with swaps, you may not want to. Popping off the last element and appending it to the beginning or creating a new array are probably cheaper.
masto