I am trying to make an add method that works like long addition, so I want to start the addition from the end and work my way backwards so I can get the carrys right and etc. So I am currently trying to start working backwards over the array.
For example what im trying to do.
two arrays with the character 123456789
and i want to add them starting at 9 + 9 then move to 8+8
So I'm pretty sure I'm using the right way to iterate backwards over an array, but everytime I try I get just the runtime error, index out of bounds, and I can't figure out why. Any help would be great, I just cant figure out why it keeps throwing the exception.
-(MPInteger *) add: (MPInteger *) x
{
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray arrayWithCapacity:100];
//for (int i = 0; i < [a count]; i++) {
for (NSInteger i = [a count] - 1; i > 0; i--) {
int num = 10;
NSNumber *ourNum = [NSNumber numberWithInt:num];
NSNumber *total = [NSNumber numberWithInt:[[a objectAtIndex:i] intValue] + [[b objectAtIndex:i] intValue]];
if ([total intValue] >= [ourNum intValue]) {
total = [NSNumber numberWithInt:([total intValue] - [ourNum intValue])];
[c addObject:[NSNumber numberWithInt:([total intValue])]];
} else {
[c addObject:[NSNumber numberWithInt:[[a objectAtIndex:i] intValue]+[[b objectAtIndex:i] intValue]]];
}
NSLog(#"%#", c[i]);
}
return x;
}
First, let's clean up this code.
- (MPInteger *)add:(MPInteger *)x {
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray arrayWithCapacity:100];
for (NSInteger i = [a count] - 1; i > 0; i--) {
int num = 10;
NSNumber *ourNum = #(num);
NSNumber *total = #([a[i] intValue] + [b[i] intValue]);
if ([total intValue] >= [ourNum intValue]) {
total = #([total intValue] - [ourNum intValue]);
[c addObject:#([total intValue])];
} else {
[c addObject:#([a[i] intValue] + [b[i] intValue])];
}
NSLog(#"%#", c[i]);
}
return x;
}
Next, let's remove redundant/duplicate code.
- (MPInteger *)add:(MPInteger *)x {
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray arrayWithCapacity:100];
for (NSInteger i = [a count] - 1; i > 0; i--) {
int num = 10;
NSNumber *total = #([a[i] intValue] + [b[i] intValue]);
if ([total intValue] >= num) {
total = #([total intValue] - num);
}
[c addObject:total];
NSLog(#"%#", c[i]);
}
return x;
}
Now we can clearly see all of the issues.
You're going from [a count] - 1 to 1. You should be going all the way to 0.
a and b might have different sizes, so if you only do [a count] - 1 to 0, then if for example [b count] < [a count], you'll get an index out of bounds error when you try to access b[i].
You're adding stuff to the end of c, but you should be adding it to the beginning of c since you're iterating backwards.
You don't store the carry anywhere.
You are accessing c[i], which doesn't exist.
You are starting with an empty array 'c', and you NSLog c[i] which is obviously out of bounds on the first iteration.
Related
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
So I'm making a biginteger program, and I'm having a problem with adding two arrays that aren't the same length. The problem I'm having is with the add method. If I'm iterating through an array is there any way to test if element is out of bounds. I've tried testing if the element in a is equal to nil, but I still get the exception. Any help would be great thanks.
#import <Foundation/Foundation.h>
#import "MPInteger.h"
#implementation MPInteger
{
}
-(id) initWithString: (NSString *) x
{
self = [super init];
if (self) {
intString = [NSMutableArray array];
for (int i = 0; i < [x length]; i++) {
NSString *ch = [x substringWithRange:NSMakeRange(i, 1)];
[intString addObject:ch];
}
}
return self;
}
-(NSString *) description
{
return self.description;
}
- (MPInteger *) add: (MPInteger *) x {
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray array];
NSInteger arrayCount;
if (a < b) {
arrayCount = [b count];
} else {
arrayCount = [a count];
}
int num = 10;
int carry = 1;
NSNumber *total;
NSNumber *carrySum;
for (int i = 0; i < arrayCount; i++) {
if (a[i] == nil) {
total = #([b[i] intValue]);
[c addObject:total];
} else if (b[i] == nil) {
total = #([a[i] intValue]);
[c addObject:total];
} else {
total = #([a[i] intValue] + [b[i] intValue]);
[c addObject:total];
}
}
for (NSInteger j = [c count]-1; j >=0; j--) {
if ([c[j] intValue] >= num) {
total = #([c[j] intValue] - num);
carrySum = #([c[j-1] intValue] + carry);
[c replaceObjectAtIndex:j withObject:total];
[c replaceObjectAtIndex:j-1 withObject: carrySum];
}
}
NSString *str = [c componentsJoinedByString:#""];
NSLog(#"%#", str);
return x;
}
-(MPInteger *) multiply: (MPInteger *) x
{
NSMutableArray *a = self->intString;
NSMutableArray *b = x->intString;
NSMutableArray *c = [NSMutableArray array];
NSMutableArray *sum = [NSMutableArray array];
NSNumber *total;
NSNumber *carrySum;
int num = 10;
NSNumber *endZero = 0;
NSInteger bottomCount = [b count]-1;
while (bottomCount != -1) {
for (int i = 0; i < [a count]; i++) {
total = #([a[i] intValue] * [[b objectAtIndex:bottomCount] intValue]);
if (bottomCount == [b count] -1) {
[c addObject:total];
} else {
[c replaceObjectAtIndex:i withObject:total];
}
}
for (NSInteger j = [c count]-1; j>=0; j--) {
NSString *carry = [NSString stringWithFormat:#"%d", [c[j] intValue]];
NSString *carry2 = [carry substringToIndex:1];
int carryFinal = [carry2 intValue];
NSString *carry3 = [carry2 stringByAppendingString:#"0"];
int carry4 = [carry3 intValue];
if ([c[j] intValue] >= num) {
total = #([c[j] intValue] - carry4);
carrySum = #([c[j-1] intValue] + carryFinal);
[c replaceObjectAtIndex:j withObject:total];
[c replaceObjectAtIndex:j-1 withObject: carrySum];
} else {
if(j == 0) {
if (bottomCount == [b count] -1) {
bottomCount = bottomCount - 1;
NSString *str = [c componentsJoinedByString:#""];
[sum addObject: str];
} else {
[c addObject:#([endZero intValue])];
bottomCount = bottomCount - 1;
NSString *str = [c componentsJoinedByString:#""];
[sum addObject: str];
}
}
}
}
}
NSMutableArray *finalSum = [NSMutableArray array];
MPInteger *ele1;
MPInteger *ele2;
MPInteger *eleSum;
NSNumber *endZ= #(0);
[finalSum insertObject:endZ atIndex:0];
for (int k = 0; k < [sum count]; k++) {
NSString *str= [NSString stringWithFormat:#"%d", [sum[k] intValue]];
NSString *str2 = [NSString stringWithFormat:#"%d", [sum[k+1] intValue]];
ele1 = [[MPInteger alloc] initWithString:str];
ele2 = [[MPInteger alloc] initWithString:str2];
eleSum = [ele1 add: ele2];
NSLog(#"%#", eleSum);
}
NSLog(#"%#", sum);
return self;
}
Updated this
for (int i = 0; i < arrayCount; i++) {
if (a[i] == nil) {
total = #([b[i] intValue]);
[c addObject:total];
} else if (b[i] == nil) {
total = #([a[i] intValue]);
[c addObject:total];
} else {
total = #([a[i] intValue] + [b[i] intValue]);
[c addObject:total];
}
}
has now become:
NSMutableArray *c = a.count > b.count ? [a mutableCopy] : [b mutableCopy];
NSArray *shortestArray = a.count > b.count ? b : a;
[shortestArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSNumber *currentNumber, NSUInteger idx, BOOL *stop) {
c[idx] = #(currentNumber.integerValue + [c[idx] integerValue]);
NSLog(#"%#", c[idx]);
}];
What I think I need to do is every index that is in array a and not b or vise versa, is add beginning zeros, but I don't know how to do that.
I printed out what it does after each iteration and it gives:
2013-09-02 12:31:42.630 Asgn1[42471:303] 5
2013-09-02 12:31:42.632 Asgn1[42471:303] 3
2013-09-02 12:31:42.632 Asgn1[42471:303] 1
And a final answer of:
2013-09-02 12:31:42.633 Asgn1[42471:303] 353
For the code that is failing would it not be simpler to take a mutableCopy of the large array and then loop over the smaller array for the calculations?
Perhaps something like this:
NSMutableArray *c = a.count > b.count ? [a mutableCopy] : [b mutableCopy];
NSArray *shortestArray = a.count > b.count ? b : a;
[shortestArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSNumber *currentNumber, NSUInteger idx, BOOL *stop) {
c[idx] = #(currentNumber.integerValue + [c[idx] integerValue]);
}];
I have an array containing twenty items. I want to search through the array, comparing one item to the next one in the array, and then print the larger item. I have already sorted the array. I just want to compare the two items, check what the remainder is between the two values, and if it's greater than say, four, print the larger item.
NSArray* arr = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:6],
[NSNumber numberWithInt:7],
[NSNumber numberWithInt:11],
nil
];
int len = [arr count];
for (int i=0; i < len-1; ++i) {
int num1 = [[arr objectAtIndex:i] intValue];
int num2 = [[arr objectAtIndex:i+1] intValue];
if ( num2-num1 > 4 ) {
NSLog(#"%d", num2);
}
}
--output:--
6
NSEnumerator *itemEnumerator = [theArray objectEnumerator];
YourClass *lastObject = [itemEnumerator nextObject];
YourClass *compareObject;
while( (compareObject = [itemEnumerator nextObject]) != nil)
{
if( /* place your condition here */ )
{
NSLog( … );
}
lastObject = compareObject;
}
Typped in Safari
Following this code:
In ViewController.m
double kk[2][2] = {{1,2},{5,6}};
if (!matrix1Col) {
matrix1Col = [NSMutableArray array];
}
for (int i=0; i<2; i++) {
[matrix1Row removeAllObjects];
if (!matrix1Row) {
matrix1Row = [NSMutableArray array];
}
for (int j=0 ; j<2; j++) {
[matrix1Row insertObject:[NSNumber numberWithDouble:kk[i][j]] atIndex:j];
}
[matrix1Col insertObject:matrix1Row atIndex:i];
}
self.label100.text = [NSString stringWithFormat:#"%f",[[[matrix1Col objectAtIndex:0] objectAtIndex:0] doubleValue]];
self.label110.text = [NSString stringWithFormat:#"%f",[[[matrix1Col objectAtIndex:1] objectAtIndex:0] doubleValue]];
self.label101.text = [NSString stringWithFormat:#"%f",[[[matrix1Col objectAtIndex:0] objectAtIndex:1] doubleValue]];
self.label111.text = [NSString stringWithFormat:#"%f",[[[matrix1Col objectAtIndex:1] objectAtIndex:1] doubleValue]];`
I wanna show object in NSMutableArray of matrix which receive value from matrix of double in label.
And my all label must show as following ->label100 show 1 ->label110 show 5 ->label101 show 2 and ->label111 show 6
but It shows ->label100 show 5 ->label110 show 5 ->label101 show 6 and ->label111 show 6
How can I do?
The problem is that you're always overwriting already inserted objects, as you insert the row many times in the same loop. That's how I would write it:
double kk[2][2] = {{1,2},{5,6}};
NSMutableArray* matrix= [NSMutableArray new];
for(unsigned int i=0; i<2; i++)
{
NSMutableArray* row= [NSMutableArray new];
for(unsigned int j=0; j<2; j++)
{
[row addObject: #(kk[i][j]) ];
}
[matrix addObject: row];
}
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];