Closest-pair problem/Objective-C: Difference between revisions

From Rosetta Code
Content added Content deleted
m (modernize)
Line 10: Line 10:
double xCoord, yCoord;
double xCoord, yCoord;
}
}
+ (id)x: (double)x y: (double)y;
+ (instancetype)x: (double)x y: (double)y;
- (id)initWithX: (double)x andY: (double)y;
- (instancetype)initWithX: (double)x andY: (double)y;
- (double)x;
- (double)x;
- (double)y;
- (double)y;
Line 21: Line 21:
@implementation Point
@implementation Point


+ (id)x: (double)x y: (double)y {
+ (instancetype)x: (double)x y: (double)y {
return [[[self alloc] initWithX: x andY: y] autorelease];
return [[self alloc] initWithX: x andY: y];
}
}


- (id)initWithX: (double)x andY: (double)y {
- (instancetype)initWithX: (double)x andY: (double)y {
if (!(self = [super init])) return nil;
if ((self = [super init])) {
xCoord = x;

xCoord = x;
yCoord = y;
}
yCoord = y;

return self;
return self;
}
}
Line 64: Line 63:


+ (NSArray *)closestPairSimple: (NSArray *)pts {
+ (NSArray *)closestPairSimple: (NSArray *)pts {
if ( [pts count] < 2 ) return @[ @HUGE_VAL ];
int i, j;
double c = [ pts[0] dist: pts[1] ];
if ( [pts count] < 2 ) return [NSArray arrayWithObject: [NSNumber numberWithDouble: HUGE_VAL]];
NSArray *r;
NSArray *r = @[ @(c), pts[0], pts[1] ];
double c = [[pts objectAtIndex: 0] dist: [pts objectAtIndex: 1]];
for(int i=0; i < ([pts count] - 1); i++) {
for(int j=i+1; j < [pts count]; j++) {
r = [NSArray
double t = [ pts[i] dist: pts[j] ];
arrayWithObjects: [NSNumber numberWithDouble: c],
[pts objectAtIndex: 0],
[pts objectAtIndex: 1], nil];
for(i=0; i < ([pts count] - 1); i++) {
for(j=i+1; j < [pts count]; j++) {
double t;
t = [[pts objectAtIndex: i] dist: [pts objectAtIndex: j]];
if ( t < c ) {
if ( t < c ) {
c = t;
c = t;
r = [NSArray
r = @[ @(t), pts[i], pts[j] ];
arrayWithObjects: [NSNumber numberWithDouble: t],
[pts objectAtIndex: i],
[pts objectAtIndex: j], nil];
}
}
}
}
Line 95: Line 85:


+ (NSArray *)closestPairPriv: (NSArray *)xP and: (NSArray *)yP {
+ (NSArray *)closestPairPriv: (NSArray *)xP and: (NSArray *)yP {
int nP, k;
NSArray *pR, *pL, *minR, *minL;
NSMutableArray *yR, *yL, *joiningStrip, *tDist, *minDist;
double middleVLine;
int i, nP, k;


if ( [xP count] <= 3 ) {
if ( [xP count] <= 3 ) {
Line 104: Line 91:
} else {
} else {
int midx = ceil([xP count]/2.0);
int midx = ceil([xP count]/2.0);
pL = [xP subarrayWithRange: NSMakeRange(0, midx)];
NSArray *pL = [xP subarrayWithRange: NSMakeRange(0, midx)];
pR = [xP subarrayWithRange: NSMakeRange(midx, [xP count] - midx)];
NSArray *pR = [xP subarrayWithRange: NSMakeRange(midx, [xP count] - midx)];
yL = [[NSMutableArray alloc] init];
NSMutableArray *yL = [[NSMutableArray alloc] init];
yR = [[NSMutableArray alloc] init];
NSMutableArray *yR = [[NSMutableArray alloc] init];
middleVLine = [[pL objectAtIndex: (midx-1)] x];
double middleVLine = [pL[midx-1] x];
for(i=0; i < [yP count]; i++) {
for(int i=0; i < [yP count]; i++) {
if ( [[yP objectAtIndex: i] x] <= middleVLine ) {
if ( [yP[i] x] <= middleVLine ) {
[yL addObject: [yP objectAtIndex: i]];
[yL addObject: yP[i]];
} else {
} else {
[yR addObject: [yP objectAtIndex: i]];
[yR addObject: yP[i]];
}
}
}
}
minR = [ClosestPair closestPairPriv: pR and: yR];
NSArray *minR = [ClosestPair closestPairPriv: pR and: yR];
minL = [ClosestPair closestPairPriv: pL and: yL];
NSArray *minL = [ClosestPair closestPairPriv: pL and: yL];
minDist = [ClosestPair minBetween: minR and: minL];
NSMutableArray *minDist = [ClosestPair minBetween: minR and: minL];
joiningStrip = [NSMutableArray arrayWithCapacity: [xP count]];
NSMutableArray *joiningStrip = [NSMutableArray arrayWithCapacity: [xP count]];
for(i=0; i < [yP count]; i++) {
for(int i=0; i < [yP count]; i++) {
if ( fabs([[yP objectAtIndex: i] x] - middleVLine) <
if ( fabs([yP[i] x] - middleVLine) <
[[minDist objectAtIndex: 0] doubleValue] ) {
[minDist[0] doubleValue] ) {
[joiningStrip addObject: [yP objectAtIndex: i]];
[joiningStrip addObject: yP[i]];
}
}
}
}
tDist = minDist;
NSMutableArray *tDist = minDist;
nP = [joiningStrip count];
int nP = [joiningStrip count];
for(i=0; i < (nP - 1); i++) {
for(int i=0; i < (nP - 1); i++) {
k = i + 1;
int k = i + 1;
while( (k < nP) &&
while( (k < nP) &&
( ([[joiningStrip objectAtIndex: k] y] -
( ([joiningStrip[k] y] - [joiningStrip[i] y]) < [minDist[0] doubleValue] ) ) {
double d = [joiningStrip[i] dist: joiningStrip[k]];
[[joiningStrip objectAtIndex: i] y]) < [[minDist objectAtIndex: 0] doubleValue] ) ) {
if ( d < [tDist[0] doubleValue] ) {
double d = [[joiningStrip objectAtIndex: i] dist: [joiningStrip objectAtIndex: k]];
if ( d < [[tDist objectAtIndex: 0] doubleValue] ) {
tDist = @[ @(d), joiningStrip[i], joiningStrip[k] ];
tDist = [NSArray arrayWithObjects: [NSNumber numberWithDouble: d],
[joiningStrip objectAtIndex: i],
[joiningStrip objectAtIndex: k], nil];
}
}
k++;
k++;
}
}
}
}
[yL release]; [yR release];
return tDist;
return tDist;
}
}
Line 148: Line 131:


+ (id)minBetween: (id)minA and: (id)minB {
+ (id)minBetween: (id)minA and: (id)minB {
if ( [[minA objectAtIndex: 0] doubleValue] <
if ( [minA[0] doubleValue] < [minB[0] doubleValue] ) {
[[minB objectAtIndex: 0] doubleValue] ) {
return minA;
return minA;
} else {
} else {
Line 164: Line 146:
int main()
int main()
{
{
@autoreleasepool {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];


NSMutableArray *p = [[NSMutableArray alloc] init];
NSMutableArray *p = [[NSMutableArray alloc] init];
srand(0);
srand(0);
for(int i = 0; i < NP; i++) {
for(int i = 0; i < NP; i++) {
[p addObject:
[p addObject:
[Point x: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0
[Point x: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0
y: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0]
y: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0]
];
];
}
}


//NSArray *r1 = [ClosestPair closestPairSimple: p];
//NSArray *r1 = [ClosestPair closestPairSimple: p];
NSArray *r2 = [ClosestPair closestPair: p];
NSArray *r2 = [ClosestPair closestPair: p];


//NSLog(@"%lf", [[r1 objectAtIndex: 0] doubleValue]);
//NSLog(@"%lf", [r1[0] doubleValue]);
NSLog(@"%lf", [[r2 objectAtIndex: 0] doubleValue]);
NSLog(@"%lf", [r2[0] doubleValue]);


}
[p release];
[pool drain];
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}</lang>
}</lang>

Revision as of 09:45, 25 February 2014

Closest-pair problem/Objective-C is part of Closest pair problem. You may find other members of Closest pair problem at Category:Closest pair problem.
Works with: GNUstep
Works with: Cocoa

<lang objc>#import <Foundation/Foundation.h>

  1. import <math.h>

@interface Point : NSObject {

 double xCoord, yCoord;

} + (instancetype)x: (double)x y: (double)y; - (instancetype)initWithX: (double)x andY: (double)y; - (double)x; - (double)y; - (double)dist: (Point *)pt; - (NSComparisonResult)compareX: (Point *)pt; - (NSComparisonResult)compareY: (Point *)pt; @end

@implementation Point

+ (instancetype)x: (double)x y: (double)y {

 return [[self alloc] initWithX: x andY: y];

}

- (instancetype)initWithX: (double)x andY: (double)y {

 if ((self = [super init])) {
   xCoord = x;
   yCoord = y;
 }
 return self;

}

- (double)x { return xCoord; } - (double)y { return yCoord; }

- (double)dist: (Point *)pt {

 return hypot([self x] - [pt x], [self y] - [pt y]);

}

- (NSComparisonResult)compareX: (Point *)pt {

 if      ( [self x] < [pt x] ) return NSOrderedAscending;
 else if ( [self x] > [pt x] ) return NSOrderedDescending;
 else                          return NSOrderedSame;

}

- (NSComparisonResult)compareY: (Point *)pt {

 if      ( [self y] < [pt y] ) return NSOrderedAscending;
 else if ( [self y] > [pt y] ) return NSOrderedDescending;
 else                          return NSOrderedSame;

} @end</lang>

<lang objc>@interface ClosestPair : NSObject + (NSArray *)closestPairSimple: (NSArray *)pts; + (NSArray *)closestPair: (NSArray *)pts; + (NSArray *)closestPairPriv: (NSArray *)xP and: (NSArray *)yP; + (id)minBetween: (id)minA and: (id)minB; @end

@implementation ClosestPair

+ (NSArray *)closestPairSimple: (NSArray *)pts {

 if ( [pts count] < 2 ) return @[ @HUGE_VAL ];
 double c = [ pts[0] dist: pts[1] ];
 NSArray *r = @[ @(c), pts[0], pts[1] ];
 for(int i=0; i < ([pts count] - 1); i++) {
   for(int j=i+1; j < [pts count]; j++) {
     double t = [ pts[i] dist: pts[j] ];
     if ( t < c ) {
       c = t;
       r = @[ @(t), pts[i], pts[j] ];
     }
   }
 }
 return r;

}

+ (NSArray *)closestPair: (NSArray *)pts {

 return [self closestPairPriv: [pts sortedArrayUsingSelector: @selector(compareX:)]
                          and: [pts sortedArrayUsingSelector: @selector(compareY:)]
   ];

}

+ (NSArray *)closestPairPriv: (NSArray *)xP and: (NSArray *)yP {

 int nP, k;
 if ( [xP count] <= 3 ) {
   return [self closestPairSimple: xP];
 } else {
   int midx = ceil([xP count]/2.0);
   NSArray *pL = [xP subarrayWithRange: NSMakeRange(0, midx)];
   NSArray *pR = [xP subarrayWithRange: NSMakeRange(midx, [xP count] - midx)];
   NSMutableArray *yL = [[NSMutableArray alloc] init];
   NSMutableArray *yR = [[NSMutableArray alloc] init];
   double middleVLine = [pL[midx-1] x];
   for(int i=0; i < [yP count]; i++) {
     if ( [yP[i] x] <= middleVLine ) {
       [yL addObject: yP[i]];
     } else {
       [yR addObject: yP[i]];
     }
   }
   NSArray *minR = [ClosestPair closestPairPriv: pR and: yR];
   NSArray *minL = [ClosestPair closestPairPriv: pL and: yL];
   NSMutableArray *minDist = [ClosestPair minBetween: minR and: minL];
   NSMutableArray *joiningStrip = [NSMutableArray arrayWithCapacity: [xP count]];
   for(int i=0; i < [yP count]; i++) {
     if ( fabs([yP[i] x] - middleVLine) <
          [minDist[0] doubleValue] ) {
       [joiningStrip addObject: yP[i]];
     }
   }
   NSMutableArray *tDist = minDist;
   int nP = [joiningStrip count];
   for(int i=0; i < (nP - 1); i++) {
     int k = i + 1;
     while( (k < nP) &&
            ( ([joiningStrip[k] y] - [joiningStrip[i] y]) < [minDist[0] doubleValue] ) ) {
       double d = [joiningStrip[i] dist: joiningStrip[k]];
       if ( d < [tDist[0] doubleValue] ) {
         tDist = @[ @(d), joiningStrip[i], joiningStrip[k] ];
       }
       k++;
     }
   }
   return tDist;
 }

}

+ (id)minBetween: (id)minA and: (id)minB {

 if ( [minA[0] doubleValue] < [minB[0] doubleValue] ) {
   return minA;
 } else {
   return minB;
 }

}

@end</lang>

Testing

<lang objc>#define NP 10000

int main() {

 @autoreleasepool {
   NSMutableArray *p = [[NSMutableArray alloc] init];
   srand(0);
   for(int i = 0; i < NP; i++) {
     [p addObject:
          [Point x: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0
                 y: 20.0*((double)rand()/(RAND_MAX+1.0)) - 10.0]
       ];
   }
   //NSArray *r1 = [ClosestPair closestPairSimple: p];
   NSArray *r2 = [ClosestPair closestPair: p];
   //NSLog(@"%lf", [r1[0] doubleValue]);
   NSLog(@"%lf", [r2[0] doubleValue]);
 }
 return EXIT_SUCCESS;

}</lang>

Timing (with the time command):

d&c:         0.22user 0.00system 0:00.41elapsed
brute force: 13.53user 0.06system 0:13.87elapsed