shuffle array repeats One value - iphone

Here i used the following code to shuffle the NSMuttable Array, While shuffling The array repeats only one value and remaining all works properly, what change should i made to shuffle without repeating?
words = [[NSMutableArray alloc] initWithObjects:#"1", #"2", #"3",#"4", nil] ;
NSUInteger count = [words count];
for (int i = 0; i < count; i++)
{
NSInteger nElements = count - i;
NSInteger n = (arc4random() % nElements) + i;
NSLog(#"n val %d i val %d",i,n);
[words exchangeObjectAtIndex:i withObjectAtIndex:n];
}
NSlog Output
2012-12-31 12:49:05.730 quizer[1607:c07] n val 0 i val 0
2012-12-31 12:49:05.731 quizer[1607:c07] n val 1 i val 3
2012-12-31 12:49:05.731 quizer[1607:c07] n val 2 i val 2
2012-12-31 12:49:05.732 quizer[1607:c07] n val 3 i val 3
Please Help me to solve

This code may help you,
The shuffle array contains each number between 0 to TOTAL_NUMBER (your array size) only once.
From which you can shuffle your existing array.
#synthesize alreadyGeneratedNumbers;//this is a mutableArray.
int TOTAL_NUMBER=5;//size of array
-(int)generateRandomNumber{
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 *startArray=[NSMutableArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
NSMutableArray *shuffle = [NSMutableArray new];
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];
}
}
if ([alreadyGeneratedNumbers count] >= TOTAL_NUMBER) {
NSLog(#"\nOne shuffel ended.....what to reshuffle");
[alreadyGeneratedNumbers removeAllObjects];
}
NSMutableArray *shuffledArray=[NSMutableArray new];
for (NSNumber *index in shuffle) {
[shuffledArray addObject:[startArray objectAtIndex:[index integerValue]]];
}
NSLog(#"Shuffled array = %#",shuffledArray);
}

To remove duplicates from your NSMutableArray,
// Removing duplicate entry from array
NSArray *copy = [words copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator])
{
if ([words indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound)
{
[words removeObjectAtIndex:index];
}
index--;
}
[copy release];
You can check it for each time you add the object.

Related

Sort NSArray for a specific order

I have an NSArray of custom objects.
Each object contains one integer value for ex. 1,2,3,4
Now I want to sort Array like below
9 7 5 3 1 2 4 6 8
Could some one help me?
Here is your answer.
Hope your first array is in sorted order (ascending) if not then you need to sort it first.
NSMutableArray *myArray = [NSMutableArray array];
//Populate your array with custom objects. I had created my own which contain an integer type property.
[myArray addObject:[[myObject alloc] initWithId:11 objectName:#"K"]];
[myArray addObject:[[myObject alloc] initWithId:3 objectName:#"C"]];
[myArray addObject:[[myObject alloc] initWithId:4 objectName:#"D"]];
....
...
.... and so on
then sort it in Ascending order. You can do it Descending also but then you need to change the below logic little bit. I showing with Ascending order.
NSArray *tempArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(myObject *obj1, myObject *obj2) {
if([obj1 objectId] > [obj2 objectId]) return NSOrderedDescending;
else if([obj1 objectId] < [obj2 objectId]) return NSOrderedAscending;
else return NSOrderedSame;
}];
Now sort them as per your requirement
NSMutableArray *finalArray = [NSMutableArray arrayWithArray:tempArray];
NSInteger totalObjects = [tempArray count];
NSInteger centerObjectIndex = totalObjects>>1;
__block NSInteger rightPosition = centerObjectIndex + 1;
__block NSInteger leftPosition = centerObjectIndex - 1;
__block BOOL toggle = NO;
[tempArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if(idx == 0) [finalArray replaceObjectAtIndex:centerObjectIndex withObject:obj];
else
{
if(toggle)
{
if(leftPosition >= 0)
{
[finalArray replaceObjectAtIndex:leftPosition withObject:obj];
leftPosition -= 1;
}
}
else
{
if(rightPosition < totalObjects)
{
[finalArray replaceObjectAtIndex:rightPosition withObject:obj];
rightPosition += 1;
}
}
toggle = !toggle;
}
}];
Here is the final step if your array contains an even numbers of objects
if(!(totalObjects % 2))
{
[finalArray removeObjectAtIndex:0];
[finalArray addObject:[tempArray objectAtIndex:totalObjects-1]];
}
Now you are at end. Your array named finalArray get sorted as per your requirement.

Random number generation from an NSMutable array [duplicate]

This question already has answers here:
Non repeating random numbers in Objective-C
(6 answers)
Generating non-repeating random numbers
(5 answers)
Closed 9 years ago.
I need to generate random numbers from an array i have tried this inside the for loop
rnd = arc4random_uniform(arr.count);
it generated random numbers but some numbers get repeated also tried Random() in math.h
still the same problem persists please help me out..
Thanks in advance..
if i understood
"I need to generate random numbers from an array"
correctly, you want the numbers to be taken from an array randomly, if so then
first store the numbers in an NSMutableArray
NSMutableArray *arr=//store your numbers in this array.
-(void)getRandomNumberFromArray:(NSMutableArray *)arr{
int r = arc4random() % arr.count;
int number=[arr objectAtIndex:r];
[arr removeObjectAtIndex:r];
}
Generate a random number for each element, and then check to make sure it's not the same as one of the existing ones. If it already exists, try again.
for(int i = 0; i < arr.count;i++)
{
BOOL isRandom = YES;
int rand = -1;
while(!isRandom )
(
isRandom = YES;
rand = arc4random() % 5;
for(int j = 0; j < i; j++)
{
int existingNumber = arr[j];
if(existingNumber == rand)
{
isRandom = NO;
break;
}
}
}
arr[i] = rand;
}
Another option is to first just assign them to have incrementing values, and then shuffle the mutable array. What's the Best Way to Shuffle an NSMutableArray?
If I understood your problem , then you dont need random numbers , you need to shuffle the elements in the Array ?
Then you need to use this method ,
-(void)shuffleWithArray:(NSArray*)cardsArray
{
NSMutableArray *shuffleArray =[[NSMutableArray alloc]initWithArray:cardsArray];
// NSUInteger count1=[shuffleArray count];
for (NSUInteger i= 0; i<[shuffleArray count]; i++)
{
int nElement=[shuffleArray count] -i;
int n=(arc4random()%nElement + i);
[shuffleArray exchangeObjectAtIndex:i withObjectAtIndex:n];
}
}
You can make use of the following function.
#property (nonatomic,strong) NSMutableArray * numbers;
- (NSInteger) nonRepeatedNumber
{
if(_numbers == nil)
{
_numbers = [[NSMutableArray alloc]init];
}
NSInteger number = arc4random()% arr.count;
while ([_numbers containsObject:[NSNumber numberWithInt:number]])
{
number = arc4random()% arr.count;;
}
[_numbers addObject:[NSNumber numberWithInt:number]];
return number;
}
Check the below Tutorial. it must help for you.
iOS Random Number generator
Try the following method
-(NSMutableArray*)randomNumbersfromArray:(NSArray*)array {
NSArray *numbers = array;
int count = [numbers count];
NSMutableArray *addedIndexes = [[NSMutableArray alloc]initWithCapacity:count];
NSMutableArray *addedObjects = [[NSMutableArray alloc]initWithCapacity:count];
int i = 0;
while ([addedIndexes count] != [numbers count]) {
int random = arc4random() % count ;
if (![addedIndexes containsObject:[NSString stringWithFormat:#"%i",random]]) {
[addedIndexes addObject:[NSString stringWithFormat:#"%i",random]];
[addedObjects addObject:[numbers objectAtIndex:random]];
i++;
}
}
return addedObjects;
}
#include <stdlib.h>
int r = 0;
if (arc4random_uniform != NULL)
r = arc4random_uniform (arr.count);
else
r = (arc4random() % arr.count);
int randomNumberFromArray=[arr objectAtIndex:r];
EDIT
Bingo.After some thinking i made it working
-(NSArray *)randomizeArray:(NSArray *)inputArray
{
NSMutableArray *checkArray=[[NSMutableArray alloc]initWithCapacity:3];
NSMutableArray *outputArray=[[NSMutableArray alloc]initWithCapacity:3];
while ([outputArray count]<[inputArray count])
{
int r=[self getRandomNumber:[inputArray count]];
if ([checkArray containsObject:[NSNumber numberWithInt:r]])
{
}
else
{
[checkArray addObject:[NSNumber numberWithInt:r]];
[outputArray addObject:[inputArray objectAtIndex:r]];
}
}
return outputArray;
}
-(int)getRandomNumber:(int)maxValue
{
int r = 0;
if (arc4random_uniform != NULL)
r = arc4random_uniform (maxValue);
else
r = (arc4random() % maxValue);
return r;
}
This randomizeArray: method will give you the whole array randomized

Want to generate non repeating random numbers [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generating non-repeating random numbers
Here is my code
NSUInteger count = 10;
for (NSUInteger i = 0; i < count; ++i) {
NSLog(#"%d",NeedRandomNumberWithoutRepeat);
}
this output should be like
8
7
9
2
1
4
6
3
5
0
Which is random and not repeating numbers
This should work:
NSUInteger count = 10;
NSMutableArray *array = [[NSMutableArray alloc]init];
for (NSUInteger i = 0; i < count; ++i) {
[array addObject:[NSNumber numberWithInt:i]];
}
NSMutableArray *copy = [array mutableCopy];
array = [[NSMutableArray alloc]init];
while ([copy count] > 0)
{
int index = arc4random() % [copy count];
id objectToMove = [copy objectAtIndex:index];
[array addObject:objectToMove];
[copy removeObjectAtIndex:index];
}
This answer is modified version from one of my answer in SO.
So, you may find something strange here, you can however use this as your requirement is similar.
int TOTAL_NUMBER=10;
NSMutableArray *alreadyGeneratedNumbers;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
alreadyGeneratedNumbers=[NSMutableArray new];
}
-(int)generateRandomNumber{
int low_bound = 0;
int high_bound = TOTAL_NUMBER;
int width = high_bound - low_bound;
int randomNumber = low_bound + arc4random() % width;
return randomNumber;
}
- (IBAction)button:(id)sender {
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:1];
BOOL contains=YES;
while ([shuffle count]<1) {
NSNumber *generatedNumber=[NSNumber numberWithInt:[self generateRandomNumber]];
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];
}
}
You put the available numbers in an array, and take the index calculated with arc4random() that goes from 0 to the size of the array -1.When a number comes out you take it away from the array:
NSMutableArray* availableNumbers=[NSMutableArray new];
for(NSUInteger i=0; i<10; i++)
{
[availableNumbers addObject: #(i)];
}
for(NSUInteger i=0; i<10; i++)
{
NSUInteger index= arc4random()%availableNumbers.count;
NSNumber* number= availableNumbers[index];
NSLog(#"%#",number);
[availableNumbers removeObjectAtIndex: index];
}
PS: At the last iteration is useless to sue arc4random(), since there's only one number inside.

How to Find Duplicate Values in Arrays?

I am working on SQLite and I have written a query which returns me two arrays ItemsArray and CustomersIDArray as:
ItemsArray
Element at Index 0 = Off White,
Element at Index 1 = Fan,
Element at Index 2 = Off White,
Element at Index 3 = Delux,
Element at Index 4 = Fan
CustomerIDArray
Element at Index 0 = 1,
Element at Index 1 = 2,
Element at Index 2 = 2,
Element at Index 3 = 3,
Element at Index 4 = 4
I want result like that Off White = 2 (count) , Fan = 2 (count) and Delux = 1;
and the Resultant Array,
Result Array
Element at Index 0 = Off White,
Element at Index 1 = Fan,
Element at Index 2 = Delux
Actually I want the count of repetition in first array but the value must not same for CustomerArray.
Please help me through logic or code.
-(NSMutableArray *)getCountAndRemoveMultiples:(NSMutableArray *)array{
NSMutableArray *newArray = [[NSMutableArray alloc]initWithArray:(NSArray *)array];
NSMutableArray *countArray = [NSMutableArray new];
int countInt = 1;
for (int i = 0; i < newArray.count; ++i) {
NSString *string = [newArray objectAtIndex:i];
for (int j = i+1; j < newArray.count; ++j) {
if ([string isEqualToString:[newArray objectAtIndex:j]]) {
[newArray removeObjectAtIndex:j];
countInt++;
}
}
[countArray addObject:[NSNumber numberWithInt:countInt]];
countInt = 1;
}
NSMutableArray *finalArray = [[NSMutableArray alloc] initWithObjects:newArray, countArray, nil];
NSLog(#"%#", finalArray);
return finalArray;
}
- (IBAction)getArrayInfo:(id)sender {
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:#"Off White", #"Fan", #"Off White", #"Deluxe", #"Fan", nil];
NSMutableArray *godArray = [self getCountAndRemoveMultiples:myArray];
NSLog(#"Array from this end = %#", godArray);
}
I just set up -getArrayInfo to test it out. Works fine. As you can see, the array you want to display will be at index:0, and the countArray at index:1.
Use NSCountedSet like below
NSMutableArray *ary_res = [[NSMutableArray alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"11",#"13",#"34",#"9",#"13",#"34",#"9",#"2",nil];
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:array];
for(id name in set)
{
if([set countForObject:name]==2)
[ary_res addObject:name];
}
//
NSLog(#"%#",ary_res);
try this:
NSArray *copy = [ItemsArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([ItemsArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[ItemsArray removeObjectAtIndex:index];
}
index--;
}

Separate array into many in a dynamic way? Obj-C

I currently have this method:
-(void)seperateGuides
{
DLog("GetGuideListCount: %i", [[appDelegate getGuideList] count]);
columnOneArray = [[NSMutableArray alloc] init];
columnTwoArray = [[NSMutableArray alloc] init];
columnThreeArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [[appDelegate getGuideList] count]; i = i + 3) {
[columnOneArray addObject:[[appDelegate getGuideList]objectAtIndex:i]];
}
for (int i = 1; i < [[appDelegate getGuideList] count]; i = i + 3) {
[columnTwoArray addObject:[[appDelegate getGuideList]objectAtIndex:i]];
}
for (int i = 2; i < [[appDelegate getGuideList] count]; i = i + 3) {
[columnThreeArray addObject:[[appDelegate getGuideList]objectAtIndex:i]];
}
}
And need to do this more dynamic, so I can define how many arrays I want and then get the arrays.
Different possibilities I'm considering is making it a mutli-dimensional array (although I'm not sure how to handle it in Objectvie-C), or making a method that simply loops through as many times as I define, the problem there is that I'm not quite sure how to get the different arrays.
A simple algorithm or another possible solution would be greatly appreciated.
The algorithm you're describing sounds equivalent to what we do when we deal a deck of cards into multiple hands, so I'd do it like this:
- (NSArray *)dealObjects:(NSArray *)objects intoArrays:(NSInteger)numArrays
{
NSMutableArray *arrays = [NSMutableArray arrayWithCapacity:numArrays];
for (a = 0; a < numArrays; a++) {
[arrays addObject:[NSMutableArray arrayWithCapacity:[objects count] / numArrays];
}
for (i = 0; i < [objects count]; i++) {
[[arrays objectAtIndex:i % numArrays] addObject:[objects objectAtIndex:i]];
}
return arrays;
}
You can add multiple array to another arrays as this,
-(void)seperateGuides:(int)columnCount
{
rootArray=[[NSMutableArray alloc] init];
for(int i=0;i<columnCount;i++)
{
column = [[NSMutableArray alloc] init];
for(int j=i;j<[[appDelegate getGuideList] count];j=j+3)
{
[column addObject:[[appDelegate getGuideList]objectAtIndex:j]];
[rootArray addObject:column];
[column release];
}
}
}
Quite simple really. Just add new NSArray objects to a root array as you iterate through your dataset.
- (void)seperateGuides {
DLog("GetGuideListCount: %i", [[AppDelegate getGuideList] count]);
NSArray *root = [[NSArray alloc] init];
int dimensions = anyIntGreaterThanZero;
for (int i = 0; i < dimensions; i += dimensions) {
NSArray *branch = [[NSArray alloc] init];
int k = 0;
for (k += i; k < [[AppDelegate getGuideList] count]; k += dimensions) {
[branch addObject:[[AppDelegate getGuideList] objectAtIndex:k]];
}
[root arrayByAddingObject:branch];
}
}
-(void)seperateGuides
{
NSMutableArray *parentArray = [[NSMutableArray alloc]init];
int count = [[appDelegate getGuideList] count];
int TOTAL_COLUMNS = 3;//Define number of columns here
for (int i = 0; i <count; i++)
{
int columnNo = i % TOTAL_COLUMNS;
if(parentArray.count > columnNo)
{
NSMutableArray *innerArray = [parentArray objectAtIndex:columnNo];
[innerArray addObject:[[appDelegate getGuideList]objectAtIndex:i]];
}
else
{
NSMutableArray *innerArray = [NSMutableArray arrayWithObject:[[appDelegate getGuideList]objectAtIndex:i]];
[parentArray insertObject:innerArray atIndex:columnNo];
}
}
}
Hope this helps...
Here parentArray will have NSMutableArray as its members. Each array represents the objects in a column.