Reading random values from an array - objective-c

I have an array with a 14 strings. I want to display each of these 14 strings to the user without duplicates. The closest I got was creating an array of integers and shuffling their values, and then reading from the array of strings using one of the numbers from the int array as the index:
//appDelegate.randomRiddles is an array of integers that has integer values randomly
appDelegate.randomRiddlesCounter++;
NSNumber *index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
int i = [index intValue];
while(i>[appDelegate.currentRiddlesContent count]){
appDelegate.randomRiddlesCounter++;
index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
i = [index intValue];
}
hintText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"hint"];
questionText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"question"];
But my way is causing crashing and duplicates. Oh and each time I read a value from the strings array, that string is removed from the array making its count decrease by 1. So that complicates this a little bit.

Get the elements in your array like this:
int position = arc4random() % ([myArray count]);
This way even though count decreases by one, that is ok, as you will still get a valid next position value till there aren't any more posible values.

By "without duplicates" I assume you mean that you want to use each string in the array once before you use the same string again, not that you want to filter the array so it doesn't contain duplicate strings.
Here's a function that uses a Fisher-Yates shuffle:
/** #brief Takes an array and produces a shuffled array.
*
* The new array will contain retained references to
* the objects in the original array
*
* #param original The array containing the objects to shuffle.
* #return A new, autoreleased array with all of the objects of
* the original array but in a random order.
*/
NSArray *shuffledArrayFromArray(NSArray *original) {
NSMutableArray *shuffled = [NSMutableArray array];
NSUInteger count = [original count];
if (count > 0) {
[shuffled addObject:[original objectAtIndex:0]];
NSUInteger j;
for (NSUInteger i = 1; i < count; ++i) {
j = arc4random() % i; // simple but may have a modulo bias
[shuffled addObject:[shuffled objectAtIndex:j]];
[shuffled replaceObjectAtIndex:j
withObject:[original objectAtIndex:i]];
}
}
return shuffled; // still autoreleased
}
If you want to keep the relationship between the riddles, hints, and questions then I'd recommend using a NSDictionary to store each set of related strings rather than storing them in separate arrays.

This task is very easy using an NSMutableArray. In order to do this, simply remove a random element from the array, display it to the user.
Declare a mutable array as an instance variable
NSMutableArray * questions;
When the app launches, populate with values from myArray
questions = [[NSMutableArray alloc] initWithArray:myArray]];
Then, to get a random element from the array and remove it, do this:
int randomIndex = (arc4random() % [questions count]);
NSDictionary * anObj = [[[questions objectAtIndex:randomIndex] retain] autorelease];
[questions removeObjectAtIndex:randomIndex];
// do something with element
hintText.text = [anObj objectForKey:#"hint"];
questionText.text = [anObj objectForKey:#"question"];

No need to type that much. To shuffle an array, you just sort it with random comparator:
#include <stdlib.h>
NSInteger shuffleCmp(id a, id b, void* c)
{
return (arc4random() & 1) ? NSOrderedAscending : NSOrderedDescending;
}
NSArray* shuffled = [original sortedArrayUsingFunction:shuffleCmp context:0];

You could copy the array into an NSMutableArray and shuffle that. A simple demonstration of how to shuffle an array:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Original array, here initialised with 1..9
NSArray *arr = [NSArray arrayWithObjects:
[NSNumber numberWithInt: 1],
[NSNumber numberWithInt: 2],
[NSNumber numberWithInt: 3],
[NSNumber numberWithInt: 4],
[NSNumber numberWithInt: 5],
[NSNumber numberWithInt: 6],
[NSNumber numberWithInt: 7],
[NSNumber numberWithInt: 8],
[NSNumber numberWithInt: 9],
nil];
// Array that will be shuffled
NSMutableArray *shuffled = [NSMutableArray arrayWithArray: arr];
// Shuffle array
for (NSUInteger i = shuffled.count - 1; i > 0; i--)
{
NSUInteger index = rand() % i;
NSNumber *temp = [shuffled objectAtIndex: index];
[shuffled removeObjectAtIndex: index];
NSNumber *top = [shuffled lastObject];
[shuffled removeLastObject];
[shuffled insertObject: top atIndex: index];
[shuffled addObject: temp];
}
// Display shuffled array
for (NSNumber *num in shuffled)
{
NSLog(#"%#", num);
}
[pool drain];
return 0;
}
Note that all arrays and numbers here are autoreleased, but in your code you might have to take care of memory management.
If you don't have to keep the elements in the array, you can simplify that (see Oscar Gomez' answer too):
NSUInteger index = rand() % shuffled.count;
NSLog(#"%#", [shuffled objectAtIndex: index]);
[shuffled removeObjectAtIndex: index];
At the end, shuffled will be empty. You will have to change the loop conditions too:
for (NSUInteger i = 0; i < shuffled.count; i++)

Related

How to multiply respective objects of NSArray and get the sum?

I have one array with data A=[a,b,c] and another with data B=[d,e,f]. I need to perform this type of operation a.d+ b.e+c.f (Note=Here (.) denotes multplication)and get the result. How can i do that using Objective-C?
Thanks in advance.
Define the function that does the multiplication and addition like this:
- (double)multiply:(NSArray <NSNumber *> *)vector1 withVector:(NSArray <NSNumber *> *)vector2 {
NSAssert(vector1.count == vector2.count, #"Both arrays should contain the same number of elements");
__block double result = 0;
[vector1 enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
double first = obj.doubleValue;
double second = vector2[idx].doubleValue;
result += first * second;
}];
return result;
}
This uses a block enumeration method on NSArray which gives me in index and a value, which I can use to get the value at the same index in the second array. Note also that I am using a typed array, so I don't have to cast the values to NSNumbers when using them.
Now you can just use the function:
NSArray *a = #[#1, #2, #3];
NSArray *b = #[#4, #5, #6];
NSArray *c = #[#1, #1, #1];
double res1 = [self multiply:a withVector:b]; // => 32.000000
double res2 = [self multiply:b withVector:c]; // => 15.000000
double res3 = [self multiply:c withVector:a]; // => 6.000000
NSNumber *myNum1 = [NSNumber numberWithInt:1];
NSNumber *myNum2 = [NSNumber numberWithInt:2];
NSNumber *myNum3 = [NSNumber numberWithInt:3];
NSArray *a = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
NSArray *b = [NSArray arrayWithObjects: myNum1, myNum2, myNum3, nil];
int sum=0;
for (int i=0; i<[a count]; i++) {
NSLog(#"%#", (NSNumber*)[a objectAtIndex:i]);
sum =sum +[(NSNumber*)[a objectAtIndex:i] intValue]*[(NSNumber*)[b objectAtIndex:i] intValue];
}
NSLog(#"Sum is %d", sum);
Hope this helps

how to get the index on numbers generated by int arc4random()

How do you get the index of the number appearing from the arc4rand method?. If 4,1,2,3 appear how do you index them . Example 4 would be 0 in the array.
int rand=((arc4random()%4)+1);
For getting random number, i did like this:
Suppose, i have a mutable array
NSMutableArray * myArray = [[NSMutableArray alloc] init];
and i kept 5 data in this myArray.
Now I have to generate random number index from myArray.
int randomIndex = (arc4random() % ([myArray count]));
Here randomIndex is random index of array
try this one. you need to put all that values into array.
NSMutableArray * array = [[NSMutableArray alloc] initWithCapacity:4];
[array insertObject:#"4" atIndex:0];
[array insertObject:#"1" atIndex:1];
[array insertObject:#"2" atIndex:2];
[array insertObject:#"3" atIndex:3];
using array to get index in ios to add all values in array like this
//convert int to nsstring and add array
NSArray *array=[NSArray arrayWithObjects:NSStringFromInt(4),NSStringFromInt(1),NSStringFromInt(2),NSStringFromInt(3), nil];
//reverse process to get int value
int value=[[array objectAtIndex:index]integerValue];
I'm just guessing, you might look for this...
NSMutableArray *_array = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[_array addObject:#((arc4random()%4)+1)];
}

Objective C - Array With Numbers

Is there a nicer way to fill an array with numbers than what I use?
It's crazy how much I got to write just to fill an array with numbers so they can be used for a calculation in a loop. This is easier in other C based languages like PHP, As3, or Java.
NSArray *myArray = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1000],[NSNumber numberWithInt:237], [NSNumber numberWithInt:2673], nil];
int total = 0;
for(int i = 0; i < [myArray count]; i += 1 ){
total += [[myArray objectAtIndex: i]intValue];
NSLog(#"%i", total);
}
Hopefully there is a shorter way... I just want to fill an array with ints... cant be that hard
I guess you have to use NSNumber for an NSArray. If you want to use ints I guess you'd have to use a c array:
NSInteger myArray[20];
for (int i=0;i<20;i++) {
int num=myArray[i];
//do something
}
NSNumber though is I guess the better approach for this language.
At least you can do fast enumeration to shorten code a bit:
for (NSNumber *n in myArray) {
int num = [n intValue];
//do something....
}
EDIT:
The question has been asked 3 years ago. There have been new literals established to make it easier to create objects like NSNumbers or NSArrays:
NSNumber *n = #100;
or
NSArray *array = #[#100,#50,#10];
Nice short alternative for looping specific integers:
NSArray *numbers = [#"1000,237,2673" componentsSeparatedByString:#","];
for (NSString *i in numbers) {
[i intValue]; // Do something.
}
First start with a C array:
NSInteger myCArray = { 1000, 237, 2673 };
// calculate number of elements
NSUInteger myCArrayLength = sizeof(myCArray) / sizeof(NSInteger;
Second, if you need an NSArray loop through this array and create one:
NSMutableArray *myNSArray = [NSMutableArray arrayWithCapacity:myCArrayLength];
for(NSUInteger ix = 0; ix < myCArrayLength; ix++)
[myNSArray addObject:[NSNumber numberWithInteger:myCArray[ix]];
You can wrap the second piece of code up as a category on NSArray if you're doing it a lot.
too late. but u can do the following too.
int total = 0;
nsarray *myArray = #[#1.8,#100,#299.8];
for(nsnumber *num in myArray){
total+=num;
}

Populating array with integers

Let's say I want to populate NSarray with 50 integers. We know that NSarray accept only objects. So I have to do 50 times
NSNumber *num1 = [NSNumber numberWithInit:10];
NSNumber *num2 = [NSNumber numberWithInit:212];
......
NSNumber *num50 = [NSNumber numberWithInit:12];
Is there more elegant way to achieve that, beacause looks stupid 50 lines of code only for create number objects ?
try this...
NSMutableArray *array=[[NSMutableArray alloc]initWithCapacity:50 ];
for (int i=0; i<0; i++) {
NSNumber *number=[[NSNumber alloc] initWithInt:i];
[array addObject:number];
[number release];
}
//do anything with arrray and release the array later.
is this OK or you are seeking anything else.?
How about using NSMutableArray?
NSMutableArray* arr = [[NSMutableArray alloc] init];
int i = 0;
for(i=0; i<50; i++) {
NSNumber* num = [NSNumber numberWithInt:i]; // use i or random numbers
[arr addObject:num];
}
Your numbers do not seem to follow any particular pattern, so you might be better doing this by creating a C array first:
int myValues[] = { 10, 212, ..., 12 };
NSUInteger count = sizeof(myValues)/sizeof(int); // number of integers in myValues
// abstract the following into a function/method/category if doing more than once
NSMutableArray *objcValues = [NSMutableArray arrayWithCapacity:count];
for(NSUInteger ix = 0; ix < count; ix++)
[objcValues addObject:[NSNumber numberWithInt:myValues[ix]];

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];