Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 将文本分成3个大小相等的组的算法_Algorithm_Sorting - Fatal编程技术网

Algorithm 将文本分成3个大小相等的组的算法

Algorithm 将文本分成3个大小相等的组的算法,algorithm,sorting,Algorithm,Sorting,我想创建一个算法,将文本分成3个大小相等的组(基于文本长度)。由于这将用于换行符,因此需要保持文本的顺序 例如,此字符串: Just testing to see how this works. 将排序为: Just testing // 12 characters to see how // 10 characters this works. // 11 characters 有什么想法吗?来自: 许多现代文字处理器都使用这种方法,如OpenOffice.org Wri

我想创建一个算法,将文本分成3个大小相等的组(基于文本长度)。由于这将用于换行符,因此需要保持文本的顺序

例如,此字符串:

Just testing to see how this works. 
将排序为:

Just testing   // 12 characters
to see how     // 10 characters
this works.    // 11 characters
有什么想法吗?

来自:

许多现代文字处理器都使用这种方法,如OpenOffice.org Writer和Microsoft word。这种算法是最优的,因为它总是将文本放在最少的行数上


对于初学者,您可以尝试下一个简单的启发式方法:将迭代器放置在n/3和2n/3中,并搜索每个迭代器附近的最近空间。

同样来自Wikipedia关于word wrap的文章的“最小粗糙度”动态程序可以根据您的需要进行调整。设置
LineWidth=len(text)/n-1
,忽略关于超出线宽的无限惩罚的注释;使用
c(i,j)
的定义,就像
P=2
一样


“某人”的回答很好。但是,我在将其转换为SWIFT代码时遇到了问题。这是我给所有感兴趣的人的翻译

import Foundation   

class SplitText{
    typealias MinRag = (Float, Int) // meaning (cost for line (so far), word index)

    // from http://stackoverflow.com/questions/6426017/word-wrap-to-x-lines-instead-of-maximum-width-least-raggedness?lq=1
    class func splitText(text:String, numberOfLines:Int)-> [String]{
        //preparations
        var words = split(text, maxSplit:100, allowEmptySlices: false, isSeparator:{(s:Character)-> Bool in return s == " " || s == "\n"})
        var cumwordwidth =  [Int](); //cummulative word widths
        cumwordwidth.append(0);
        for word in words{
            cumwordwidth.append(cumwordwidth[cumwordwidth.count - 1] + count(word));
        }
        var totalwidth = cumwordwidth[cumwordwidth.count - 1] + count(words) - 1;
        var linewidth:Float = Float(totalwidth - (numberOfLines - 1)) / Float(numberOfLines)

        // cost function for one line for words i .. j
        var cost = { (i:Int,j:Int)-> Float in
            var actuallinewidth = max(j - i - 1, 0) + (cumwordwidth[j] - cumwordwidth[i]);
            var remainingWidth: Float = linewidth - Float(actuallinewidth)
            return remainingWidth * remainingWidth
        }

        var best = [[MinRag]]()
        var tmp = [MinRag]();
        //ensure that data structure is initialised in a way that we start with adding the first word
        tmp.append((0, -1));
        for  word in words {
            tmp.append((Float.infinity , -1));
        }
        best.append(tmp);
        //now we can start. We simply calculate the cost for all possible lines
        for l in 1...numberOfLines {
            tmp = [MinRag]()
            for j in 0...words.count {
                var min:MinRag = (best[l - 1][0].0 + cost(0, j), 0);
                var k: Int
                for k = 0; k < j + 1 ; ++k  {
                    var loc:Float = best[l - 1][k].0 + cost(k, j);
                    if (loc < min.0 || (loc == min.0 && k < min.1)) {
                        min=(loc, k);
                    }
                    println("l=\(l), j=\(j), k=\(k), min=\(min)")
                }
                tmp.append(min);
            }
            best.append(tmp);
        }

        //now build the answer based on above calculations
        var lines = [String]();
        var b = words.count;
        var o:Int
        for o = numberOfLines; o > 0 ; --o {
            var a = best[o][b].1;
            lines.append(" ".join(words[a...b-1]));
            b = a;
        }
        return reverse(lines);
    }
}
<代码>导入基础 类拆分文本{ typealias MinRag=(Float,Int)//意思(行的成本(到目前为止),单词索引) //从http://stackoverflow.com/questions/6426017/word-wrap-to-x-lines-instead-of-maximum-width-least-raggedness?lq=1 类func splitText(文本:String,numberOfLines:Int)->[String]{ //准备工作 var words=split(text,maxslit:100,allowEmptySlices:false,isSeparator:{(s:Character)->Bool返回s==“”| | s==“\n”}) var cumwordwidth=[Int]();//累积字宽 cumwordwidth.append(0); 一字不差{ append(cumwordwidth[cumwordwidth.count-1]+count(word)); } var totalwidth=cumwordwidth[cumwordwidth.count-1]+count(words)-1; 变量linewidth:Float=Float(总宽度-(numberOfLines-1))/Float(numberOfLines) //单词i..j的一行成本函数 var成本={(i:Int,j:Int)->浮动 var actuallinewidth=max(j-i-1,0)+(cumwordwidth[j]-cumwordwidth[i]); var remainingWidth:Float=linewidth-Float(实际线宽) 返回剩余宽度*剩余宽度 } var best=[[MinRag]]() var tmp=[MinRag](); //确保以我们从添加第一个单词开始的方式初始化数据结构 tmp.append((0,-1)); 一字不差{ 追加((Float.infinity,-1)); } 最佳附加(tmp); //现在我们可以开始了。我们只需计算所有可能线路的成本 对于1…numberOfLines中的l{ tmp=[MinRag]() 对于0…单词中的j.count{ VarMin:MinRag=(最佳[l-1][0].0+成本(0,j),0); 变量k:Int 对于k=0;k0;--o{ var a=最佳[o][b].1; 行。追加(“.join(单词[a…b-1])); b=a; } 返回反向(行); } }
如果您可以为n组而不是仅为3组获得奖励积分,则可获得奖励积分!)那么,您需要对文本进行排序还是拆分?有点不同,应该是n组大小相对相似的?请解释是什么决定了组的大小。忘记n组。只有3组尽可能接近大小。我认为这个问题不同于通常的单词包装。通常,您提前知道线宽,并且算法确定行数。在这里,你预先知道行数,算法决定了行宽。把字符串的长度除以你想要的行数怎么样?它至少会给出一个近似值。你能为此创建一些代码吗?我不明白你的意思(我读过关于最小粗糙度的书,它似乎正是我所需要的。但是我不知道如何将这个等式转换成可用的代码。有什么想法吗?呃……我正在尝试将它转换成Objective-C和Actionscript……但我在这两个方面都失败了。这是python脚本吗?我不喜欢如此相互依赖,但我只是可以不要解析它…即使有代码提示。好吧,这绝对是我要找的!非常感谢。我要看看是否能找到一个懂Python的朋友。这段代码是用Objective-C编写的,放在这里:我采用了Swift的代码,放在这里:
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()
import Foundation   

class SplitText{
    typealias MinRag = (Float, Int) // meaning (cost for line (so far), word index)

    // from http://stackoverflow.com/questions/6426017/word-wrap-to-x-lines-instead-of-maximum-width-least-raggedness?lq=1
    class func splitText(text:String, numberOfLines:Int)-> [String]{
        //preparations
        var words = split(text, maxSplit:100, allowEmptySlices: false, isSeparator:{(s:Character)-> Bool in return s == " " || s == "\n"})
        var cumwordwidth =  [Int](); //cummulative word widths
        cumwordwidth.append(0);
        for word in words{
            cumwordwidth.append(cumwordwidth[cumwordwidth.count - 1] + count(word));
        }
        var totalwidth = cumwordwidth[cumwordwidth.count - 1] + count(words) - 1;
        var linewidth:Float = Float(totalwidth - (numberOfLines - 1)) / Float(numberOfLines)

        // cost function for one line for words i .. j
        var cost = { (i:Int,j:Int)-> Float in
            var actuallinewidth = max(j - i - 1, 0) + (cumwordwidth[j] - cumwordwidth[i]);
            var remainingWidth: Float = linewidth - Float(actuallinewidth)
            return remainingWidth * remainingWidth
        }

        var best = [[MinRag]]()
        var tmp = [MinRag]();
        //ensure that data structure is initialised in a way that we start with adding the first word
        tmp.append((0, -1));
        for  word in words {
            tmp.append((Float.infinity , -1));
        }
        best.append(tmp);
        //now we can start. We simply calculate the cost for all possible lines
        for l in 1...numberOfLines {
            tmp = [MinRag]()
            for j in 0...words.count {
                var min:MinRag = (best[l - 1][0].0 + cost(0, j), 0);
                var k: Int
                for k = 0; k < j + 1 ; ++k  {
                    var loc:Float = best[l - 1][k].0 + cost(k, j);
                    if (loc < min.0 || (loc == min.0 && k < min.1)) {
                        min=(loc, k);
                    }
                    println("l=\(l), j=\(j), k=\(k), min=\(min)")
                }
                tmp.append(min);
            }
            best.append(tmp);
        }

        //now build the answer based on above calculations
        var lines = [String]();
        var b = words.count;
        var o:Int
        for o = numberOfLines; o > 0 ; --o {
            var a = best[o][b].1;
            lines.append(" ".join(words[a...b-1]));
            b = a;
        }
        return reverse(lines);
    }
}