[英]Converting a Python script to Objective-C
I recently asked this question to create a function for optimal word-wrapping and got the response I was looking for in this Python script. 我最近问了这个问题,以创建一个用于最佳自动换行的函数,并获得了我在此Python脚本中寻找的响应。 Unfortunately, I don't speak Python.
不幸的是,我不会说Python。 :D Can someone help me convert this to Objective-C?
:D有人可以帮助我将其转换为Objective-C吗?
_ _
Code. I took the liberty of modifying the DP always to return exactly n lines, at the cost of increasing the running time from O(#words ** 2) to O(#words ** 2 * n).
def minragged(text, n=3):
"""
>>> minragged('Just testing to see how this works.')
['Just testing', 'to see how', 'this works.']
>>> minragged('Just testing to see how this works.', 10)
['', '', 'Just', 'testing', 'to', 'see', 'how', 'this', 'works.', '']
"""
words = text.split()
cumwordwidth = [0]
# cumwordwidth[-1] is the last element
for word in words:
cumwordwidth.append(cumwordwidth[-1] + len(word))
totalwidth = cumwordwidth[-1] + len(words) - 1 # len(words) - 1 spaces
linewidth = float(totalwidth - (n - 1)) / float(n) # n - 1 line breaks
def cost(i, j):
"""
cost of a line words[i], ..., words[j - 1] (words[i:j])
"""
actuallinewidth = max(j - i - 1, 0) + (cumwordwidth[j] - cumwordwidth[i])
return (linewidth - float(actuallinewidth)) ** 2
# best[l][k][0] is the min total cost for words 0, ..., k - 1 on l lines
# best[l][k][1] is a minimizing index for the start of the last line
best = [[(0.0, None)] + [(float('inf'), None)] * len(words)]
# xrange(upper) is the interval 0, 1, ..., upper - 1
for l in xrange(1, n + 1):
best.append([])
for j in xrange(len(words) + 1):
best[l].append(min((best[l - 1][k][0] + cost(k, j), k) for k in xrange(j + 1)))
lines = []
b = len(words)
# xrange(upper, 0, -1) is the interval upper, upper - 1, ..., 1
for l in xrange(n, 0, -1):
a = best[l][b][1]
lines.append(' '.join(words[a:b]))
b = a
lines.reverse()
return lines
if __name__ == '__main__':
import doctest
doctest.testmod()
Here's the function translated to Objective-C. 这是转换为Objective-C的函数。 It's been updated to compile but only barely tested for correctness (on the example given in your previous question :
[... minragged:@"Just testing to see how this works." lineCount:3]
). 已对其进行了更新以进行编译,但仅对正确性进行了测试(在上一个问题中给出的示例中:
[... minragged:@"Just testing to see how this works." lineCount:3]
)。 Nothing regarding efficiency or Objective-C idioms has been taken in to account. 没有考虑到效率或Objective-C习惯用语。
@interface NSMutableArray (reverse)
/* Could also return self, but this makes it explicit that array is reversed in-place
rather than returning a reversed copy.
*/
-(void)reverse;
@end
@implementation NSMutableArray (reverse)
-(void)reverse {
int i,j;
for (i=0,j=[self count]-1; i<j; ++i,--j) {
[self exchangeObjectAtIndex:i withObjectAtIndex:j];
}
}
@end
-(NSArray*)minragged:(NSString*)text lineCount:(int)n {
int width = 0;
NSArray *words = [text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *cumWordWidth = [NSMutableArray arrayWithObject:[NSNumber numberWithInt:width]];
for (NSString *word in words) {
width += [word length];
[cumWordWidth addObject:[NSNumber numberWithInt:width]];
}
int totalWidth = width + [words count] - 1,
lineWidth = (double)(totalWidth - (n - 1)) / (double)(n),
actualLineWidth,
i, j, k, min_k;
double cost, min_cost;
// best[i][k][0] is the min total cost for words 0, ..., k - 1 on i lines
// best[i][k][1] is a minimizing index for the start of the last line
NSMutableArray *best = [NSMutableArray arrayWithCapacity:n],
*best_i_prev = [NSMutableArray arrayWithCapacity:([words count]+1)],
*best_i;
[best_i_prev addObject:[NSArray arrayWithObjects:[NSNumber numberWithDouble:0.0],[NSNull null],nil]];
for (i=0; i < [words count]; ++i) {
[best_i_prev addObject:[NSArray arrayWithObjects:(NSNumber*)kCFNumberPositiveInfinity,[NSNull null],nil]];
}
[best addObject:best_i_prev];
for (i=1; i <= n; ++i) {
best_i=[NSMutableArray arrayWithCapacity:[words count]];
for (j=0; j <= [words count]; ++j) {
min_k=0;
min_cost = [(NSNumber*)kCFNumberPositiveInfinity doubleValue];
for (k=0; k < j; ++k) {
actualLineWidth = j - k - 1;
if (actualLineWidth < 0) {
actualLineWidth = 0;
}
actualLineWidth += [[cumWordWidth objectAtIndex:j] intValue]
- [[cumWordWidth objectAtIndex:k] intValue];
cost = (lineWidth - (double)(actualLineWidth));
cost *= cost;
cost += [[[best_i_prev objectAtIndex:k] objectAtIndex:0] doubleValue];
if (cost < min_cost) {
min_cost = cost;
min_k = k;
}
}
[best_i addObject:[NSArray arrayWithObjects:[NSNumber numberWithDouble:min_cost],
[NSNumber numberWithInt:min_k],
nil]];
}
[best addObject:best_i];
best_i_prev = best_i;
}
NSMutableArray *lines = [NSMutableArray arrayWithCapacity:n];
NSRange range;
int end;
end = [words count];
for (i=n; i > 0; --i) {
range.location = [[[[best objectAtIndex:i] objectAtIndex:end] objectAtIndex:1] intValue];
range.length = end-range.location;
[lines addObject:[[words subarrayWithRange:range] componentsJoinedByString:@" "]];
end = range.location;
}
[lines reverse];
return lines;
}
You may wish to create an autorelease pool to clear out the objects created in -minragged:lineCount:
so as not to exhaust memory. 您可能希望创建一个自动释放池,以清除在
-minragged:lineCount:
创建的对象, -minragged:lineCount:
耗尽内存。 If you do, make sure to retain lines
before draining the pool, and autoreleasing it afterwards. 如果这样做,请确保在排干池之前保留
lines
,然后再自动释放池。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.