Question:
Find the value of K in myInterViewArray without any messages/calls
I was given this hint:
The numbers in the array will never exceed 1-9.
NSArray *myInterViewArray = #[#2,#1,#3,#9,#9,#8,#7];
Example:
If you send 3, the array will return the 3 biggest values in myInterViewArray * 3. So in the example below, K = 9 + 9 + 8.
--
I was asked this question a while back in an interview and was completely stumped. The first solution that I could think of looked something like this:
Interview Test Array:
[self findingK:myInterViewArray abc:3];
-(int)findingK:(NSArray *)myArray abc:(int)k{ // With Reverse Object Enumerator
myArray = [[[myArray sortedArrayUsingSelector:#selector(compare:)] reverseObjectEnumerator] allObjects];
int tempA = 0;
for (int i = 0; i < k; i++) {
tempA += [[myArray objectAtIndex:i] intValue];
}
k = tempA;
return k;
}
But apparently that was a big no-no. They wanted me to find the value of K without using any messages. That means that I was unable to use sortedArrayUsingSelector and even reverseObjectEnumerator.
Now to the point!
I've been thinking about this for quite a while and I still can't think of an approach without messages. Does anyone have any ideas?
There is only one way to do that and that is bridging the array to CF type and then use plain C, e.g.:
NSArray *array = #[#1, #2, #3];
CFArrayRef cfArray = (__bridge CFArrayRef)(array);
NSLog(#"%#", CFArrayGetValueAtIndex(cfArray, 0));
However, if the value is a NSNumber, you will still need messages to access its numeric value.
Most likely the authors of the question didn't have a very good knowledge of the concept of messages. Maybe they thought that subscripting and property access were not messages or something else.
Using objects in Obj-C without messages is impossible. Every property access, every method call, every method initialization is done using messages.
Rereading the question, they probably wanted you to implement the algorithm without using library functions, e.g. sort (e.g. you could implement a K-heap and use that heap to find the K highest numbers in a for iteration).
I assume what is meant is that you can't mutate the original array. Otherwise, that restriction doesn't make sense.
Here's something that might work:
NSMutableArray *a = [NSMutableArray array];
for (NSNumber *num in array) {
BOOL shouldAdd = NO;
for (int i = a.count - 1; i >= k; i--) {
if ([a[i] intValue] < [num intValue]) {
shouldAdd = YES;
break;
}
}
if (shouldAdd) {
[a addObject:num];
}
}
int result = a[a.count - k];
for (int i = k; k < a.count; k++) {
result += [a[i] intValue];
}
return result;
Related
I have two arrays: array1 and array2. Each object of arrays is an array too (2D arrays). In this way I multiple them. So how I have big arrays I use dispatch_apply. Every time i receive different results include a right result. Maybe somebody knows how to fix it?
dispatch_apply([array2 count], queue, ^(size_t j)
{
k = 0;
for (int l = 0; l < [[array1 objectAtIndex:0] count]; l++) {
k += [[[array1 objectAtIndex:i] objectAtIndex:l] intValue] *
[[[array2 objectAtIndex:j] objectAtIndex:l] intValue];
}
kNSNumber = [NSNumber numberWithInt:k];
[multipliedArrayInto replaceObjectAtIndex:j withObject:kNSNumber];
});
[resulArray insertObject:multipliedArrayInto atIndex:i];
}
There's two things, I can suggest, and I bet one of them (or both) is the overarching solution to your problem.
First, I would declare k local to the block, so there would be no question that you are overwriting it or not. You likely have the same problem with kNSNumber inside the block. If you are just using that NSNumber instance to slam into the multipliedArrayInto accumulator, you may as well remove kNSNumber, and use #(k) in it's place (if only to be more readable). Similarly, make sure multipliedArrayInto is declared just before the dispatch_apply, in what looks like an outer for loop (where ever i is coming from). And finally, make sure resulArray is instantiated, or otherwise readied just before that outer for loop.
Second, is queue a concurrent or serial queue? If you are using dispatch_apply like a parallel-executing for/enumeration -- which is likely, I think, so you are taking about handling "big arrays" efficiently -- then you are practically guaranteeing that k is being overwritten. If you change it to serial, it may work as designed. If you want it to be parallel, you will need to move the declaration of your k accumulator inside the block, and make sure the declaration of other variables makes sense, too.
Update to reflect question updates:
#antonytonies ideally, your followup answer on this thread should be moved into the question itself, so that people can follow this thread easier.
So, it looks like what I described is exactly your problem.
The global queues are all concurrent queues, which means that (hypothetically) all the dispatch blocks are executing at once, and the contents of k and other variables are getting blown away depending on how the order of the blocks executes.
I've taken your update (in the "answer" you added), and modified it to probably work:
// I renamed your method, because nameless parameters pain me. This is cosmetic, and doesn't
// matter for the problem at hand.
- (NSMutableArray *)multiplicationArrays:(NSMutableArray *)array vector:(NSMutableArray *)vector
{
// IMHO, you want to set resultArray to nil here. Another option is to set it to nil in the
// else case, below. Properties in Objective-C are initalized to nil,0,false,etc; you can
// rely on ARC to initialize pointer to objc objects on the stack, too. However, someone
// reading this code may or may not know that. IMHO, using the explicitly assignement makes it
// clear that you're going to be returning `nil` or an instance of `NSMutableArray`.
NSMutableArray *resultArray = nil;
if ([[array objectAtIndex:0] count] == [vector count]) {
// Nicely done w/ pre-allocating the result array here, so that there's no question
// of the indexes matches the results later on.
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
// 'queue' here is a concurrent queue. This means that you are proclaiming to the runtime
// that the blocks being executed are able to operate correctly w/o interference from each
// other. This is also thought of in terms of parallel execution: all these blocks may run
// **at once**. This *also* means, that you must not share storage between them.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j) {
// Moved 'result' inside the block.
NSInteger result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
// These array reads are **NOT** thread safe. They probably don't cause must trouble in
// practice, but you may want to reconfigure this.
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l] intValue];
}
// The replace of the object into resultArray is **NOT** thread-safe.
// This probably hasn't caused you much trouble, since you can guarantee that
// you aren't writing at the same index. However, I would strongly suggest to
// change this to be thread-safe.
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else {
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
Finally: consider just using Apple's Accelerate framework for this sort of problem solving. It's available on OSX and iOS, so you should have all of your bases covered.
it's the same thing if I multiple 2D-array and vector
-(NSMutableArray*)multiplicationArraysWithVector:(NSMutableArray *)array :(NSMutableArray *)vector
{
NSMutableArray* resultArray;
if ([[array objectAtIndex:0] count] == [vector count])
{
resultArray = [[NSMutableArray alloc] initWithCapacity:[array count]];
for (int i=0; i < [array count]; i++) {
[resultArray insertObject:[NSNull null] atIndex:i];
}
__block NSInteger result;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([array count], queue, ^(size_t j)
{
result = 0;
for (int l = 0; l < [[array objectAtIndex:0] count]; l++) {
result += [[[array objectAtIndex:j] objectAtIndex:l] intValue] * [[vector objectAtIndex:l]intValue];
}
[resultArray replaceObjectAtIndex:j withObject:#(result)];
});
}
else
{
NSLog(#"matrix count isn't correspond");
}
return resultArray;
}
In this case I can get a right or wrong data result.
I have an NSMutableArray urlArray of size n, I want to randomly choose 4 of these URLs from the total number of elements in the array.
However I don't want to shuffle urlArray directly, I'd prefer to make an "indexArray" [0 ... (n-1)] & shuffle these, & then use the first 4 elements of the shuffled indexArray to decide which elements I choose from urlArray.
First off I created the indexArray as follows:
for (int i = 0; i < numberOfStems; i++) {
[indexArray addObject:[NSNumber numberWithInteger:i]];
}
This allowed me to shuffle my indexArray, so far so good. Because I used the
[NSNumber numberWithInteger:i] method, the elements in the shuffled indexArray are NSNumbers.
Is there a way to convert the NSNumber objects in indexArray into ints?
I attempted to use the intValue function but this didn't appear to be what I needed.
I also tried creating a c style array but that wasn't so successful either - I'd like to stick with objective-c syntax if possible.
Any ideas? any hints appreciated :)
Why don't you just create a normal c array, shuffle that and then use the first four integers in the array as the for random index?
something like
int* index = malloc(numberOfStems*sizeof(int));
for (int i = 0; i < numberOfStems; ++i)
{
index[i] = i;
}
for (int i = numberOfStems - 1; i > 0; --i)
{
int randomIndex = arc4random() % i;
int tmp = index[i];
index[i] = index[randomIndex];
index[randomIndex] = tmp;
}
now use index to access the URL's
EDITED: updated algorithm (although not really related to OP question)
For a temporary array that stores only integers and gets thrown away after a relatively short task I would definitely prefer a C-style array: this would avoid a great deal of overhead, and is also simple to read.
int *array = (int*)malloc(sizeof(int)*numberOfStems);
for (int i = 0 ; i != numberOfStems ; i++) {
array[i] = i;
}
// Do the shuffle
// Pick first four, and do whatever you need to do
// ...
// Now that you are done with the array, do not forget to free it:
free(array);
I'm trying to use NSRange to hold a range of years, such as
NSRange years = NSMakeRange(2011, 5);
I know NSRange is used mostly for filtering, however I want to loop over the elements in the range. Is that possible without converting the NSRange into a NSArray?
It kind of sounds like you're expecting NSRange to be like a Python range object. It's not; NSRange is simply a struct
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;
not an object. Once you've created one, you can use its members in a plain old for loop:
NSUInteger year;
for(year = years.location; year < NSMaxRange(years); year++ ){
// Do your thing.
}
(Still working on the assumption that you're thinking about Python.) There's syntax in ObjC called fast enumeration for iterating over the contents of an NSArray that is pleasantly similar to a Python for loop, but since literal and primitive numbers can't be put into an NSArray, you can't go directly from an NSRange to a Cocoa array.
A category could make that easier, though:
#implementation NSArray (WSSRangeArray)
+ (id)WSSArrayWithNumbersInRange:(NSRange)range
{
NSMutableArray * arr = [NSMutableArray array];
NSUInteger i;
for( i = range.location; i < NSMaxRange(range); i++ ){
[arr addObject:[NSNumber numberWithUnsignedInteger:i]];
}
return arr;
}
Then you can create an array and use fast enumeration:
NSArray * years = [NSArray WSSArrayWithNumbersInRange:NSMakeRange(2011, 5)];
for( NSNumber * yearNum in years ){
NSUInteger year = [yearNum unsignedIntegerValue];
// and so on...
}
Remember that a NSRange is a structure holding two integers, representing the start and length of the range. You can easily loop over all of the contained integers using a for loop.
NSRange years = NSMakeRange(2011, 5);
NSUInteger year;
for(year = years.location; year < years.location + years.length; ++year) {
// Use the year variable here
}
This is a bit of an old question, but an alternative to using an NSArray would be to create an NSIndexSet with the desired range (using indexWithIndexesInRange: or initWithIndexesInRange:) and then using block enumeration as in https://stackoverflow.com/a/4209289/138772. (Seemed relevant as I was just checking on this myself.)
My alternate solution for this, was to define a macro just to make shorthand quicker.
#define NSRangeEnumerate(i, range) for(i = range.location; i < NSMaxRange(range); ++i)
To call it you do:
NSArray *array = #[]; // must contain at least the following range...
NSRange range = NSMakeRange(2011, 5);
NSUInteger i;
NSRangeEnumerate(i, range) {
id item = array[i];
// do your thing
}
personally I am still trying to figure out how I can write the macro so I can just call it like:
NSRangeEnumerate(NSUInteger i, range) {
}
which is not supported just yet... hope that helps or makes typing your program quicker
I have a 2D NSArray of string numbers that I would like to convert to a 2D C array of doubles for use with BLAS/LAPACK functions (through the accelerate framework).
This line of code seems to work, however seems to be incredibly inefficient and eventually crashes due to a malloc error. Is there a more efficient way to convert this 2D NSArray to a C array? Or a convienent way of using NSArrays with BLAS/LAPACK?
double gridDataC[[nrows intValue]+1][[ncol intValue]+1];
for(i=6;i<[fileLines count]-1;i++){
for(j=0;j<[ncol intValue]-1;j++){
gridDataC[i][j]=[[[[fileLines objectAtIndex:i] componentsSeparatedByString:#" "] objectAtIndex:j] doubleValue];
}
}
fileLines is an array that contains lines of a file that are parsed into respective numbers.
There are few things here that deal with memory.
1.componentsSeparatedByString: creates an autoreleased array. Since you're looping for every object within that string, you are creating similar array multiple times. As the autoreleased objects are not released until the end of the runloop this might clog the memory. It's better to do this once by bringing the method call out of the inner loop.
2.The value of i is the most confusing. You pass i as the index for gridDataC. It should probably be i - 6 if you're starting from i = 6.
double gridDataC[[nrows intValue] + 1][[ncol intValue] + 1];
for( i = 6; i < [fileLines count] - 1; i++ ){
NSArray * components = [[fileLines objectAtIndex:i] componentsSeparatedByString:#" "];
for( j = 0; j < [ncol intValue] - 1; j++ ){
gridDataC[i - 6][j] = [[components objectAtIndex:j] doubleValue];
}
}
I have seen this over and over, why exactly is it faster to use fast enumeration in loops rather than an NSEnumerator using nextObject:.
NSEnumerator is the old way to enumerate over collections. It involves creating an object to represent the enumeration, then calling a method on it for every single iteration. While this was perfectly serviceable for many years, it's not terribly efficient, as it involves at least one message send for every iteration of the loop. NSFastEnumeration is the more modern approach, which leverages native language support to provide a much more efficient enumeration. The way it works under the hood is it creates a struct that represents the current enumeration state and repeatedly calls -countByEnumeratingWithState:objects:count: on the collection. This method returns a C array of objects in the objects out-param as well as a counter in the count out-param. This allows the caller to then iterate over the C array. In essence, this means one message call per chunk of objects, which, depending on the collection, could be as efficient as a single message call to get all objects.
If you have a bit of code that looks like
for (id obj in myArray) {
[obj doSomething];
}
This gets translated by the compiler into something roughly equivalent to
NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
for (NSUInteger i = 0; i < __count; i++) {
id obj = __objects[i];
[obj doSomething];
}
}
The actual variables used are hidden, and the maximum size of the object buffer is also implementation-dependent, but the basic idea is there. It translates iteration over an obj-c collection into iteration over a C array.
GCC 8.9.4 Fast enumeration
protocol
GNUstep libs/base/trunk/Source/NSEnumerator.m countByEnumeratingWithState:objects:count:
It is not same as Apple's implementation but it is helpful to understand.
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (NSUInteger)len
{
IMP nextObject = [self methodForSelector: #selector(nextObject)];
int i;
state->itemsPtr = stackbuf;
state->mutationsPtr = (unsigned long*)self;
for (i = 0; i < len; i++)
{
id next = nextObject(self, #selector(nextObject));
if (nil == next)
{
return i;
}
*(stackbuf+i) = next;
}
return len;
}
NSArray *array = something;
array = { {1,2}, {2,3}, {3,4} }
that means array is an array of array. so how can you access all the arrays and their values.
we can use for loop like this
for (int i = 0; i < array.count; i++)
{
NSArray x = [array objectAtIndex:i];
}
or a fast enum works like this
for(NSArray array2 in array)
{
// do what ever you want with this new array2.
}
this is a sample example.
PS. I forgot how the array looks in console.