Array - find how many times an object repeats consecutively - objective-c

My array objects are as follows:
10,10,10
20,23,14
10,10,10
10,10,10
10,10,10
32,23,42
32,23,42
10,10,10
32,23,23
32,23,23
How can I go through this array and find out how many times the same object repeats sequentially, then add a , and the number of times it repeats?
Then save a new array with objects like:
10,10,10,1
20,23,14,1
10,10,10,3
32,23,42,2
10,10,10,1
32,23,23,2
Any help would be appreciated.
Thanks!

Try this:
NSMutableArray *outArray = [[NSMutableArray alloc] init];
for (NSUInteger j = 0; j < [theArray count]; j++) {
id object = [theArray objectAtIndex:j];
NSUInteger repeats = 1;
while (j + 1 < [theArray count] && [[theArray objectAtIndex:j + 1] isEqual:object]) {
j++;
repeats++;
}
[outArray addObject:object];
[outArray addObject:[NSNumber numberWithUnsignedInteger:repeats]];
}
return outArray;
This can also be done in place if the input array is mutable. I leave that as an exercise for the reader.

Break up every three integers into its own array (make sure they are strings).
Then iterate through each one of those arrays, and input into an NSMutableDictionary, the key is the string (your number), the value is a counter (if seen once, add 1, etc...)
Keep a pointer to the highest key (if newCount > highestCountPointer, then highestCountPointer=newCount)
At the end of that iteration, add the number that the highestCountPoints to to the end of the array.

I'm not an Objective C programmer, so please pardon any language gaffes. Something like the following should do the job:
NSMutableArray *result = [[NSMutableArray alloc] init];
id pending = nil;
NSUInteger count = 0;
for (NSUInteger i = 0; i < [theArray count]; i++) {
id object = [theArray objectAtIndex:i];
if ([object isEqual:pending]) {
count++;
} else {
if (pending != nil) {
[result addObject:[NSString stringWithFormat:#"%#,%d", pending, count]];
}
pending = object;
count = 1;
}
}
if (pending != nil) {
[result addObject:[NSString stringWithFormat:#"%#,%d", pending, count]];
}

Just run "uniq -c" from command line :)

Related

Merge Sorting in Objective C

I am trying to implement merge sort in objective -C.
This is a similar question asked in the following link , did not find it answered so creating a new question.
Merge sort in Objective-C
This is what I have tried ,
-(NSArray *)mergeSort:(NSArray *)unsortedArray {
if ([unsortedArray count] < 2)
return unsortedArray;
long mid = [unsortedArray count] / 2;
NSRange left = NSMakeRange(0, mid);
NSRange right = NSMakeRange(mid, [unsortedArray count] - mid);
NSArray *rightArray = [unsortedArray subarrayWithRange:right];
NSArray *leftArray = [unsortedArray subarrayWithRange:left];
NSArray *resultArray = [self merge:leftArray andRight:rightArray];
return resultArray;
}
-(NSArray *)merge:(NSArray *)leftArray andRight:(NSArray *)rightArray {
NSMutableArray *result = [NSMutableArray array];
int right = 0;
int left = 0;
while (left < [leftArray count] && right < [rightArray count]) {
NSComparisonResult comparisonResult = [leftArray[left] compare:rightArray[right]];
if (comparisonResult != NSOrderedDescending) {
[result addObject:[leftArray objectAtIndex:left++]];
} else {
[result addObject:[rightArray objectAtIndex:right++]];
}
/*if ([[leftArray objectAtIndex:left] intValue] < [[rightArray objectAtIndex:right] intValue]) {
[result addObject:[leftArray objectAtIndex:left++]];
//left++;
} else {
[result addObject:[rightArray objectAtIndex:right++]];
//right++;
}*/
}
NSRange leftRange = NSMakeRange(left, [leftArray count] - left);
NSRange rightRange = NSMakeRange(right, [rightArray count] - right);
NSArray * newRight = [rightArray subarrayWithRange:rightRange];
NSArray * newLeft = [leftArray subarrayWithRange:leftRange];
newLeft = [result arrayByAddingObjectsFromArray:newLeft];
return [newLeft arrayByAddingObjectsFromArray:newRight];
}
Kindly let me know if anyone has any other approaches for merge sort.
I dont understand why do you people want the long way.. Even though there are already easy way of doing this...
I made one myself hope this will help you..
- (NSArray *)arrayMergeSort:(NSArray *)targetArray
{
if (targetArray.count < 2)
return targetArray;
long midIndex = targetArray.count/2;
NSArray *arrayLeft = [targetArray subarrayWithRange:NSMakeRange(0, midIndex)];
NSArray *arrayRight= [targetArray subarrayWithRange:NSMakeRange(midIndex, targetArray.count - midIndex)];
return [self arrayMerge: [self arrayMergeSort:arrayLeft] : [self arrayMergeSort:arrayRight]];
}
For arrange merge:
- (NSArray *)arrayMerge:(NSArray *)arrayLeft :(NSArray *)arrayRight
{
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
int i = 0, j = 0;
while (i < arrayLeft.count && j < arrayRight.count)
[resultArray addObject:([arrayLeft[i] intValue] < [arrayRight[j] intValue]) ? arrayLeft[i++] : arrayRight[j++]];
while (i < arrayLeft.count)
[resultArray addObject:arrayLeft[i++]];
while (j < arrayRight.count)
[resultArray addObject:arrayRight[j++]];
return resultArray;
}
And using it like:
//Sample array
NSArray *activeArray = #[#101,#201,#301,#121,#11,#123,#21,#14,#32,#76,#89,#987,#65];
NSLog(#"arrayMergeSort %#",[self arrayMergeSort:activeArray]);
Output would be:
And also this bubble sort if you needed this:
- (NSArray *)arrayBubbleSort:(NSArray *)targetArray
{
NSMutableArray *resultArray = [targetArray mutableCopy];
for (int k = 0; k < resultArray.count; k++)
{
for (int l = 0; l < resultArray.count; l++)
{
if ([resultArray[k] intValue] < [resultArray[l] intValue])
{
[resultArray exchangeObjectAtIndex:k withObjectAtIndex:l];
}
}
}
return resultArray;
}
Hope i've helped you.. Cheers..
You've made a simple mistake. Merge sort works my splitting the array, sorting to the two halves, then merging the results.
Your mergeSort: method does the split, doesn't sort the two halves, and then calls merge: to merge the two (unfortunately unsorted) halves.
Before calling merge: you need to make recursive calls to mergeSort: to sort the two halves - this is the simple step you missed out.
I'm guessing this in a learning exercise, so no code, but you're almost there (fix it and it does work).
BTW Once you've fixed it you might want to think about why you don't need to create new arrays for the split part (but its far easier to create a new array for the merges).
HTH

Iterate through nested arrays to grab the first object of each array, then the second, etc

I have nested Arrays,
For example:
[[1,2,3,4,5], [A,B,C,D,E], [Z,Y,X,W,V]
I want to iterate through this array and create a new array, that looks like this:
[1,A,Z,2,B,Y,3,C,X,4,D,W,5,E,V]
I was initially thinking of using nested For loops, e.g.:
int index = 0;
int stop = [[arrays objectAtIndex:0] count];
NSMutableArray* finalArray = [NSMutableArray new];
while(index < stop)
{
for(id array in images)
{
[finalArray addObject:[array objectAtIndex:index]];
}
index++;
}
What would be the most efficient way of doing this?
I don't believe your code will actually generate what you mean (it won't actually compile because NSArray doesn't have addObject:). What you want is a Zipper:
NSArray *Zip(NSArray *arrays) {
if ([arrays count] == 0) {
return #[];
}
NSMutableArray *result = [NSMutableArray new];
NSInteger minCount = NSIntegerMax;
for (NSArray *array in arrays) {
minCount = MIN(minCount, [array count]);
}
for (NSInteger i = 0; i < minCount; i++) {
for (NSArray *array in arrays) {
[result addObject:array[i]];
}
}
return result;
}
Can't comment as I don't have 50 rep, so has to be as an answer!
Have you tried using loops such as
Dim i As Integer, j As Integer
For i = 1 To 5
For j = 1 To 3
Select Item i from array j
Next j
Next i

Sudoku Function returning array of identical boards

I am writing a recursive Sudoku solver and I am having some issues with 2D array handling. I included the function which is giving the trouble. There are some unnecessary lines I was using for debugging in there.
- (Stack *)successors
{
Stack *stack = [[Stack alloc] init];
NSMutableArray *temp = [[NSMutableArray alloc] init];
NSMutableArray *test = [[NSMutableArray alloc] init];
temp = [self.board copy];
for (int x = 0; x < columns; x++) {
for (int y = 0; y < rows; y++) {
if ([self.board[x][y] isEqualToString:#""] ||
[self.board[x][y] isEqualToString:#"."]) {
NSLog(#"%d %d", x, y);
for (int i = 1; i < 10; i++) {
NSLog(#"%d", i);
[temp[x] setObject:[NSString stringWithFormat:#"%d", i] atIndex:y];
State *tempState = [[State alloc] initWithBoard:temp];
if ([tempState legal]) {
NSMutableArray *input = [NSMutableArray arrayWithArray:temp];
[stack push:input];
[stack push:input];
[test addObject:input];
}
}
NSLog(#"test %#", test);
int p = [stack size];
for (int i = 0; i < p; i++) {
NSLog(#"%#", [stack pop]);
}
return stack;
}
}
}
return stack;
}
essentially, it begins at the top of the array and if the space is empty, it tries putting in the number 1 through 9 and if it is legal, based on another function I wrote previously, it will input it in the temp array and add it to the stack. I checked this and it works great. However, after adding them all together, I NSLog to check the stack and find that all of the stacked arrays now begin with the number 9, the last number checked in the temp array. I believe I am having some issue with keeping reference to the temp array, but I cannot figure it out. Any help is great.

Getting a random object from NSArray without duplication

I have an NSArray with 17 objects, something like this:
NSArray *objArray = [[NSArray alloc]initWithObjects: #"1",#"2",#"3",#"4",#"5",#"6"
,#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17", nil];
and an int with a random number as follows:
int random = arc4random()%17+1;
I want to get a random object from this NSArray without it being a duplicate, even if I closed the app (maybe by using NSUserDefaults).
If I've gotten all the objects I want to generate a new random sequence for the same objects.
You could do this by making a mutable copy of the array, and after you make a random selection from that array, remove that same object. When you want to save the array, save the mutable array itself, so can resume where you left off when the app restarts. This little test app does that, and just logs the value of the random pick:
- (void)viewDidLoad {
[super viewDidLoad];
self.objArray = #[#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"11",#"12",#"13",#"14",#"15",#"16",#"17"];
self.mut = [self.objArray mutableCopy];
}
-(IBAction)pickNumber:(id)sender {
int index = arc4random_uniform(self.mut.count);
NSLog(#"%#", self.mut[index]);
[self.mut removeObjectAtIndex:index];
if (self.mut.count == 0) {
self.mut = [self.objArray mutableCopy];
NSLog(#"*******************");
}
}
As a starting point, you could shuffle your array:
+ (NSArray *)arrayByShufflingArray:(NSArray *)array
{
// Fisher-Yates algorithm
NSMutableArray *result = [array mutableCopy];
NSUInteger count = [result count];
for (NSInteger i = ((NSInteger) count) - 1; i > 0; i--) {
NSUInteger firstIndex = (NSUInteger)i;
NSUInteger secondIndex = arc4random() % (NSUInteger)(i + 1);
[result exchangeObjectAtIndex:firstIndex withObjectAtIndex:secondIndex];
}
return result;
}
Step through each shuffled element and when you get to the end, reshuffle.
It can still happen that an item is selected twice in a row when the last item of one shuffle is the same as the first item in the next shuffle. If you want to avoid this you'll have to add some additional code.
Just Copy and Paste
-(NSMutableArray*)getRandomValueFromArray:(NSMutableArray*)arrAllData randomDataCount:(NSInteger)count {
NSMutableArray *arrFilterData = [[NSMutableArray alloc]init];
for(int i=0; i<count; i++){
NSInteger index = arc4random() % (NSUInteger)(arrAllData.count);
[arrFilterData addObject:[arrAllData objectAtIndex:index]];
[arrAllData removeObjectAtIndex:index];
}
return arrFilterData;
}
Note: count = number of random values you want to fetch from array.

How to simplify my code... 2D NSArray in Objective C...?

self.myArray = [NSArray arrayWithObjects: [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil], [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil],nil];
for (int k=0; k<[self.myArray count]; k++) {
for(int s = 0; s<[[self.myArray objectAtIndex:k] count]; s++){
[[[self.myArray objectAtIndex:k] objectAtIndex:s] setAttribute:[self generateSecertAttribute]];
}
}
As you can see this is a simple 2*2 array, but it takes me lots of code to assign the NSArray in very first place, because I found that the NSArray can't assign the size at very beginning. Also, I want to set attribute one by one. I can't think of if my array change to 10*10. How long it could be. So, I hope you guys can give me some suggestions on shorten the code, and more readable. thz
(Some Assumptions: myArray will have a fixed size. It won't grown up or become smaller in the run time.)
Generate the array by -addObject:.
NSMutableArray* myArray = [NSMutableArray array];
for (int k = 0; k < 10; ++ k) {
NSMutableArray* subArr = [NSMutableArray array];
for (int s = 0; s < 10; ++ s) {
id item = (s == 0 && k == 0) ? [self d] : [self generateMySecretObject];
[item setAttribute:[self generateSecertAttribute]];
[subArr addObject:item];
}
[myArray addObject:subArr];
// use [myArray addObject:[[subArr copy] autorelease]] for deep immutability.
}
return [[myArray copy] autorelease];
(Don't query self.myArray many times. Each corresponds to an ObjC call and while someone calls an ObjC call is cheap, it's still not free.)
If the array is a fixed size and each row is the same length then you could uses a 1D array and an offset, EG:
int rowLength = 5;
int rowNumber = 0;
int columnNumber = 3;
[myArray objectAtIndex: (rowLength * rowNumber) + columnNumber];