Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.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
Python 将块状序列划分为偶数块?_Python_Algorithm - Fatal编程技术网

Python 将块状序列划分为偶数块?

Python 将块状序列划分为偶数块?,python,algorithm,Python,Algorithm,我有一个“块状”的项目序列,我希望将其划分为一定数量的大小大致相同的包裹,同时保持包裹内容(以及包裹本身)的排序顺序。既然世上没有什么新鲜事,我想我只是缺少这个问题的正确名称。我的最终目标是用python实现该算法,但我至少需要朝着正确的方向努力 问题是我有一篇文章,分成不同长度的章节,我想把它分成一系列公平的阅读。当然,阅读的顺序必须保持不变 关于一些细节,我有2519节。最长1876字,最短7字。平均长度为305个单词,中间长度为242个。我不确定它是否准确地解决了您的程序,但在麻省理工学院

我有一个“块状”的项目序列,我希望将其划分为一定数量的大小大致相同的包裹,同时保持包裹内容(以及包裹本身)的排序顺序。既然世上没有什么新鲜事,我想我只是缺少这个问题的正确名称。我的最终目标是用python实现该算法,但我至少需要朝着正确的方向努力

问题是我有一篇文章,分成不同长度的章节,我想把它分成一系列公平的阅读。当然,阅读的顺序必须保持不变


关于一些细节,我有2519节。最长1876字,最短7字。平均长度为305个单词,中间长度为242个。

我不确定它是否准确地解决了您的程序,但在麻省理工学院开放式课程中,它们用于解决行的最佳分割,以便文本沿着页面(“”)很好地填充,类似于Latex。见第17分钟

该算法将根据线分裂的丑陋程度定义惩罚的函数,给出保证的最优分裂。在讲座中,他们将这个丑陋的函数定义为
(pagewidth-actual_linewidth)^3
,但您可以定义自己的函数。该算法或多或少地尝试了所有不同的分割可能性(以一种智能的方式),并选择了最佳的一种。DP的主要要求是可将问题划分为子程序,例如,可根据
n-1、n-2、…
单词的先前解决方案描述
n
单词的解决方案。这些类型的DP算法通常是
O(n^2)
O(n^3)
,因此肯定不是NP难的


如果你对基本算法感兴趣,我强烈建议你观看整个系列讲座,老师们都很棒。

这会给你一个好的结果,一个“贪婪”的策略:

  • 计算出你努力追求的平均值,
    avg=total\u words/num\u reads
  • 开始迭代各部分,累积到目前为止的字数
  • 如果你击中了一个精确的匹配,那么标记该部分并继续
  • 否则,如果您要检查字数,请根据更接近平均值的内容选择是否包含下一节,例如,如果您未包含,则短20,如果包含,则短100,则将其忽略
要想做得更好,你需要一些启发。如果你把输入搞乱了,比如一个大的部分和许多小的部分,比如

100 100 100 100 100 100 40000 100 100 100 100
如果你想把它分成5个部分,你希望你的输出是什么样的?我的算法会告诉你:

100 100 100 100 100 100
40000
100 100 100 100
0
0
您可以轻松地对其进行调整,以强制每个部分至少使用一个单词:

100 100 100 100 100 100
40000
100 100
100
100
但这可能不像这个选项那么“好”:

100 100 100
100 100 100
40000
100 100
100 100

是的,我建议你去看看建议的讲座。你必须稍微调整一下启发式。例如,对于你来说,在一个部分中有更多的单词是可以的,而对于行包装,如果你看了,那么它是无限糟糕的。

好吧,这激起了我的好奇心,所以我写了一个动态规划算法,使用简单的不良启发法
abs(num_words-avg_words)**3
。它应该与任何启发一起工作。以下是示例输出:

>>> section_words = [100, 100, 100, 100, 100, 100, 40000, 100, 100, 100, 100]
>>> def heuristic(num_words, avg):
...     return abs(num_words - avg)**3
... 
>>> print_solution(solve(section_words, heuristic, 3))
Total=41000, 3 readings, avg=13666.67
Reading #1 (  600 words): [100, 100, 100, 100, 100, 100]
Reading #2 (40000 words): [40000]
Reading #3 (  400 words): [100, 100, 100, 100]
>>> print_solution(solve(section_words, heuristic, 5))
Total=41000, 5 readings, avg=8200.00
Reading #1 (  300 words): [100, 100, 100]
Reading #2 (  300 words): [100, 100, 100]
Reading #3 (40000 words): [40000]
Reading #4 (  200 words): [100, 100]
Reading #5 (  200 words): [100, 100]

>>> section_words = [7, 300, 242, 100, 115, 49, 563, 
                     1000, 400, 9, 14, 300, 200, 400, 
                     500, 200, 10, 19, 1876, 100, 200, 
                     15, 59, 299, 144, 85, 400, 600, 534, 200, 143, 15]
>>> print_solution(solve(section_words, heuristic, 10))
Total=9098, 10 readings, avg=909.80
Reading #1 (  649 words): [7, 300, 242, 100]
Reading #2 (  727 words): [115, 49, 563]
Reading #3 ( 1000 words): [1000]
Reading #4 (  723 words): [400, 9, 14, 300]
Reading #5 (  600 words): [200, 400]
Reading #6 (  729 words): [500, 200, 10, 19]
Reading #7 ( 1876 words): [1876]
Reading #8 (  902 words): [100, 200, 15, 59, 299, 144, 85]
Reading #9 ( 1000 words): [400, 600]
Reading #10 (  892 words): [534, 200, 143, 15]

>>> print_solution(solve(section_words, heuristic, 5))
Total=9098, 5 readings, avg=1819.60
Reading #1 ( 2376 words): [7, 300, 242, 100, 115, 49, 563, 1000]
Reading #2 ( 2023 words): [400, 9, 14, 300, 200, 400, 500, 200]
Reading #3 ( 1905 words): [10, 19, 1876]
Reading #4 ( 1302 words): [100, 200, 15, 59, 299, 144, 85, 400]
Reading #5 ( 1492 words): [600, 534, 200, 143, 15]

>>> print_solution(solve(section_words, heuristic, 3))
Total=9098, 3 readings, avg=3032.67
Reading #1 ( 3099 words): [7, 300, 242, 100, 115, 49, 563, 1000, 400, 9, 14, 300]
Reading #2 ( 3205 words): [200, 400, 500, 200, 10, 19, 1876]
Reading #3 ( 2794 words): [100, 200, 15, 59, 299, 144, 85, 400, 600, 534, 200, 143, 15]
这是密码。尽管我建议你自己尝试去实现它,做一个好的练习

子问题是
R(n,i,j)
,即:通过
n
读数拆分
i
j
段的最低不良程度是什么

基本情况很简单:

R(1, i, j) = heuristic(num words in sections i thru j, total words / total sections)
然后,对于递归,您可以从所有可能的方法中找到最佳的解决方案,将剩余的部分数拆分为左和右,以及放置该分区的最佳位置:

R(n, i, j) = the lowest badness out of
    R(1, i, i+1) + R(n-1, i+1, j)
    R(1, i, i+2) + R(n-1, i+2, j)
    ...
    R(1, i, j-1) + R(n-1, j-1, j)

    R(2, i, i+1) + R(n-2, i+1, j)
    R(2, i, i+2) + R(n-2, i+2, j)
    ...
    R(2, i, j-1) + R(n-2, j-1, j)

    ...
    ...

    R(n-1, i, i+1) + R(1, i+1, j)
    R(n-1, i, i+2) + R(1, i+2, j)
    ...
    R(n-1, i, j-1) + R(1, j-1, j)
病理病例是指当你的阅读量超过部分时:

R(n, i, j) = infinity if n > j-i
您可以从
n=1
开始构建解决方案,然后从
j-i=1
开始构建解决方案,然后从
i=0
开始构建解决方案


它最终有5个嵌套for循环,所以我不确定它是否尽可能有效,但它似乎做到了这一点。

读数是否必须始终保持在节顺序?是的,我认为这是使其不同于普通箱子包装的要求。“公平读数”是什么?如果整组章节/阅读必须保持有序,你可能不会比计算
K=总长度/阅读数量
,然后在文本中线性移动并在每个长度处停止-
K
块做得更好。但是,是的,你是对的,订购的要求使这与装箱不同。这不再是一个组合问题,因为你不能组合任何东西,因为顺序是固定的。是的,我肯定在寻找一个“好”的解决方案,因为各部分的大小确实有很大差异,我希望贪婪的方法会导致病理结果。谢谢!这将是一个很大的帮助,在理解文本的视频。我也会实现自己,来处理我的具体情况。