Subarray with range - ios

Im trying to split an array of objects into smaller arrays containing 32 objects. With the remaining about being put into the array at the end.
This is the code I'm using
int a = sharedManager.inventoryArray2.count;
float b = a / 33;
int c = ceilf(b);
NSMutableArray *arrayOfArrays = [NSMutableArray array];
int from = 0;
int to = 31;
for (int e = 0; e <= c; e++) {
if (sharedManager.inventoryArray2.count < to) {
NSArray *smallArray = [sharedManager.inventoryArray2 subarrayWithRange:NSMakeRange(from, sharedManager.inventoryArray2.count)];
[arrayOfArrays addObject:smallArray];
}
else {
NSArray *smallArray = [sharedManager.inventoryArray2 subarrayWithRange:NSMakeRange(from, to)];
from = from + (31+1);
to = from + 31;
[arrayOfArrays addObject:smallArray];
}
}
I'm getting the following error.
'NSRangeException', reason: '*** -[NSArray subarrayWithRange:]: range {32, 63} extends beyond bounds [0 .. 83]'
I don't get it, the range of 32-63 is in the bounds of 0-83.
Any advice?
Thanks.
Paul.

A NSRange indicates the starting point and the number of entries to select from that point on.. So it actually means "Starting point 32, select 63 items from that point on", which will exceed your 83 entries (32 + 63)

2nd parameter of NSMakeRange is length range to create, not the last index in it. So you need to change your code accordingly (simplifying it a bit):
NSUInteger count = sharedManager.inventoryArray2.count;
NSMutableArray *arrayOfArrays = [NSMutableArray array];
NSUInteger from = 0;
while (from < count) {
NSRange range = NSMakeRange(from, MIN(32, count-from));
NSArray *smallArray = [sharedManager.inventoryArray2 subarrayWithRange:range];
[arrayOfArrays addObject:smallArray];
from += 32;
}

No Actually the range doesn't work like this
NSRange {32, 63} => means from the index 32 take 63 elements
Here is documentation :
NSRange
A structure used to describe a portion of a series—such as characters in a string or objects in an NSArray object.
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;
location
The start index (0 is the first, as in C arrays). For type compatibility with the rest of the system, LONG_MAX is the maximum value you should use for location.
length
The number of items in the range (can be 0). For type compatibility with the rest of the system, LONG_MAX is the maximum value you should use for length.

Related

Calculating the standard deviation of a string

I want the user to provide a string. The string will be divided into individual characters. Each character will be put into a number (a = 1, b = 2, c = 3, etc) and then put into an array with the values, and then the standard deviation will be calculated.
I already have the code to convert the letters:
for (int i = 0 ; i < str.length ; ++i ) {
// 'A' unicode value is 65, so by substracting 64 you'll get 1 for A, 2 for B, 3 for C...
total += [str characterAtIndex:i] - 64;
But that code only uses the string (maybe there is a way to just put the values directly into a string?)
And the code for standard deviation:
NSArray *numbers = #[#1, #2];
NSExpression *expression = [NSExpression expressionForFunction:#"stddev:" arguments:#[[NSExpression expressionForConstantValue:numbers]]];
NSNumber *value = [expression expressionValueWithObject:nil context:nil];
NSLog(#"%#,", value);
If your question is "how would I convert the string of letters into an array of numbers?", try something like this:
NSMutableArray * array = [NSMutableArray arrayWithCapacity:str.length];
for (int i = 0; i < str.length; ++i) {
[array addObject:[NSNumber numberWithInt:[str characterAtIndex:i]-64]];
}

How to create random numbers for multiple images to show randomly in Grid without repetition in iOS?

I create GridView in SpriteKit.my requirement is to shuffle images randomly in Grid View.
Here is my code to show images randomly without repetition.but this code is working for only two images.for multiple images this code is not working.
int RandomRowMainImage = arc4random_uniform(3);
int RandomColumnMainImage = arc4random_uniform(3);
//
int RandomRowOtherImage = arc4random_uniform(3);
int RandomColumnOtherImage = arc4random_uniform(3);
NSLog(#"RandomRowMain:%d \n Random Column :%d \n RandomRow1:%d \n randomColumn1 :%d",RandomRowMainImage,RandomColumnMainImage,RandomRowOtherImage,RandomColumnOtherImage);
//
BOOL checkStatus = [self checkRandomNumberColumRowLogic:RandomRowMainImage withMainRow:RandomColumnMainImage withOtherColumn:RandomColumnOtherImage withOtherRow:RandomRowOtherImage];
if (checkStatus) {
imgIcons.position = [self GridPosition:MainRowCount Column:MainColumnCount];
imgOtherImage.position = [self GridPosition:otherRowCount Column:otherColumnCount];
}
than Code for Position of Images
//Grid Position
-(CGPoint)GridPosition:(int)Row Column:(int)Column
{
CGFloat offset = SizeOfGrid / 2.0 + 0.5;
CGFloat x = Column * SizeOfGrid - (SizeOfGrid*TotalCol)/2.0 + offset;
CGFloat y = (TotalRows-Row-1) * SizeOfGrid -(SizeOfGrid*TotalRows)/2.0 + offset;
return CGPointMake(x, y);}
//Code to check prevent duplication of repeat random number for Two Images.
- (BOOL)checkRandomNumberColumRowLogic:(int)MainColumn withMainRow:(int)mainRow withOtherColumn:(int)otherColumn withOtherRow:(int)otherRow {
BOOL CompareRow = false;
BOOL CompareColumn = false;
if (mainRow == otherRow) {
int otherRow = 0;
for (int i = 0; i < TotalCol; i++ ) {
otherRow = [self checkRandomNumberCompare:otherRow];
if (MainColumn == otherRow) {
CompareRow = true;
break;
}
}
MainColumnCount = mainRow;
otherColumnCount = otherRow;
}
else {
CompareRow = true;
MainRowCount = mainRow;
otherRowCount = otherRow;
}
if (MainColumn == otherColumn) {
int otherCol = 0;
for (int i = 0; i < TotalCol; i++ ) {
otherCol = [self checkRandomNumberCompare:otherColumn];
if (MainColumn == otherCol) {
CompareColumn = true;
break;
}
}
MainColumnCount = MainColumn;
otherColumnCount = otherCol;
}
else {
CompareColumn = true;
MainColumnCount = MainColumn;
otherColumnCount = otherColumn;
}
if(CompareRow == CompareColumn) {
return true;
} else {
return false;
}
}
-(int)checkRandomNumberCompare:(int)compareRow {
int compareDiff = arc4random_uniform(TotalRows);
return compareDiff;
}
can you please help to display multiple images without repeat? like one time one image in Node
Sorry, but the logic of your checkRandomNumberColumRowLogic: method baffles me. Given two coordinates (x1, y1) and (x2, y2) then they represent the same point if and only if x1 == x2 and y1 == y2, and if this is not fall then they represent different points.
Here is the outline of a possible algorithm to solve your problem. First consider that given a rectangular grid of cells where the rows and columns are numbered starting from 0 then each cell can be assigned a unique number by multiplying its row index by the number of columns and adding in its column index. A diagram is worth a thousand words, given a 3 x 3 grid you get the numbering:
0 1 2
3 4 5
6 7 8
Note that given a cell number the row & column it represents can be calculated using integer division and remainder.
Doing the above reduces your problem to producing the numbers from 0 to rowCount x colCount - 1 in some random order.
There are a number of ways in which you can do this, here is one:
Set upperLimit to rowCount x colCount - 1
Generate a random number r between 0 and upperLimit
Check if cell r is occupied, if it is add 1 to r and repeat this step
Place next image into cell r
Subtract 1 from upperLimit and goto step 2 if the result is greater than 0 (of course "goto" here translates to a "while" in code)
They key to avoiding duplicates is step 3, and the algorithm guarantees that step 3 will always find an unoccupied cell – proving that is left as an exercise.
HTH
I'd agree with the answer above that your logic is overly complicated. If you give an index to each image as suggested, e.g. for a 3x4 grid:
0 1 2
3 4 5
6 7 8
9 10 11
You could then randomise the grid and exchange those images. The following code would achieve this:
-(void)createRandomGridArrays
{
NSInteger columnLength = 3;
NSInteger rowLength = 4;
// Create an array of NSNumbers up to the max then randomise
NSMutableArray *indexes = [NSMutableArray new];
for (NSInteger i=0; i<columnLength*rowLength; i++) {
[indexes addObject:#(i)];
}
NSArray *randomIndexes = [self shuffleArray:indexes];
NSLog(#"%# -> %#", indexes, randomIndexes);
// (0,1,2,3,4,5,6,7,8,9,10,11) -> (1,0,6,10,4,2,7,11,9,5,8,3)
// Convert indexes back to row/columns
for (NSNumber *randomIndex in randomIndexes) {
NSInteger index = [randomIndex integerValue];
NSInteger row = index % rowLength;
NSInteger column = index % columnLength;
NSLog(#"%ld row:%ld, column:%ld", index, row, column);
}
}
-(NSArray*)shuffleArray:(NSArray*)array
{
NSMutableArray *shuffledArray = [array mutableCopy];
for (NSInteger i=shuffledArray.count-1; i>0; i--) {
[shuffledArray exchangeObjectAtIndex:i withObjectAtIndex:arc4random_uniform(i+1)];
}
return shuffledArray;
}
If you had an NSMutableArray of images you would then just exchange the image at index with the image at [randomIndexes[index] integerValue].

How do I loop through NSString N number of times?

how do I loop the string 9 times ? (z x c v b n z x c)
NSString *fl = #"zxcvbn";
Here's a fast and dirty snippet:
NSString *string = #"abcdef";
NSString *letter = nil;
int n = 9;
for (int index = 0; index < n; index++) {
// start over if it's more than the length
int currentIndex = index % string.length;
letter = [string substringWithRange:NSMakeRange(currentIndex, 1)];
NSLog(#"letter: %#", letter);
}
If you want a low-level example with detailed explanation check this out.
In addition to using substringWithRange (which returns a NSString), you can also use characterAtIndex to get the character value:
NSInteger n = 9;
for (NSInteger index = 0; index < n; index++) {
unichar character = [fl characterAtIndex:index % fl.length];
// do something with `character`, e.g.
//
// if (character == 'z') { ... }
}

conversion of decimal to binary output

I am facing problem with the objective c code to convert decimal to binary. When I enter small values it shows me the output.
For e.g. 12 -> 1010
But when I enters large numbers, it shows me the output as "10..." (includes dots in the output)
Please help me.
My program is as follows:
NSUInteger x = [newDec integerValue];
//int y[30];
int i=0;
int m =1;
while (x != 0) {
int mod = x % 2;
x /= 2;
i = i + mod * m;
m = m * 10;
string = [NSString stringWithFormat:#"%d", i];
}
There are two problems with your code.
1) Your label size is perhaps not able to accommodate your string. So check the length of it.
2) Your code will not support the conversion if value of x is large. The reason is that int has limited capacity. Check this question regarding memory size of in-built variable. So, consider making your string mutable and add 0s or 1s in it. I am attaching my snippet of code.
NSMutableString *string = [[NSMutableString alloc] init];
while (x != 0) {
int mod = x % 2;
x /= 2;
[string insertString:[NSString stringWithFormat:#"%d", mod] atIndex:0];
}
NSLog(#"String = %#", string);

Take average of segments of NSArray

I have an NSArray of 100 numbers. I would like to create an NSArray of 5 numbers. The first number in the second array is the average of the first 20 numbers in the first array. The second number is the average of the second set of 20 numbers in the first array. And so on.
I'm curious to hear people's ideas for an efficient algorithm.
One idea I had was to do a for-loop on each set of 20 numbers, creating a temp NSArray of 20 numbers. Then perform a KVO average operation and add to the final NSArray.
Note: I always award THE answer to someone, and I'm not shy to up vote your answers. I encourage many answers. Thanks!
Just add the values in each 20 number section, divide by 20 and put in the appropriate output array location. It is one pass through the array, Big O(n), what more could you ask for? The time to compute this is minuscule.
The following is simple and efficient:
NSArray *numbers = ... // array of 100 numbers
NSMutableArray *averages = [NSMutableArray array];
for (int = 0; i < 5; i++) {
float total = 0.0;
int base = i * 20;
for (int j = 0; j < 20; j++) {
float num = [numbers[base + j] floatValue];
total += num;
}
float avg = total / 20.0f;
[averages addObject:#(avg)];
}
NSLog(#"Averages = %#", averages);
you could try something like this...
NSArray *_array = // with the 100 numbers... (I used NSNumber object for each number)
NSMutableArray *_averages = [NSMutableArray array];
for (int i = 0; i < 5; i++) [_averages addObject:#([[[_array subarrayWithRange:NSMakeRange(i * 20, 20)] valueForKeyPath:#"#avg.floatValue"] floatValue])];
the _averages will contain 5 values with the averages of the five different sections of the 100 numbers.
UPDATED:
this part is just for eyes with extra curiosity.
if you tries to avoid the NSObjects and the double for loops, you could achieve a really fast algorithm, and of course when you go lower levels, you can improve the current speed as well, the question is: does it really need?
NSInteger _segments = 1000; // it means 20.000 numbers;
Float64 _numbers[(_segments * 20)]; // fill this array as you'd like.
Float64 _averages[_segments];
for (int i = 0; i < _segments; i++) {
NSInteger _offset = (_segments<<4)+4;
_averages[i] = (_numbers[_offset] + _numbers[_offset+1] + _numbers[_offset+2] + _numbers[_offset+3] + _numbers[_offset+4] + _numbers[_offset+5] + _numbers[_offset+6] + _numbers[_offset+7] + _numbers[_offset+8] + _numbers[_offset+9] + _numbers[_offset+10] + _numbers[_offset+11] + _numbers[_offset+12] + _numbers[_offset+13] + _numbers[_offset+14] + _numbers[_offset+15] + _numbers[_offset+16] + _numbers[_offset+17] + _numbers[_offset+18] + _numbers[_offset+19]) / 20.f;
}
it is 10 times faster than the solution with double for loops and NSObject classes.
(un)fortunately, it is not even the ugliest solution, but there is no question it is fast as hell, I won't recommend it except the speed really matter because that kind of solutions can provide really good efficiency.

Resources