-1

I've prototyped an algorithm for my iOS game in Python, and I need to rewrite in in ObjC. Basically, I have a board of 16 numbers, and I want to loop through every number three times and the four functions I'm using (add, subtract, multiply, exponentiate). 1+2+3, 2*3-4, 3^4-5, 9-4^3, etc., but without order of operations (first operation is always done first).

What I would like is an overview of how this might be implemented in Objective-C. Specifically, what is the equivalent of an array of functions in Objective-C? Is there an easy way to implement it with selectors? What's the best structure to use for loops with numbers? Array of NSIntegers, array of ints, NSArray/NSMutableArray of NSNumbers?

import random as rand
min = 0
max = 9

max_target = 20

maximum_to_calculate = 100


def multiply(x, y):
    return x * y


def exponate(x, y):
    return x ** y


def add(x, y):
    return x + y


def subtract(x, y):
    return x - y

function_array = [multiply, exponate, add, subtract]

board = [rand.randint(min, max) for i in xrange(0, 16)]

dict_of_frequencies = {}

for a in board:
    for b in board:
        for first_fun in function_array:
            first_result = first_fun(a, b)
            for c in board:
                for second_fun in function_array:
                    final_result = second_fun(first_result, c)
                    if final_result not in dict_of_frequencies:
                        dict_of_frequencies[final_result] = 0
                    dict_of_frequencies[final_result] += 1
jscs
  • 63,694
  • 13
  • 151
  • 195
Marcus Buffett
  • 1,289
  • 1
  • 14
  • 32
  • Here are some random thoughts: Use NS(Mutable)Array. Don't bother with C arrays. You can't call normal C functions with selectors, those are only for Obj-C methods. Look into C function pointers. – Linuxios Apr 23 '14 at 22:23
  • Have a look at Objective C Blocks - https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html – Paulw11 Apr 23 '14 at 22:26
  • Thanks, rmaddy for pointing that out, I've edited the question a bit. However, I would prefer not to post my Objective-C code because I don't have a specific problem with it, it just seems bloated and inefficient. I don't want an exact algorithm I can copy and paste into my code, just an idea of how an experienced developer would go about doing something like this. – Marcus Buffett Apr 23 '14 at 23:13

3 Answers3

2

The most convenient way in Objective-C to construct an array of functions would be to use Blocks:

typedef NSInteger (^ArithmeticBlock)(NSInteger, NSInteger);

ArithmeticBlock add = ^NSInteger (NSInteger x, NSInteger y){
    return x + y;
};

ArithmeticBlock sub = ^NSInteger (NSInteger x, NSInteger y){
    return x - y;
};

NSArray * operations = @[add, sub];

Since there's no great way to perform arithmetic on NSNumbers, it would probably be best to create and store the board's values as primitives, such as NSIntegers, in a plain C array. You can box them up later easily enough, if necessary -- @(boardValue) gives you an NSNumber.

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
  • Editorial note: Arrays of numbers is something that's a lot easier to deal with in Python than ObjC; I'm hoping the newish ObjC literal stuff in Clang will be expanded with arithmetic features. – jscs Apr 23 '14 at 23:12
0

If you want to do it with straight C function pointers, something like this will do it:

#include <stdio.h>
#include <math.h>

long add(int a, int b) {
    return a + b;
}

long subtract(int a, int b) {
    return a - b;
}

long multiply(int a, int b) {
    return a * b;
}

long exponate(int a, int b) {
    return pow(a, b);
}

int main(void) {
    long (*mfunc[4])(int, int) = {add, subtract, multiply, exponate};
    char ops[4] = {'+', '-', '*', '^'};

    for ( int i = 0; i < 4; ++i ) {
        printf("5 %c 9 = %ld\n", ops[i], mfunc[i](5, 9));
    }

    return 0;
}

and gives the output:

paul@MacBook:~/Documents/src$ ./rndfnc
5 + 9 = 14
5 - 9 = -4
5 * 9 = 45
5 ^ 9 = 1953125
paul@MacBook:~/Documents/src$ 

Function pointer syntax can be slightly convoluted. long (*mfunc[4])(int, int) basically translates to defining a four-element array, called mfunc, of pointers to functions returning long and taking two arguments of type int.

Crowman
  • 25,242
  • 5
  • 48
  • 56
0

Maddy is right. Anyway, I'll give it a try just for the fun of it. This has never seen a compiler. So please forgive me all the typos and minor syntax errors in advance.

#include <stdlib.h>

...

const int MIN = 0;
const int MAX = 9;
const int MAX_TARGET = 20;
const int MAX_TO_CALCULATE = 100;

...

- (int) multiply:(int)x with:(int)y { return x * y; } 
- (int) exponate:(int)x with:(int)y { return x ^ y; } 
- (int) add:(int)x to:(int)y { return x + y; } 
- (int) substract:(int)x by:(int)y { return x - y; } 

// some method should start here, probably with 
-(void) someMethod {

NSArray *functionArray = [NSArray arrayWithObjects: @selector(multiply::), @selector(exponate::), @selector(add::), @substract(multiply::), nil]; // there are other ways of generating an array of objects

NSMutableArray *board = [NSMutableArray arrayWithCapacity:16]; //Again, there are other ways available.

for (int i = 0; i < 16; i++) {
  [board addObject:@(arc4random() % (MAX-MIN) + MIN)];
}

NSMutableDictionary dictOfFrequencies = [[NSMutableDictionary alloc] init];  

for (NSNumber a in board) 
  for (NSNumber b in board) 
    for (SEL firstFun in functionArray) {
      NSNumber firstResult = @([self performSelector:firstFun withObject:a withObject:b]);
      NSNumber countedResults = [dictOfFrequencies objectForKey:firstResult];
      if (countedResults) {
        [dictOfFrequencies removeObjectForKey:firstResult];
        countedResults = @(1 + [countedResults intValue]);
      } else {
        countedResults = @1; // BTW, using the @ followed by a numeric expression creates an NSNumber object with the value 1. 
      }
      [dictOfFrequencies setObject:countedResults forKey:firstResult];
    }
}

Well, let me add some comments before others do. :-) There is no need for objective c. You python code is iterative therefore you can implement it in plain C. Plain C is available where ever Objective C is. If you really want to go for Objective-C here then you should forget your python code and implement the same logic (aiming for the same result) in Objective-C in an OOP style. My code really tries to translate your code as close as possible. Therefore my code is far far away from neither beeing good style nor maintainable nor proper OOP. Just keep that in mind before you think, ObjC was complicated compared to python :-)

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • This is exactly the kind of thing I was looking for, I didn't know selectors could be used like that, thank you! – Marcus Buffett Apr 23 '14 at 23:37
  • You're welcome. Well, you could express your greatfullness by accepting the answer. :-) – Hermann Klecker Apr 23 '14 at 23:41
  • You need to store & retrieve your selectors as NSValues. Store like `[NSValue valueWithPointer:@selector(yourSelector:)];` and retrieve like `SEL yourSelector = yourArray[0].pointerValue;` – Logan Apr 23 '14 at 23:51
  • I will, just have to get to a computer, can't figure out how to do it on the app I'm using. You mentioned it's not really an OOP approach, would you mind giving a really brief overview of what I could change to make it more OOP? – Marcus Buffett Apr 24 '14 at 00:09
  • These shouldn't be methods. What object performs these actions? – jscs Apr 24 '14 at 01:34
  • 1
    Can an NSArray hold a selector? It gives me an error when I do it. – Marcus Buffett Apr 24 '14 at 14:43
  • No, it can't, @MarcusBuffett. – jscs Apr 24 '14 at 21:18
  • @JoshCaswell, yes, these methods should be part of a class implementation. However, I don't think that this was the original question. A good answer for plain C functions was already given. – Hermann Klecker Apr 24 '14 at 23:11
  • @MarcusBuffett, that is a good point. Frankly, I never tried that out. NSArrays can hold objects only. The selector can easily wrapped in a class that does not do anything but hold a selector. As I said, the aim to translate your python code was just 'out of the top of my head' and never passed a compiler so far. – Hermann Klecker Apr 24 '14 at 23:13