I'm making an Objective C program to generate two random arrays and check them for similar numbers. I get the "NSRangeException" on the marked line of code, but I'm not sure why. Here's my code:
// Array Comparator (Check Two Arrays for Similar Numbers)
#interface ArrayComparator: NSObject
{
NSMutableArray *arrayOne;
NSMutableArray *arrayTwo;
}
- (void) generateFirstArray;
- (void) generateSecondArray;
- (void) check;
#end
#implementation ArrayComparator
- (void) generateFirstArray
{
arrayOne = [[NSMutableArray alloc] initWithCapacity: 50];
for (NSUInteger n = 0; n < 50; n++)
{
[arrayOne addObject: #(arc4random_uniform(999) + 1)];
}
for (NSUInteger n = 0; n < 50; n++)
{
printf("%li, ", (long) [arrayOne[n] integerValue]);
}
printf("first array.\n\n");
}
- (void) generateSecondArray
{
arrayTwo = [[NSMutableArray alloc] initWithCapacity: 50];
for (NSUInteger n = 0; n < 50; n++)
{
[arrayTwo addObject: #(arc4random_uniform(999) + 1)];
}
for (NSUInteger n = 0; n < 50; n++)
{
printf("%li, ", (long) [arrayTwo[n] integerValue]);
}
printf("second array.\n\n");
}
- (void) check
{
long similar = 0;
for (NSUInteger n = 0; n < 50; n++)
{
for (NSUInteger m = 0; m < 50; n++)
{
if ([arrayOne[n] integerValue] == [arrayTwo[m] integerValue]) // This is where I get the error.
{
similar++;
}
}
}
printf("There are %li similar numbers between the two arrays!", similar);
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool
{
ArrayComparator *arrayComp = [[ArrayComparator alloc] init];
[arrayComp generateFirstArray];
[arrayComp generateSecondArray];
[arrayComp check];
} return 0;
}
Any help is appreciated, thanks. (Please excuse my noobishness.)
(NSUInteger m = 0; m < 50; n++)
You mean m++.
Related
What is the best algorithm to find all possible words from an array of array of character.
Here an example :
From this array : [[A],[B,C,D],[E,F],[G,H]]
I need in return an array of the 12 ordered possibilities [[A,B,E,G],[A,C,E,G], ... , [A,D,F,H]]
Do you know how to implement this algorithm ? If you know it and you provide an example in any language (C,JAVA,Javascript, ...), feel free to share because it's been a day I try to find it ...
Here how I tries to implement it ("array" is an array of array of char):
+ (NSArray*) possibleReading:(NSMutableArray*)array {
int nbPossibilities = 1;
for(int i = 0; i < [array count]; i++) {
nbPossibilities *=[[array objectAtIndex:i] count];
}
NSMutableArray *possArr = [[NSMutableArray alloc] initWithCapacity:nbPossibilities];
for (int i=0; i < nbPossibilities; i++) {
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[possArr addObject:innerArray];
}
for (int i=0; i< [array count]; i++) {
//
for(int nbPoss = 0; nbPoss < nbPossibilities; nbPoss++) {
NSMutableArray * arr = [possArr objectAtIndex:nbPoss];
NSNumber * num = [NSNumber numberWithInt:nbPoss % [[array objectAtIndex:i] count]];
NSString * literal = [[array objectAtIndex:i] objectAtIndex:[num intValue]];
[arr insertObject:literal atIndex:i];
}
}
return possArr;
}
It would be easiest to do this using a recursive method.
Java code
import java.util.Arrays;
public class CartesianProductCalculator {
private char[][] result;
private char[][] sets;
private char[] currentSet;
private int index;
public char[][] calculateProduct(char[][] sets) {
index = 0;
// calculate size of result
int resultSize = 1;
this.sets = sets;
for (char[] set : sets) {
resultSize *= set.length;
}
result = new char[resultSize][];
currentSet = new char[sets.length];
calculateProduct(sets.length-1);
return result;
}
// fills result from right to left
public void calculateProduct(int setIndex) {
if (setIndex >= 0) {
for (char c : sets[setIndex]) {
currentSet[setIndex] = c;
calculateProduct(setIndex-1);
}
} else {
result[index++] = Arrays.copyOf(currentSet, currentSet.length);
}
}
public static void main(String[] args) {
char[][] input = {{'A'},{'B','C','D'},{'E','F'},{'G','H'}};
CartesianProductCalculator productCalculator = new CartesianProductCalculator();
System.out.println(Arrays.deepToString(productCalculator.calculateProduct(input)));
}
}
Objectiv-C
+ (NSArray *) cartesianProductOfArrays(NSArray *arrays) {
int arraysCount = arrays.count;
unsigned long resultSize = 1;
for (NSArray *array in arrays)
resultSize *= array.count;
NSMutableArray *product = [NSMutableArray arrayWithCapacity:resultSize];
for (unsigned long i = 0; i < resultSize; ++i) {
NSMutableArray *cross = [NSMutableArray arrayWithCapacity:arraysCount];
[product addObject:cross];
unsigned long n = i;
for (NSArray *array in arrays) {
[cross addObject:[array objectAtIndex:n % array.count]];
n /= array.count;
}
}
return product;
}
C
#include <stdio.h>
#include <string.h>
void print(int size, char *array[size], int indexs[size]){
char result[size+1];
int i;
for(i = 0; i < size; ++i)
result[i] = array[i][indexs[i]];
result[size] = 0;
puts(result);
}
int countUp(int size, int indexs[size], int lens[size]){
int i = size -1;
while(i >= 0){
indexs[i] += 1;// count up
if(indexs[i] == lens[i])
indexs[i--] = 0;
else
break;
}
return i >= 0;
}
void find_all(int size, char *array[size]){
int lens[size];
int indexs[size];
int i;
for(i = 0; i < size; ++i){//initialize
lens[i] = strlen(array[i]);
indexs[i] = 0;
}
do{
print(size, array, indexs);
}while(countUp(size, indexs, lens));
}
int main(void){
char *array[] = { "A", "BCD", "EF", "GH" };
int size = sizeof(array)/sizeof(*array);
find_all(size, array);
return 0;
}
If you can remove duplicate entries in inner array objects before executing method then you won't get duplicate words in result array.
- (NSArray*) possibleReading:(NSMutableArray*)array {
int nbPossibilities = 1;
for(int i = 0; i < [array count]; i++)
{
NSArray *cleanedArray = [[NSSet setWithArray:[array objectAtIndex:i]] allObjects];
[array replaceObjectAtIndex:i withObject:cleanedArray];
nbPossibilities *=[[array objectAtIndex:i] count];
}
NSMutableArray *possArr = [[NSMutableArray alloc] initWithCapacity:nbPossibilities];
for (int i=0; i < nbPossibilities; i++) {
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
[possArr addObject:innerArray];
}
for (int i=0; i< [array count]; i++) {
//
for(int nbPoss = 0; nbPoss < nbPossibilities; nbPoss++) {
NSMutableArray * arr = [possArr objectAtIndex:nbPoss];
NSNumber * num = [NSNumber numberWithInt:nbPoss % [[array objectAtIndex:i] count]];
NSString * literal = [[array objectAtIndex:i] objectAtIndex:[num intValue]];
[arr insertObject:literal atIndex:i];
}
}
return possArr;
}
I wrote a program to sort a randomly generated array of 50 integers from greatest to least. So far it works, but it will occasionally return random zeros at the end of the sorted array. These zeros are not present in the unsorted array, and they do not always appear. Here's my program:
#import <Foundation/Foundation.h>
#interface Number: NSObject
- (void) start;
- (int) getValue;
- (void) counted;
- (void) placeValue: (int) a;
#end
#implementation Number
{
int x;
}
- (void) start
{
x = arc4random_uniform(1000);
if (x == 1)
{
x = x+1;
}
}
- (int) getValue
{
return x;
}
- (void) counted
{
x = 0;
}
- (void) placeValue: (int) a
{
x = a;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool
{
NSMutableArray *unsortedArray = [[NSMutableArray alloc] initWithCapacity: 50];
for (int n = 0; n < 50; n++)
{
Number *num = [[Number alloc] init];
[num start];
[unsortedArray addObject: num];
}
for (int n = 0; n < 50; n++)
{
printf("%i, ", [unsortedArray[n] getValue]);
}
printf ("unsorted array.\n\n");
int x = 0;
int y = 1001;
for (int n = 0; n < 50; n++)
{
for (int m = 0; m < 50; m++)
{
if (([unsortedArray[m] getValue] > x) && ([unsortedArray[m] getValue] < y))
{
x = [unsortedArray[m] getValue];
}
}
printf("%i, ", x);
y = x;
x = 0;
}
printf("sorted array.\n");
} return 0;
}
Try this:
- (void)start
{
x = (arc4random_uniform(1000) + 1);
}
You don't want to only be increasing x when you hit 0 or 1, since that will skew the results. arc4random_uniform will return a random number less than 1000 in this case, so 0 -> 999, adding 1 to all values, gives you 1 -> 1000. Adjust your numbers to suit what you need.
There are other issues in your code though. Why create your own Number class? Why create your own sort method? Use NSNumber and NSArray's sort methods.
Here is a much cleaner version:
int main(int argc, const char * argv[])
{
#autoreleasepool
{
NSMutableArray* unsortedArray = [[NSMutableArray alloc] initWithCapacity:50];
for (NSUInteger n = 0; n < 50; ++n) {
[unsortedArray addObject:#(arc4random_uniform(999) + 1)];
}
for (NSUInteger n = 0; n < 50; ++n) {
printf("%li, ", (long)[unsortedArray[n] integerValue]);
}
printf ("unsorted array.\n\n");
NSArray* sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj2 compare:obj1];
}];
for (NSUInteger n = 0; n < 50; ++n) {
printf("%li, ", (long)[sortedArray[n] integerValue]);
}
printf("sorted array.\n");
}
return 0;
}
- (void) start
{
x = arc4random_uniform(1000);
if (x == 0)
x = x + 1;
}
Everyone is focusing on the fact that arc4random_uniform can generate zero as an acceptable value (which is true), but there is another problem: Your sort algorithm is incorrect, as it will only work if the values in the array are unique. But, if you have any duplicate values (and there's no assurances that arc4random_uniform won't generate some duplicates), your algorithm will show only one of those values, and thus, by the time you get to the end, you'll see a bunch of extra zeros.
There are tons of different sorting algorithms, but it's probably easier to just avail yourself of one of the native NSMutableArray sort methods, which gets you out of the weeds of writing your own.
I create this objective C class to Genrate prime numbers from n to limit. I have problem I could not get the item in NSMutableArray inside for loop. can some one show me how can I fix it?
#implementation Prime
-(NSMutableArray *)generatePrimes:(int)upperLimit{
NSMutableArray *primes = [[NSMutableArray alloc]init];
bool isPrime;
int j;
[primes addObject:[NSDecimalNumber numberWithInt:2]];
for (int i= 3; i <= upperLimit ; i+=2) {
j = 0;
isPrime = YES;
NSInteger index;
for(id obj in primes)
{
index = [primes indexOfObject:obj];
if((index * index) <= i )
{
if(i % index == 0)
{
isPrime = NO;
break;
}
}
}
if(isPrime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
#end
This question is a little vague, but it seems to me what you're trying to do is convert the NSDecimalNumber back into an int. What your code is actually doing is getting the number's index inside the array (ie the first object is 0, the second is 1, etc.) If you are trying to get the original value of i, change these lines:
for(id obj in primes)
{
index = [primes indexOfObject:obj];
to this:
for(NSDecimalNumber num in primes)
{
index = [num integerValue];
I'd also recommend using a different name than index, as that's misleading as to what you're actually doing.
-(NSMutableArray *)generatePrimes:(int)upperLimit
{
NSMutableArray *primes = [[NSMutableArray alloc]init];
bool isPrime;
for (int i=2; i<upperLimit; i++)
{
bool prime = true;
for (int j=2; j*j<=i; j++)
{
if (i % j == 0)
{
prime = false;
break;
}
}
if(prime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
or
-(NSMutableArray *)generatePrimes:(int)upperLimit
{
NSMutableArray *primes = [[NSMutableArray alloc]init];
[primes addObject:[NSDecimalNumber numberWithInt:2]];
for(int i=3; i < upperLimit; i++)
{
bool prime=true;
for(int j=0;j<primes.count && (((NSDecimalNumber *)primes[j]).integerValue*((NSDecimalNumber *)primes[j]).integerValue) <= i;j++)
{
if(i % (((NSDecimalNumber *)primes[j]).integerValue) == 0)
{
prime=false;
break;
}
}
if(prime)
{
[primes addObject:[NSDecimalNumber numberWithInt:i]];
}
}
return primes;
}
Hope this helps!
i have written the following code to check anagram want to know is this perfect & is there any better way to implement the same in objective C
-(BOOL) findAnagram :(NSString *) string1 :(NSString *) string2
{
int len = string1.length;
if (len != string2.length)
{
return false;
}
for (int i=0; i < len; i++)
{
int h = 0;
int q = 0;
for (int k = 0; k < len ; k ++)
{
if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k])
{
h++;
}
if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k])
{
q++;
}
}
if (h!=q)
{
return false;
}
}
return TRUE;
}
A better performing version than yours, which is a O(n ^ 2) algorithm, is a O(n) algorithm:
BOOL anagrams(NSString *a, NSString *b)
{
if (a.length != b.length)
return NO;
NSCountedSet *aSet = [[NSCountedSet alloc] init];
NSCountedSet *bSet = [[NSCountedSet alloc] init];
for (int i = 0; i < a.length; i++)
{
[aSet addObject:#([a characterAtIndex:i])];
[bSet addObject:#([b characterAtIndex:i])];
}
return [aSet isEqual:bSet];
}
You want to know if two strings contain exactly the same characters? Easiest way would probably be to sort both of them and compare the sorted version.
Another way would be to count the number of appearances of each letter (how many As, how many Bs, and so forth), then compare those counts.
(Note: The second way is just a variation of the first one, it's one efficient way to sort a string)
It looks fine to me. But the code style is slightly odd. I would write it like this:
- (BOOL)isStringAnagram:(NSString *)string1 ofString:(NSString *)string2 {
int len = string1.length;
if (len != string2.length) {
return NO;
}
for (int i=0; i < len; i++) {
int h = 0;
int q = 0;
for (int k = 0; k < len; k++) {
if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k]) {
h++;
}
if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k]) {
q++;
}
}
if (h != q) {
return NO;
}
}
return YES;
}
The main issue I have is with the method name. While it's possible to have parameters that have nothing before them in the name, it is not advisable. i.e. you had findAnagram:: as the name whereas I've used isStringAnagram:ofString:.
This is an implementation on #zmbq suggestion of sorting and comparing.
You should consider the requirements of deleting spaces and being case insensitive.
- (BOOL)isAnagram:(NSString *)leftString and:(NSString *)rightString {
NSString *trimmedLeft = [[leftString stringByReplacingOccurrencesOfString:#" " withString:#""] lowercaseString];
NSString *trimmedRight = [[rightString stringByReplacingOccurrencesOfString:#" " withString:#""] lowercaseString];
return [[self stringToCharArraySorted:trimmedLeft] isEqual:[self stringToCharArraySorted:trimmedRight]];
}
- (NSArray *)stringToCharArraySorted:(NSString *)string {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0 ; i < string.length ; i++) {
[array addObject:#([string characterAtIndex:i])];
}
return [[array sortedArrayUsingSelector:#selector(compare:)] copy];
}
called like this
BOOL isAnagram = [self isAnagram:#"A BC" and:#"cba"];
Check the following method which check Anagram strings.
-(BOOL)checkAnagramString:(NSString*)string1 WithAnotherString:(NSString*)string2{
NSCountedSet *countSet1=[[NSCountedSet alloc]init];
NSCountedSet *countSet2=[[NSCountedSet alloc]init];
if (string1.length!=string2.length) {
NSLog(#"NOT ANAGRAM String");
return NO;
}
for (int i=0; i<string1.length; i++) {
[countSet1 addObject:#([string1 characterAtIndex:i])];
[countSet2 addObject:#([string2 characterAtIndex:i])];
}
if ([countSet1 isEqual:countSet2]) {
NSLog(#"ANAGRAM String");
return YES;
} else {
NSLog(#"NOT ANAGRAM String");
return NO;
}
}
Another run of the mill algorithm:
- (BOOL) testForAnagramWithStrings:(NSString *)stringA andStringB: (NSString *)stringB{
stringA = [stringA lowercaseString];
stringB = [stringB lowercaseString];
int counter = 0;
for (int i=0; i< stringA.length; i++){
for (int j=0; j<stringB.length;j++){
if ([stringA characterAtIndex:i]==[stringB characterAtIndex:j]){
counter++;
}
}
}
if (counter!= stringA.length){
return false;
}
return true;
}
I am trying to sort 15 random numbers using Objective-C in the code shown below. The code is not working as planned. I took the concept from the the insertion sort C code. The 15 random numbers are generating properly but the sort is not working.
C code:
int i, j, index;
for (i = 1; i < array_size; ++i)
{
index = a[i];
for (j = i; j > 0 && a[j-1] > index; j--)
a[j] = a[j-1];
a[j] = index;
}
Objective-C code:
-(IBAction)clicked_insertsort:(id)sender
{
NSMutableArray *array = [NSMutableArray array];
for (int x = 0; x < 15; x++)
{
[array addObject: [NSNumber numberWithInt: arc4random()%200]];
}
NSLog(#"%#",array);
{
int i, j;
id index;
for (i = 1; i < 15; ++i)
{
index = [array objectAtIndex:(NSUInteger)i]; // a[i];
for (j = i; j > 0 && [array objectAtIndex:(NSUInteger)j-1] > index; j--)
[array replaceObjectAtIndex: (j) withObject: [array objectAtIndex: (j-1)]];
[array objectAtIndex:(NSUInteger)j] == index ;
}
}
NSLog(#"%#",array);
}
You are comparing pointers, which is just sorting your array by the memory addresses of your objects, not their actual value.
index = [array objectAtIndex:(NSUInteger)i]; // a[i];
[array objectAtIndex:(NSUInteger)j-1] > index
You need to get the primitive integer value of the NSNumber:
[NSNumber numberWithInt:20] != 20; // This is wrong.
[[NSNumber numberWithInt:20] intValue] == 20; // This is correct.
Here's your code, with revisions:
-(IBAction)clicked_insertsort:(id)sender
{
NSMutableArray *array = [NSMutableArray array];
for (int x = 0; x < 15; x++)
{
[array addObject: [NSNumber numberWithInt: arc4random()%200]];
}
NSLog(#"%#",array);
{
int i, j;
id index;
for (i = 1; i < 15; ++i)
{
index = [[array objectAtIndex:(NSUInteger)i] intValue]; // a[i];
for (j = i; j > 0 && [[array objectAtIndex:(NSUInteger)j-1] intValue] > index; j--)
[array replaceObjectAtIndex: (j) withObject: [array objectAtIndex: (j-1)]];
[[array objectAtIndex:(NSUInteger)j] intValue] == index ;
}
}
NSLog(#"%#",array);
}
Actually the problem is that the algorithm itself does not make much sense.
This line:
[array objectAtIndex:(NSUInteger)j] == index ;
Should be:
[array replaceObjectAtIndex:j withObject:index]; //yes again
Try this way, with modern syntax:
-(IBAction)clicked_insertsort:(id)sender
{
NSMutableArray *array = [NSMutableArray array];
for (int x = 0; x < 15; x++)
{
[array addObject: #(arc4random()%200)];
}
NSLog(#"%#",array);
NSUInteger i, j;
for (i = 1; i < 15; ++i)
{
NSNumber *current = array[i];
for (j = i; j > 0 && [array[j-1] unsignedIntegerValue] > [current unsignedIntegerValue]; j--)
array[j] = array[j-1];
array[j] = current;
}
NSLog(#"%#",array);
}
Run the code and see the result.