Gold Challenge: Can't get container to hold a container


#1

I’m having some trouble with getting a container to have another instance of a container. I can bring them in with no problem if I take just the subitems from one and place them in another, though I’m guessing that’s not what the solution called for.

The following code works, but I’m sure there’s probably a more elegant way to do it. I’ve basically tried to place “container1” and “container2” into “container3” along with an extra item.

Here is my code:

BNRItem.h

#import <Foundation/Foundation.h>

@interface BNRItem : NSObject

{
    NSString *itemName;
    NSString *serialNumber;
    int valueInDollars;
    NSDate *dateCreated;
}

+(id)randomItem;

-(id)initWithItemName:(NSString *)name
       valueInDollars:(int)value
         serialNumber:(NSString *)sNumber;

-(void)setItemName:(NSString *)str;
-(NSString *)itemName;

-(void)setSerialNumber:(NSString *)str;
-(NSString *)serialNumber;

-(void)setValueInDollars:(int)i;
-(int)valueInDollars;

-(NSDate *)dateCreated;

@end

BNRItem.m

#import "BNRItem.h"

@implementation BNRItem

+(id)randomItem
{
    NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy",@"Rusty",@"Shiny", nil];
    NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear",@"Spork",@"Mac", nil];
    
    NSInteger adjectiveIndex = rand() % [randomAdjectiveList count];
    NSInteger nounIndex = rand() % [randomNounList count];
    
    NSString *randomName = [NSString stringWithFormat:@"%@ %@",[randomAdjectiveList objectAtIndex:adjectiveIndex],[randomNounList objectAtIndex:nounIndex]];
    
    int randomValue = rand() %100;
    
    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                    '0' + rand() % 10,
                                    'A' + rand() % 26,
                                    '0' + rand() % 10,
                                    'A' + rand() % 26,
                                    '0' + rand() % 10];
    
    BNRItem *newItem = [[self alloc] initWithItemName:randomName
                                       valueInDollars:randomValue
                                         serialNumber:randomSerialNumber];
    return newItem;
}


-(id)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber
{
    self = [super init];
    
    if (self) {
        
    [self setItemName:name];
    [self setSerialNumber:sNumber];
    [self setValueInDollars:value];
    dateCreated = [[NSDate alloc] init];
    }
    
    return self;
}

-(id)init
{
    return [self initWithItemName:@"Item" valueInDollars:0 serialNumber:@""];
}

-(void)setItemName:(NSString *)str
{
    itemName = str;
}

-(NSString *)itemName
{
    return itemName;
}

-(void)setSerialNumber:(NSString *)str
{
    serialNumber = str;
}

-(NSString *)serialNumber
{
    return serialNumber;
}

-(void)setValueInDollars:(int)i
{
    valueInDollars = i;
}

-(int)valueInDollars
{
    return valueInDollars;
}

-(NSDate *)dateCreated
{
    return dateCreated;
}

-(NSString *)description
{
    NSString *descriptionString = [[NSString alloc] initWithFormat:@"%@ (%@): Worth %d",
                                   itemName,
                                   serialNumber,
                                   valueInDollars];
    return descriptionString;
}

@end

BNRContainer.h

#import "BNRItem.h"

@interface BNRContainer : BNRItem
{
    NSString *containerName;
    NSArray *subitems;
    int containerValue;
}

-(void)setContainerName:(NSString *)str;
-(NSString *)containerName;

-(void)setSubitems:(NSArray *)sItems;
-(NSArray *)subitems;

-(void)setContainerValue:(int)i;
-(int)containerValue;

-(id)initWithContainerName:(NSString *)cName;
@end

BNRContainer.m

#import "BNRContainer.h"

@implementation BNRContainer

-(void)setContainerName:(NSString *)str
{
    containerName = str;
}

-(NSString *)containerName
{
    return containerName;
}

-(void)setSubitems:(NSArray *)sItems
{
    subitems = sItems;
}

-(NSArray *)subitems
{
    return subitems;
}

-(void)setContainerValue:(int)i
{
    containerValue = i;
}

-(int)containerValue
{
    int i = 0;

    if (!containerValue) {
        for (int v = 0; v < [subitems count]; v++) {
            i += [[subitems objectAtIndex:v] valueInDollars];
        }
    } else {
        i += containerValue;
    }
    return i;
}

-(id)initWithContainerName:(NSString *)cName
{
    self = [super init];
    
    if (self) {
        [self setContainerName:cName];
    }
    
    return self;
}

@end

main.m

#import <Foundation/Foundation.h>
#import "BNRItem.h"
#import "BNRContainer.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        BNRContainer *c1 = [[BNRContainer alloc] initWithContainerName:@"container1"];
        BNRContainer *c2 = [[BNRContainer alloc] initWithContainerName:@"container2"];
        BNRContainer *c3 = [[BNRContainer alloc] initWithContainerName:@"container3"];
        
        NSMutableArray *items1 = [[NSMutableArray alloc] init];
        for (int i = 0; i < 6; i++) {
            BNRItem *p1 = [BNRItem randomItem];
            [items1 addObject:p1];
        }

        NSMutableArray *items2 = [[NSMutableArray alloc] init];
        for (int i = 0; i < 3; i++) {
            BNRItem *p2 = [BNRItem randomItem];
            [items2 addObject:p2];
        }

        NSArray *subitem1 = [[NSArray alloc] init];
        subitem1 = items1;
        [c1 setSubitems];
        
        NSArray *subitem2 = [[NSArray alloc] init];
        subitem2 = items2;
        [c2 setSubitems];
        
        NSMutableArray *subitem3 = [[NSMutableArray alloc] init];
        [subitem3 addObject:[c1 subitems]];
        [subitem3 addObject:[c2 subitems]];
        [subitem3 addObject:[BNRItem randomItem]];
        [c3 setSubitems];
        [c3 setContainerValue:([c1 containerValue] + [c2 containerValue] + [[subitem3 objectAtIndex:2] valueInDollars])];
        
        NSLog(@"%@ contains %@, worth %d",[c1 containerName],[c1 subitems],[c1 containerValue]);
        NSLog(@"%@ contains %@, worth %d",[c2 containerName],[c2 subitems],[c2 containerValue]);
        NSLog(@"%@ contains %@, worth %d",[c3 containerName],[c3 subitems], [c3 containerValue]);

        items1 = nil;
        items2 = nil;
        
        
    }
    
    return 0;
}

I am also having trouble having it automatically calculate a container value automatically. It works now, but it’s because I’ve manually entered in how to sum up the value of “container3”.

Thanks in advance for comments.


#2

You can just pass any BNRItem as the subitem of the BNRItemContainer. Since BNRItemContainer is a subclass of BNRItem, you can treat it like an BNRItem. Just insert an instance into the NSArray, which you give the other container as subitems.

You should make at least one more method in BNRItemContainer:

which adds an Item at the end of the subitems array.

Then you can make one container in the main method, give it some BNRItems as subitems, and then do the same again, and add the second container as subitem of the first container.

Then you should not give the container an extra container name. Just use the inherited itemName.

You should also overwrite the description method in BNRItemContainer, so that you first give all the details of the BNRItemContainer, and then the array description (which again gives the description of all contained items. If one Item is an BNRItemContainer, it will again give its own description and then the array description etc. etc.)


#3

My BNRItemContainer interface:

[code]#import “BNRItem.h”

@interface BNRItemContainer : BNRItem
{
NSMutableArray *subitems;
}

  • (NSArray *)subitems;
  • (void)setSubitems:(NSArray *)subitems;
  • (void) addSubitem:(BNRItem *)item;
    @end[/code]

#4

Thank you, TAKeanice! I’ll play around with this. I really appreciate the help!