Objective C - comparing values in an array to an arbritary - objective-c

How would you sort through an array, which also contains 0 values i.e.
-54
0
-12
0
-10
and comparing it to a constant (say -5), which would return the index of the corresponding closest value (smallest difference) ? (i.e. closest value = -10, so returned value = 4)
The challenge here being 0 values should always be overlooked, and the array cannot be sorted before hand
Heres a Similar problem, answers for which doesn't quite work in my case
How do I find the closest array element to an arbitrary (non-member) number?

That is relatively straightforward:
NSArray *data = #[#-54, #0, #-12, #0, #-10];
NSUInteger best = 0;
int target = -5;
for (NSUInteger i = 1 ; i < data.count ; i++) {
int a = [[data objectAtIndex:best] intValue];
int b = [[data objectAtIndex:i] intValue];
if (b && abs(a-target) > abs(b-target)) { // Ignore zeros, check diff
best = i;
}
}
// At this point, "best" contains the index of the best match
NSLog(#"%lu",best); // Prints 4

Related

Get sequence of random numbers' pairs (Objective-c)

Good morning, i'm trying to generate a sequence of N pairs of numbers, for example 1-0, 2-4, 4-3. These numbers must range between 0 and 8 and the pair must be different for all the numbers.
I don't want that: 1-3 1-3
I found that if a and b are the numbers, (a+b)+(a-b) has to be different for all couples of numbers.
So I manage to do that, but the loop never ends.
Would you please correct my code or write me another one? I need it as soon as possible.
NSNumber*number1;
int risultato;
int riga;
int colonna;
NSMutableArray*array=[NSMutableArray array];
NSMutableArray*righe=[NSMutableArray array];
NSMutableArray*colonne=[NSMutableArray array];
for(int i=0; i<27; i++)
{
riga=arc4random()%9;
colonna=arc4random()%9;
risultato=(riga+colonna)+(riga-colonna);
number1=[NSNumber numberWithInt:risultato];
while([array containsObject:number1])
{
riga=arc4random()%9;
colonna=arc4random()%9;
risultato=(riga+colonna)+(riga-colonna);
number1=[NSNumber numberWithInt:risultato];
}
NSNumber*row=[NSNumber numberWithBool:riga];
NSNumber*column=[NSNumber numberWithInt:colonna];
[righe addObject:row];
[colonne addObject:column];
[array addObject:number1];
}
for(int i=0; i<27; i++)
{
NSNumber*one=[righe objectAtIndex:i];
NSNumber*two=[colonne objectAtIndex:i];
NSLog(#"VALUE1 %ld VALUE2 %ld", [one integerValue], (long)[two integerValue]);
}
edit:
I have two arrays (righe, colonne) and I want them to have 27 elements [0-8].
I want to obtain a sequence like it:
righe: 1 2 4 6 7 8 2 3 4 8 8 7
colonne: 1 3 4 4 2 1 5 2 7 6 5 6
I don't want to have that:
righe: 1 2 4 6 2
colonne: 1 3 5 2 3
Where you see that 2-3 is repeated once. Then I'd like to store these values in a primitive 2d array (array[2][27])
I found that if a and b are the numbers, (a+b)+(a-b) has to be different for all couples of numbers.
This is just 2 * a and is not a valid test.
What you are looking for are pairs of digits between 0 - 8, giving a total of 81 possible combinations.
Consider: Numbers written in base 9 (as opposed to the common bases of 2, 10 or 16) use the digits 0 - 8, and if you express the decimal numbers 0 -> 80 in base 9 you will get 0 -> 88 going through all the combinations of 0 - 8 for each digit.
Given that you can can restate your problem as requiring to generate 27 numbers in the range 0 - 80 decimal, no duplicates, and expressing the resultant numbers in base 9. You can extract the "digits" of your number using integer division (/ 9) and modulus (% 9)
To perform the duplicate test you can simply use an array of 81 boolean values: false - number not used, true - number used. For collisions you can just seek through the array (wrapping around) till you find an unused number.
Then I'd like to store these values in a primitive 2d array (array[2][27])
If that is the case just store the numbers directly into such an array, using NSMutableArray is pointless.
So after that long explanation, the really short code:
int pairs[2][27];
bool used[81]; // for the collision testing
// set used to all false
memset(used, false, sizeof(used));
for(int ix = 0; ix < 27; ix++)
{
// get a random number
int candidate = arc4random_uniform(81);
// make sure we haven't used this one yet
while(used[candidate]) candidate = (candidate + 1) % 81;
// record
pairs[0][ix] = candidate / 9;
pairs[1][ix] = candidate % 9;
// mark as used
used[candidate] = true;
}
HTH
Your assumption about (a+b)+(a-b) is incorrect: this formula effectively equals 2*a, which is obviously not what you want. I suggest storing the numbers in a CGPoint struct and checking in a do...while loop if you already have the newly generated tuple in your array:
// this array will contain objects of type NSValue,
// since you can not store CGPoint structs in NSMutableArray directly
NSMutableArray* array = [NSMutableArray array];
for(int i=0; i<27; i++) {
// declare a new CGPoint struct
CGPoint newPoint;
do {
// generate values for the CGPoint x and y fields
newPoint = CGPointMake(arc4random_uniform(9), arc4random_uniform(9));
} while([array indexOfObjectPassingTest:^BOOL(NSValue* _Nonnull pointValue, NSUInteger idx, BOOL * _Nonnull stop) {
// here we retrieve CGPoint structs from the array one by one
CGPoint point = [pointValue CGPointValue];
// and check if one of them equals to our new point
return CGPointEqualToPoint(point, newPoint);
}] != NSNotFound);
// previous while loop would regenerate CGPoint structs until
// we have no match in the array, so now we are sure that
// newPoint has unique values, and we can store it in the array
[array addObject:[NSValue valueWithCGPoint:newPoint]];
}
for(int i=0; i<27; i++)
{
NSValue* value = array[i];
// array contains NSValue objects, so we must convert them
// back to CGPoint structs
CGPoint point = [value CGPointValue];
NSInteger one = point.x;
NSInteger two = point.y;
NSLog(#"VALUE1 %ld VALUE2 %ld", one, two);
}

Find the largest number from NSArray that is smaller than the given number

Suppose I have a sorted array of integers int[], and I want to search the closest smaller value to some input number.
for example if the array contains 1, 23, 57, 59, 120 and the input is 109, the output should be 59.
I have tried this but it is not working out as needed.
NSTimeInterval currentTime = self.player.currentTime;
NSInteger playerTime=currentTime;
NSUInteger index = [_timesArray indexOfObject:#(playerTime)
inSortedRange:NSMakeRange(0, _timesArray.count-1)
options:NSBinarySearchingFirstEqual | NSBinarySearchingInsertionIndex
usingComparator:^(id a, id b) {
return [a compare:b];
}];
Your code does work as expected with the example data you gave:
NSArray *_timesArray = #[#1, #23, #57, #59, #120];
NSTimeInterval currentTime = 109;
NSInteger playerTime=currentTime;
NSUInteger index = [_timesArray indexOfObject:#(playerTime)
inSortedRange:NSMakeRange(0, _timesArray.count-1)
options:NSBinarySearchingFirstEqual | NSBinarySearchingInsertionIndex
usingComparator:^(id a, id b) {
return [a compare:b];
}];
NSLog(#"Index: %lu", (unsigned long)index);
Output:
Index: 4
Check your inputs. Likely they are not what you think they are.
As I said before: "you have sorted array and what you need is to step downward from biggest number to smallest... algorithm is simple here!"
NSNumber* givenNumber = #(105);
for (NSNumber* item in [#[#(1), #(23), #(57), #(59), #(120)] reverseObjectEnumerator]){
// go downward
if (item.integerValue < givenNumber.integerValue)
{
NSLog(#"%# < %#",item,givenNumber);
// save this number somewhere
break;
}
}
It can be solved by binary_search_like algorithm which runs in O(lg n) , but I don't know objective-c so I'll give code in c++.
I assume the given element is not in the array.
int binary_search_like(int s[], int key, int low, int high)
{
int middle;
if (low > high) return (s[high]);
middle = (low + high) / 2;
if (s[middle] > key)
return(binary_search_like(s, key, low, middle - 1));
else
return(binary_search_like(s, key, middle + 1, high));
}
int Search(int s[], int key, int size){
if (key > s[size - 1]) return s[size - 1];
// Check if key < smallest element , give error !
return binary_search_like(s, key, 0, size);
}

Sequence combinations of varying length using two 'alphabets'

I am trying to generate all possible combinations of a sequence of length k given a certain alphabet (this is to generate query sequences for a bioinformatics project).
The sequences are of the form:
A first character and last character that can be any of A C G U (call these Y) and k - 2 characters in between that can be any of A C G U or ? (call these X).
e.g. if k = 3 then the pattern is of the form YXY and if k = 5 then YXXXY.
Generating all possible sequences if k is known is easy, as you can just use k nested for loops. But if k is not known in advance, then this implementation does not fit.
The total number of possible sequences can be expressed by 4^2 * 5^(k-2). With k = 3 this only gives 80 combinations, but scale that up to k = 9 and you have 1,250,000!
Any tips, ideas or suggestions would be much appreciated.
I need to use every sequence generated, so they need to be either stored in an array, or passed at creation/generation to another function, it doesn't really matter which, although I would prefer not to have to store all of them.
Many Thanks.
N.B. I am writing in objective-c, but any c-style code, or psuedocode or just plain english descriptions of an algorithm would be helpful.
UPDATE:
Here is the objc code I wrote base on the brilliant answer by Analog File. Currently it just outputs one sequence per line to stdout, but I will modify it to produce an array of strings.
Many thanks to everyone who contributed.
NSArray *yAlphabet = [NSArray arrayWithObjects:#"A", #"C", #"G", #"U", nil];
NSArray *xAlphabet = [NSArray arrayWithObjects:#"A", #"C", #"G", #"U", #"?", nil];
int i, v;
int count = 0;
int numberOfCases = 16 * pow(5 , (k - 2));
for (int n = 0; n < (numberOfCases); n++) {
i = n;
v = i % 4;
i = i / 4;
count++;
printf("\n%s", [[yAlphabet objectAtIndex:v] cStringUsingEncoding:NSUTF8StringEncoding]);
for (int m = 1; m < (k - 1); m++) {
v = i % 5;
i = i / 5;
printf("%s", [[xAlphabet objectAtIndex:v] cStringUsingEncoding:NSUTF8StringEncoding]);
}
printf("%s", [[yAlphabet objectAtIndex:i] cStringUsingEncoding:NSUTF8StringEncoding]);
}
printf("\n");
NSLog(#"No. Sequences: %i", count);
UPDATE 2:
And here's the code, outputting the generated sequences to an array of strings. Note that k is the length of the desired sequences and is given as a parameter elsewhere. I have tested this up to k=9 (1,250,000 sequences). Also note that my code uses ARC, hence there is no memory deallocation shown.
NSArray *yAlphabet = [NSArray arrayWithObjects:#"A", #"C", #"G", #"U", nil];
NSArray *xAlphabet = [NSArray arrayWithObjects:#"A", #"C", #"G", #"U", #"?", nil];
NSMutableArray *sequences = [[NSMutableArray alloc] init];
int i, v;
int count = 0;
int numberOfCases = 16 * pow(5 , (k - 2));
for (int n = 0; n < (numberOfCases); n++) {
i = n;
v = i % 4;
i = i / 4;
count++;
NSMutableString *seq = [[NSMutableString alloc] initWithString:[yAlphabet objectAtIndex:v]];
for (int m = 1; m < (k - 1); m++) {
v = i % 5;
i = i / 5;
[seq appendString:[xAlphabet objectAtIndex:v]];
}
[seq appendString:[yAlphabet objectAtIndex:i]];
[sequences addObject:seq];
}
NSLog(#"No. Sequences looped: %i", count);
//print the array to confirm
int count1 = 0;
for (NSMutableString *str in sequences) {
fprintf(stderr, "%s\n", [str cStringUsingEncoding:NSUTF8StringEncoding]);
count1++;
}
NSLog(#"No. Sequences printed: %i", count1);
NSLog(#"Counts match? : %#", (count == count1 ? #"YES" : #"NO"));
You know how many cases you are going to get.
This is pseudocode (k is the sequence length)
for n = 0 to num_of_cases - 1
i = n
v = i % length_of_alphabeth_Y
i = i / length_of_alphabeth_Y
output vth char in alphabeth Y
for m = 1 to k-1
v = i % length_of_alphabeth_X
i = i / length_of_alphabeth_X
output vth char in alphabeth X
output ith char in alphabeth Y
output end of sequence
Each iteration of the outer loop generates a case.I wrote output but it's easy to instead "store" the data in a dynamically allocated structure (n indexes in the roes, first case is column 0 then m indexes in the columns and last case is column k-1. if you do that "end of sequence" need not be output as it's subsumed by the increment of n).
Note how we are effectively "counting" in base length_of_alphabeth, except we use different bases depending on the digit. Modulo gives you the least significant digit, and integer division gets rid of it and shifts next digit to least significant position.
If you can imagine n as being just a value, in no specific base, the logic is rather simple. You could probably write this yourself from scratch, once you understand it.
It sounds like k will be passed in as a parameter, so something like this (in Python-ish pseudo-code) should work
Y_alphabet = ['A','C','G','U']
X_alphabet = ['A','C','G','U','?']
outputs = []
for i in range(k):
if i == 0 or i == k-1:
current_alphabet = Y_alphabet
else:
current_alphabet = X_alphabet
last_outputs = outputs
outputs = []
for next_character in current_alphabet:
# This just replaces outputs with a new list that consists
# of all the possible sequences of length i appended with
# the current character
outputs += [seq + next_character for seq in last_outputs]
The basic form for doing this looks like this (Java-ish psuedocode)
char[] output = new char[k];
pubilc void go(cur_k){
if(cur_k>k) // do something - copy the array and store it, etc.
for( char letter : alphabet ){
output[cur_k]=char_letter;
go(cur_k+1);
}
}

Dividing an array into separate arrays of four elements plus the reminder

I'm trying to divide an array into individual arrays of four elements, where the last array will contain the reminder. For example, if that main array's length property will be ten, three subarrays will be created - two consisting of four elements, and one of two elements.
The code I have right now looks like the following:
NSMutableArray *mainMutableArray = [NSMutableArray arrayWithObjects:#"First", #"Second", #"Third", #"Fourth", #"Fifth", #"Sixth", #"Seventh", #"Eighth", nil];
NSMutableArray *mutableArrayOfSubarrays = [NSMutableArray array];
int length = mainMutableArray.count / 4;
int location = 0;
for (int i = 0; i < length; i++)
{
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
This of course works only when the reminder is equal to 0.
Any help would be greatly appreciated.
Ok, here we go:
int length = mainMutableArray.count;
for (int location = 0; location < length; location+=4)
{
unsigned int Size=length-location;
if (Size>4) Size=4;
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, Size)]];
}
If you use a while loop, you can make the condition describe what you are actually trying to do:
NSUInteger length = [mainMutableArray count];
NSUInteger location = 0;
// Until the location is less than four away from the end
while( location <= (length - 4) ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
// Pick up the remainder, if any
if( location != length ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, length-location)]];
}
Loop from length*4 to mainMutableArray.count to get the remainder of the array.

Array giving EXC_BAD_ACCESS in for loop

I have a C array defined in my method as:
int c = 4;
int r = 5;
keysArray[c][r];
I have this for loop, which works, populating the keysArray as expected.
for (int row = 0; row < r; row++) {
for (int column = 0; column < c; column++){
keysArray[column][row] = [anotherArray objectAtIndex:0];
NSLog(#"array1 %#",keysArray[column][row]);
[anotherArray removeObjectAtIndex:0];
}
}
Then in a for loop underneath, featuring exactly the same looping counter structure, when i try to NSLog the array, it gives an EXC_BAD_ACCESS.
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#",keysArray[column][row]); //EXC_BAD_ACCESS here
}
}
What would cause this to happen, given that the keysArray is defined in the method body, outside of both sets of loops?
Are the contents of anotherArray retained by some other object? If not, they do not exist anymore in the second loop. WTH are you using a C array to store Objective-C objects anyway?
int c = 4;
int r = 5;
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:c];
for (int column = 0; column < c; column++) {
[keysArray addObject:[NSMutableArray arrayWithCapacity:r]];
for (int row = 0; row < r; row++) {
[[keysArray objectAtIndex:column] addObject:[anotherArray objectAtIndex:0]];
[anotherArray removeObjectAtIndex:0];
}
}
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#", [[keysArray objectAtIndex:column] objectAtIndex:row]);
}
}
You need to retain the objects held in your C array. Unlikes an NS*Array, a C array does not retain on adding to the array.
However, for a no-holes 2D array like that, I'd just use a single NSMutableArray. Any N-dimensional array can be represented as a line-- as a one dimensional array-- with simple math.
Namely, to determine the index of an object at (X,Y), use (Y * width) + X).
The only caveat is that NS*Array does not support "holes". You will need to fill the array row by row. That is, for a 3x4 (3 wide, 4 tall) array, you would fill it in the order 0,0, 1,0, 2,0, 0,1, 1,1, etc...
Obviously, insert and remove operations will mess up your 2D representation (but they would in an NSMutableArray of NSMutableArrays, too).
Alternatively, use NSPointerArray as it can have holes.
Could this be the problem :
[anotherArray removeObjectAtIndex:0];
try
keysArray[column][row] = [[anotherArray objectAtIndex:0] retain];
although if I were you I would use NSMutableArray of NSMutableArray instead