mirror of
https://github.com/danog/Telegram.git
synced 2024-12-03 09:57:46 +01:00
117 lines
3.8 KiB
Objective-C
117 lines
3.8 KiB
Objective-C
#import "TGGifKeyboardBalancedPartition.h"
|
|
|
|
#define NH_LP_TABLE_LOOKUP(table, i, j, rowsize) (table)[(i) * (rowsize) + (j)]
|
|
|
|
@implementation TGGifKeyboardBalancedPartition
|
|
|
|
+ (NSInteger *)linearPartitionTable:(NSArray *)sequence numPartitions:(NSInteger)numPartitions
|
|
{
|
|
NSInteger k = numPartitions;
|
|
NSInteger n = [sequence count];
|
|
|
|
// allocate a table buffer of n * k integers
|
|
NSInteger tableSize = sizeof(NSInteger) * n * k;
|
|
NSInteger *tmpTable = (NSInteger *)malloc(tableSize);
|
|
memset(tmpTable, 0, tableSize);
|
|
|
|
// allocate a solution buffer of (n - 1) * (k - 1) integers
|
|
NSInteger solutionSize = sizeof(NSInteger) * (n - 1) * (k - 1);
|
|
NSInteger *solution = (NSInteger *)malloc(solutionSize);
|
|
memset(solution, 0, solutionSize);
|
|
|
|
// fill table with initial values
|
|
for (NSInteger i = 0; i < n; i++) {
|
|
NSInteger offset = i? NH_LP_TABLE_LOOKUP(tmpTable, i - 1, 0, k) : 0;
|
|
NH_LP_TABLE_LOOKUP(tmpTable, i, 0, k) = [sequence[i] integerValue] + offset;
|
|
}
|
|
|
|
for (NSInteger j = 0; j < k; j++) {
|
|
NH_LP_TABLE_LOOKUP(tmpTable, 0, j, k) = [sequence[0] integerValue];
|
|
}
|
|
|
|
// calculate the costs and fill the solution buffer
|
|
for (NSInteger i = 1; i < n; i++) {
|
|
for (NSInteger j = 1; j < k; j++) {
|
|
NSInteger currentMin = 0;
|
|
NSInteger minX = NSIntegerMax;
|
|
|
|
for (NSInteger x = 0; x < i; x++) {
|
|
NSInteger c1 = NH_LP_TABLE_LOOKUP(tmpTable, x, j - 1, k);
|
|
NSInteger c2 = NH_LP_TABLE_LOOKUP(tmpTable, i, 0, k) - NH_LP_TABLE_LOOKUP(tmpTable, x, 0, k);
|
|
NSInteger cost = MAX(c1, c2);
|
|
|
|
if (!x || cost < currentMin) {
|
|
currentMin = cost;
|
|
minX = x;
|
|
}
|
|
}
|
|
|
|
NH_LP_TABLE_LOOKUP(tmpTable, i, j, k) = currentMin;
|
|
NH_LP_TABLE_LOOKUP(solution, i - 1, j - 1, k - 1) = minX;
|
|
}
|
|
}
|
|
|
|
// free the tmp table, we don't need it anymore
|
|
free(tmpTable);
|
|
|
|
return solution;
|
|
}
|
|
|
|
+ (NSArray *)linearPartitionForSequence:(NSArray *)sequence numberOfPartitions:(NSInteger)numberOfPartitions
|
|
{
|
|
NSInteger n = [sequence count];
|
|
NSInteger k = numberOfPartitions;
|
|
|
|
if (k <= 0) return @[];
|
|
|
|
if (k >= n) {
|
|
NSMutableArray *partition = [[NSMutableArray alloc] init];
|
|
[sequence enumerateObjectsUsingBlock:^(id obj, __unused NSUInteger idx, __unused BOOL *stop) {
|
|
[partition addObject:@[obj]];
|
|
}];
|
|
return [partition copy];
|
|
}
|
|
|
|
if (n == 1) {
|
|
return @[sequence];
|
|
}
|
|
|
|
// get the solution table
|
|
NSInteger *solution = [self linearPartitionTable:sequence numPartitions:numberOfPartitions];
|
|
NSInteger solutionRowSize = numberOfPartitions - 1;
|
|
|
|
k = k - 2;
|
|
n = n - 1;
|
|
NSMutableArray *answer = [NSMutableArray array];
|
|
|
|
while (k >= 0) {
|
|
if (n < 1) {
|
|
[answer insertObject:@[] atIndex:0];
|
|
} else {
|
|
NSMutableArray *currentAnswer = [NSMutableArray array];
|
|
for (NSInteger i = NH_LP_TABLE_LOOKUP(solution, n - 1, k, solutionRowSize) + 1, range = n + 1; i < range; i++) {
|
|
[currentAnswer addObject:sequence[i]];
|
|
}
|
|
[answer insertObject:currentAnswer atIndex:0];
|
|
|
|
n = NH_LP_TABLE_LOOKUP(solution, n - 1, k, solutionRowSize);
|
|
}
|
|
|
|
k = k - 1;
|
|
}
|
|
|
|
// free the solution table because we don't need it anymore
|
|
free(solution);
|
|
|
|
NSMutableArray *currentAnswer = [NSMutableArray array];
|
|
for (NSInteger i = 0, range = n + 1; i < range; i++) {
|
|
[currentAnswer addObject:sequence[i]];
|
|
}
|
|
|
|
[answer insertObject:currentAnswer atIndex:0];
|
|
|
|
return [answer copy];
|
|
}
|
|
|
|
@end
|