On 24/02/2009, at 1:21 PM, Ashley Perrien wrote:

It's a bit unclear from your description if what you have is really a 3D array or a 2D array. Each of the combinations in your example output has three dimensions, not two.

To recreate what I had described earlier:

NSArray *numbers = [NSArray arrayWithObjects: @"1", @"2", @"3", nil];
NSArray *letters = [NSArray arrayWithObjects: @"A", @"B", nil];
NSArray *colors = [NSArray arrayWithObjects: @"Red", @"White", @"Blue", nil];

NSArray *primaryArray = [NSArray arrayWithObjects: numbers, letters, colors, nil];

The primaryArray is being created in another method and being passed in. In THIS case it has 3 arrays in it, but I can't assume it'll always have 3.

- (void)        combinations
{
        NSArray* numbers = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
NSArray* letters = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", nil]; NSArray* colours = [NSArray arrayWithObjects:@"Red", @"White", @"Blue", nil];
        
        unsigned i, j, k;
        NSString* combo;
        
        for( i = 0; i < [numbers count]; ++i )
        {
                for( j = 0; j < [letters count]; ++j )
                {
                        for( k = 0; k < [colours count]; ++k)
                        {
int index = (i * [letters count] * [colours count]) + (j * [colours count]) + k; combo = [NSString stringWithFormat:@"combo%d: %@, %@, %@", index + 1, [numbers objectAtIndex:i], [letters objectAtIndex:j], [colours objectAtIndex:k]];
                                NSLog(@"%@", combo);
                        }
                }
        }
}

But this code assumes there will be 3 arrays (numbers, letters, colors), what if that number is not known? It could be 3, it could be 8. I could (fairly safely) assume that it will always be less than 12 and then nest it as shown with lots of error checking but that would be an unsightly mess.

Ashley Perrien



OK, I get what you mean now.

What you want to do is multiply all the arrays together, i.e. result = m(0) x m(1) x..x m(n) where n is the number of arrays in your "primary array" (that being the dimension of the result), and m being each array contained therein.

The difficulty is defining what it means to "multiply" two objects. If an array is being multiplied by a scalar, the result is a new array containing the same number of objects as the original. If the array is multiplied by another array, the result is a new array containing m x n objects.

One solution that comes to mind is to create a "multiply" category for NSObject, NSArray and maybe NSString if that's what you know your objects are going to be. For each class you need to define what it means to multiply it by another object, be it an array, another object of its own kind or any other object. For strings for example it might mean concatenating the strings or inserting them into a formatted string. Once you've done that you can simply write something like:

result = 1;

for( each object in primaryArray )
        result = [result multiplyBy:object];


Here's a very quick attempt at doing this - seems to work pretty well. Note that in the case of multiplying one array by another, if either array is empty it returns the other one. This is not strictly mathematically correct as it implies that n x 0 = n, which is not true. However this does simplify calling the code unconditionally (and if it offends you, you can redefine the empty array == 1) since the case of multiplying an array by a series of arrays is made to work simply.

This isn't the only solution, but it's object-oriented and clean. Hope it helps - interesting problem ;-)

--Graham





@interface NSArray (Multiply)

- (NSArray*)    multiplyBy:(id) object;
- (NSArray*)    multiplyByArray:(NSArray*) objects;
+ (void)        testMultiplication;

@end


@interface NSObject (Multiply)

- (id)          multiplyBy:(id) object;

@end


@interface NSString (Multiply)

- (NSString*)   multiplyBy:(id) object;

@end



@implementation NSArray (Multiply)


- (NSArray*)    multiplyByArray:(NSArray*) objects
{
// returns an array which is all the combinations of the objects in the input array with the objects of self. To simplify things, // the empty array is treated as equal to a constant of 1, i.e. array * empty -> array, not -> empty.
        
        if([self count] == 0 )
                return objects;
        else if([objects count] == 0 )
                return self;
        else
        {
                NSMutableArray* result = [NSMutableArray array];

                unsigned i, j;

                for( i = 0; i < [self count]; ++i )
                {
                        for( j = 0; j < [objects count]; ++j )
[result addObject:[[self objectAtIndex:i] multiplyBy:[objects objectAtIndex:j]]];
                }
                return result;
        }
}



- (NSArray*)    multiplyBy:(id) object
{
        if([object isKindOfClass:[self class]])
                return [self multiplyByArray:object];
        else
        {
                NSMutableArray* array = [NSMutableArray array];
                unsigned i;
                
                for( i = 0; i < [self count]; ++i )
                        [array addObject:[[self objectAtIndex:i] 
multiplyBy:object]];
                
                return array;
        }
}


+ (void)                testMultiplication
{
NSArray* numbers = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", nil];
        NSArray*        letters = [NSArray arrayWithObjects:@"A", @"B", @"C", 
nil];
NSArray* colours = [NSArray arrayWithObjects:@"Red", @"White", @"Blue", nil];
        NSArray*        animals = [NSArray arrayWithObjects:@"Cat", @"Dog", 
nil];
        
NSArray* primary = [NSArray arrayWithObjects:numbers, letters, colours, animals, nil];
        
        unsigned i;
NSArray* result = [NSArray array]; // start with an empty array (==1) to allow us to simply iterate the list below.
        
        for( i = 0; i < [primary count]; ++i )
                result = [result multiplyBy:[primary objectAtIndex:i]];
        
        NSLog(@"%@", result);
}



@end


@implementation NSString (Multiply)

- (NSString*)   multiplyBy:(id) object
{
// "multiplying" two strings returns the two strings separated by a comma
        
        return [NSString stringWithFormat:@"%@, %@", self, object];
}

@end



@implementation         NSObject (Multiply)

- (id)          multiplyBy:(id) object
{
#pragma unused(object)
// generally this needs to be implemented appropriately by specific subclasses of NSObject so that the // operation "multiply" can be defined to make sense. Currently simply returns self, treating <object> as constant == 1
        
        return self;
}

@end


Logged output of test method:

    "1, A, Red, Cat",
    "1, A, Red, Dog",
    "1, A, White, Cat",
    "1, A, White, Dog",
    "1, A, Blue, Cat",
    "1, A, Blue, Dog",
    "1, B, Red, Cat",
    "1, B, Red, Dog",
    "1, B, White, Cat",
    "1, B, White, Dog",
    "1, B, Blue, Cat",
    "1, B, Blue, Dog",
    "1, C, Red, Cat",
    "1, C, Red, Dog",
    "1, C, White, Cat",
    "1, C, White, Dog",
    "1, C, Blue, Cat",
    "1, C, Blue, Dog",
    "2, A, Red, Cat",
    "2, A, Red, Dog",
    "2, A, White, Cat",
    "2, A, White, Dog",
    "2, A, Blue, Cat",
    "2, A, Blue, Dog",
    "2, B, Red, Cat",
    "2, B, Red, Dog",
    "2, B, White, Cat",
    "2, B, White, Dog",
    "2, B, Blue, Cat",
    "2, B, Blue, Dog",
    "2, C, Red, Cat",
    "2, C, Red, Dog",
    "2, C, White, Cat",
    "2, C, White, Dog",
    "2, C, Blue, Cat",
    "2, C, Blue, Dog",
    "3, A, Red, Cat",
    "3, A, Red, Dog",
    "3, A, White, Cat",
    "3, A, White, Dog",
    "3, A, Blue, Cat",
    "3, A, Blue, Dog",
    "3, B, Red, Cat",
    "3, B, Red, Dog",
    "3, B, White, Cat",
    "3, B, White, Dog",
    "3, B, Blue, Cat",
    "3, B, Blue, Dog",
    "3, C, Red, Cat",
    "3, C, Red, Dog",
    "3, C, White, Cat",
    "3, C, White, Dog",
    "3, C, Blue, Cat",
    "3, C, Blue, Dog",
    "4, A, Red, Cat",
    "4, A, Red, Dog",
    "4, A, White, Cat",
    "4, A, White, Dog",
    "4, A, Blue, Cat",
    "4, A, Blue, Dog",
    "4, B, Red, Cat",
    "4, B, Red, Dog",
    "4, B, White, Cat",
    "4, B, White, Dog",
    "4, B, Blue, Cat",
    "4, B, Blue, Dog",
    "4, C, Red, Cat",
    "4, C, Red, Dog",
    "4, C, White, Cat",
    "4, C, White, Dog",
    "4, C, Blue, Cat",
    "4, C, Blue, Dog"





_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to