Creating NSArray of repeated numbers - objective-c

I want to initialize NSArray with given numbers of zeros. I need it to create an array of counters and in the end of the function return an index of the counter with highest value.
So the question is how to initialize NSArray of zeros of given length? Is there a good way to do it in 1-2 lines? Maybe there is a better way to count objects? How would you do it?
Thanks!
UPD: Here is the code of my existing function. It returns the maximum number of cards, which have the same rank.
+ (int)ranksMatched:(NSArray *)cards
{
NSMutableArray *ranksCounter = [[NSMutableArray alloc] initWithCapacity:[PlayingCard maxRank]];
for (int i = 0; i < [PlayingCard maxRank]; ++i) {
[ranksCounter addObject:[NSNumber numberWithInt:0]];
}
int maxIndex = 0;
int maxCount = 0;
for (PlayingCard *card in cards) {
int currentCount = [ranksCounter[card.rank] intValue] + 1;
if (maxCount < currentCount) {
maxCount = currentCount;
maxIndex = card.rank;
}
}
return maxCount;
}

I guess you want the group the cards by rank and return the rank of the largest group:
+ (int)ranksMatched:(NSArray *)cards
{
NSCountedSet *ranks = [NSCountedSet setWithArray:[cards valueForKeyPath:#"rank"]];
NSNumber *maxRank = nil;
NSUInteger maxCount = 0;
for (NSNumber *rank in ranks) {
NSUInteger rankCount = [ranks countForObject:rank];
if (rankCount > maxCount) {
maxRank = rank;
maxCount = rankCount;
}
}
return [maxRank intValue];
}
assuming you have
#interface PlayingCard : NSObject
#property (nonatomic, assign) int rank;
…
#end
And cardsis an array of PlayingCard.

Related

How to send values to Ivar in method

new to Objective-C and keeping it very very simple I'm looking to understand one thing at a time... I set up a very simple class called student all it does is add two numbers trying to see how things pass into and back from methods) **I rewrote the code ==>> look at end to see the version that works **
If I have a method that has
#property (nonatomic) int firstNum;
#property (nonatomic) int secondNum;
and I have an instance of my class called student I assign a value to firstNum like student.firstNum = 100; student.secondNum = 77; that is easy and the method adds them and sends the sum in a return
But in main I tried assigning it from an array and it did not work I tried
student.firstNum = [myIntegers objectAtIndex:0];
and
student.firstNum = [myIntegers objectAtIndex:i]; //using a for loop with i index
it says incompatible pointer to integer conversion
Here is the snippet from main I tried it's not complete it just is trying to set firstNum eventually I will also set up secondNum and send each pair to the method to get added together but for now I am stuck trying to get the firstNum assigned the value in myIntegers[i] to start
NSMutableArray *myIntegers = [NSMutableArray array];
for (NSInteger i= 0; i <= 10; i++) {
[myIntegers addObject:[NSNumber numberWithInteger:i]]; // this works up to here
student.firstNum = [myIntegers objectAtIndex:i]; // this does not work
}
I also tried [i].
Here is my method:
- (int)addNumbers {
int sum = self.firstNum + self.secondNum;
return sum;
}
HERE IS WHAT WORKS : assuming I have a student object
.m
(long)addNumbers:(NSNumber *)x :(NSNumber *)y {
long sum;
sum = [x integerValue] + [y integerValue];
return sum;
}
main
NSMutableArray *myIntegers1 = [NSMutableArray array];
NSMutableArray *myIntegers2 = [NSMutableArray array];
for (NSInteger i= 0; i <40; i++) {
[myIntegers1 addObject:[NSNumber numberWithInteger:i]];
[myIntegers2 addObject:[NSNumber numberWithInteger:i]];
long sum = [student addNumbers:[myIntegers1 objectAtIndex:i] :[myIntegers2 objectAtIndex:i]];
NSLog(#" The sum is %ld", sum);
}
You are creating a properties of type int, but in your for loop, you are trying to assign them an NSNumber.
NSNumber is a simple container for a c data item and can hold int, float, char, bool, etc.
Change your loop to be like that:
for (NSInteger i= 0; i <= 10; i++) {
[myIntegers addObject:[NSNumber numberWithInteger:i]];
student.firstNum = [[myIntegers objectAtIndex:i] intValue]; // this 'extracts' the int value from the NSNumber
}

Why does my sorted array occasionally return random 0s at the end?

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.

How to generate non repeating random number

I am trying to randomize numbers in an array. I am able to do that using arc4random() % [indexes count]
My problem is - If an array consists of 20 items, every time the array shuffles, in a batch of 5, different number should appear. Example :
first shuffle: 1,4,2,5,6.
second shuffle: 7,12,9,15,3
-(IBAction)randomNumbers:(UIButton *)sender
{
int length = 10; // int length = [yourArray count];
NSMutableArray *indexes = [[NSMutableArray alloc] initWithCapacity:length];
for (int i=0; i<5; i++)
[indexes addObject:[NSNumber numberWithInt:i]];
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:length];
while ([indexes count])
{
int index = arc4random() % [indexes count];
[shuffle addObject:[indexes objectAtIndex:index]];
[indexes removeObjectAtIndex:index];
}
// for (int i=0; i<[shuffle count]; i++)
NSLog(#"%#", [shuffle description]);
}
As per your requirement....kindly check this code
Make this a property
#synthesize alreadyGeneratedNumbers;
Add these methods in your .m
-(int)generateRandomNumber{
int TOTAL_NUMBER=20;
int low_bound = 0;
int high_bound = TOTAL_NUMBER;
int width = high_bound - low_bound;
int randomNumber = low_bound + arc4random() % width;
return randomNumber;
}
-(IBAction)randomNumbers:(UIButton *)sender
{
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:5];
BOOL contains=YES;
while ([shuffle count]<5) {
NSNumber *generatedNumber=[NSNumber numberWithInt:[self generateRandomNumber]];
//NSLog(#"->%#",generatedNumber);
if (![alreadyGeneratedNumbers containsObject:generatedNumber]) {
[shuffle addObject:generatedNumber];
contains=NO;
[alreadyGeneratedNumbers addObject:generatedNumber];
}
}
NSLog(#"shuffle %#",shuffle);
NSLog(#"Next Batch");
if ([alreadyGeneratedNumbers count] >= TOTAL_NUMBER) {
NSLog(#"\nGame over, Want to play once again?");//or similar kind of thing.
[alreadyGeneratedNumbers removeAllObjects];
}
}
Still I feel you need to some changes like
it will give you correct value, but what if user pressed 5th time?
out of 20 numbers you already picked 4 sets of 5 number, on on 6th time it will be in loop to search for next set of numbers and will become infinite.
So what you can do is, keep the track of shuffle and once it reaches the limit i.e, 20/5=4 disable the random button.
Declare array that contains already generated number in extension or header file
#property (strong, nonatomic)NSMutableArray *existingNums;
#property (assign, nonatomic)NSInteger maxLimit;
#property (assign, nonatomic)NSInteger minLimit;
Then implement given code in implementation file
#synthesize existingNums;
#synthesize maxLimit;
#synthesize minLimit;
- (NSInteger)randomNumber {
if(!existingNums)
existingNums = [NSMutableArray array];
while (YES) {
NSNumber *randonNum = [NSNumber numberWithInteger:minLimit+arc4random()%maxLimit];
if([existingNums containsObject:randonNum]) {
if([existingNums count] == (maxLimit - minLimit))
return -1; // All possible numbers generated in the given range
continue;
}
[existingNums addObject:randonNum];
return [randonNum integerValue];
}
return -1; // return error
}
Hope this will help you :)
This one works for me:
NSMutableArray *numbers = [NSMutableArray new];
BOOL addElement = YES;
int limit = 100; // Range from 0 to 36
int numElem = 10; // Number of elements
do
{
int ranNum = (arc4random() % limit) +1;
if ([numbers count] < numElem) {
for (NSNumber *oneNumber in numbers) {
addElement =([oneNumber intValue] != ranNum) ? YES:NO;
if (!addElement) break;
}
if (addElement) [numbers addObject:[NSNumber numberWithInt:ranNum]];
} else {
break;
}
} while (1);
NSLog(#"%#",numbers);
The problem with all these answers is that you need to review your previous generated random numbers and that takes extra time if you need a large number of random integers.
Another solution is using cryptography:
Generate a random key
Iterate between 0..n
Encrypt each integer and apply modulo the number of alternatives do you want to use to the output of the function.
There are some extra details to take into account that don't matter for your case.

Adding an object to a NSMutablearray doesn't work properly

I have a situation where in a loop I'm trying to add an object to a NSMutableArray. At the end of the loop it is showing that 54 objects (as an example) are added to the array but when I'm trying to read the objects from the array, apparently they are all the same as each other and same as the last object that is inserted into the array.
Could anyone please help me with this issue.This is my code:
int counter=0;
for (int j=0; j<rows; j++)
{
Product *product ;
product = [[Product alloc] init];
int numberr= [product getImageNumber];
[wineList addObject:product];
counter = counter + 1;
}
After adding the objects,I'm testing the content of the array which I'm getting the same result for each item in the array
//testing
Product *producttest1 = wineList[1];
int numbertest1= [producttest1 getImageNumber];
Product *producttest2 = wineList[20];
int numbertest2= [producttest2 getImageNumber];
This is the definition of the Product class that I have :
#import "Product.h"
#implementation Product
int imageNumber;
bool isInCase;
-(id) init {
imageNumber = (arc4random() % 11) + 1;
isInCase = false;
return self;
}
-(int) getImageNumber {
return imageNumber;
}
-(void) setImageNumber:(int) number {
imageNumber = number;
}
Your -init method never initializes your class. Make a call to [super init].
-(id)init {
self = [super init];
if (self) {
imageNumber = (arc4random() % 11) + 1;
isInCase = false;
}
return self;
}
Your code should probably go like this,
int counter=0;
for (int j=0; j < rows; j++)
{
Product *product = [[Product alloc] init]; // Added variable declaration inside.
int numberr= [product getImageNumber];
[wineList addObject:product];
[product release]; // Added release for product
counter = counter + 1;
}

Reversing "columns" in a table made from a NSArray

I have a NSArray made out of numbers 1..50, which represents a table with columns & rows.
I need to reverse only the order of the columns, while keeping the order of the rows.
So for example:
0,1,2,3,4,5,6
7,8,9,9,10,11,12
has to be
6,5,4,3,2,1,0
12,11,10,9,8,7
Right now, i use a huge IF statement for that:
for (dd *d in dates[i]) {
if (tileNum==0) {
reversedTileNum = 6;
} else if (tileNum==1) {
reversedTileNum = 5;
}else if (tileNum==2) {
reversedTileNum = 4;
}else if (tileNum==3) {
reversedTileNum = 3;
}else if (tileNum==4) {
reversedTileNum = 2;
}else if (tileNum==5) {
reversedTileNum = 1;
} else if (tileNum==6) {
reversedTileNum = 0;
}
....
....
}
Here's a solution that should be easy to drop into any project. It involves two categories: one on NSMutableArray that provides a method to swap objects at two indices, and one on NSArray that provides the -arrayByReversingGroups: method. The idea is to swap the elements in pairs within a group, reversing the group. If number of elements in the array isn't an even multiple of groupSize, the extras at the end are left untouched.
The code presented here is a complete program, so you can see an example of using -arrayByReversingGroups: in the main() function.
#import <Foundation/Foundation.h>
#interface NSArray(Reversible)
-(NSArray*)arrayByReversingGroups:(int)groupSize;
#end
#interface NSMutableArray(Swappable)
-(void)swapObjectAtIndex:(int)first withObjectAtIndex:(int)second;
#end
#implementation NSArray(Reversible)
-(NSArray*)arrayByReversingGroups:(int)groupSize
{
NSMutableArray *newArray = [self mutableCopy];
// Iterate over the array in chunks of groupSize elements. i will be first index in
// the current chunk.
for (int i = 0; (i + groupSize) < [newArray count]; i += groupSize) {
// Iterate over the items in the current chunk, swapping the bth and
// (groupsize-b-1)th elements until they meet at groupsize/2.
for (int b = 0; b <= (groupSize / 2); b++) {
int first = i + b;
int second = i + groupSize - b - 1;
[newArray swapObjectAtIndex:first withObjectAtIndex:second];
}
}
return [newArray copy];
}
#end
#implementation NSMutableArray(Swappable)
-(void)swapObjectAtIndex:(int)first withObjectAtIndex:(int)second
{
id temp = [[self objectAtIndex:second] retain];
[self replaceObjectAtIndex:second withObject:[self objectAtIndex:first]];
[self replaceObjectAtIndex:first withObject:temp];
[temp release];
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSArray *array = [NSArray arrayWithObjects:
#"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", #"9", #"10", #"11", #"12", nil];
NSLog(#"Original: %#", array);
NSLog(#"Reversed: %#", [array arrayByReversingGroups:5]);
}
return 0;
}
I can give you the logic.. you will have to write the code...
First create a function where you pass in an array(here you will send in a row.) then in this function create a new tempeorary array and store all the values for that row in this column then overwrite the original array in reverse order from this new array and return this to the full matrix and store it in there ... hope it helps.