【问题标题】:Splitting long string without breaking words fulfilling lines拆分长字符串而不破坏单词完成行
【发布时间】:2013-05-07 08:54:46
【问题描述】:

在您认为它重复之前(有很多问题询问如何在不破坏单词的情况下拆分长字符串)请记住我的问题有点不同:顺序并不重要,我必须适合单词为了尽可能地使用每一行。

我有一组无序的单词,我想在不超过 253 个字符的情况下将它们组合起来。

def compose(words):
    result = " ".join(words)
    if len(result) > 253:
        pass # this should not happen!
    return result

我的问题是我想尽可能地填满这条线。例如:

words = "a bc def ghil mno pq r st uv"
limit = 5 # max 5 characters

# This is good because it's the shortest possible list,
#   but I don't know how could I get it
# Note: order is not important
good = ["a def", "bc pq", "ghil", "mno r", "st uv"]

# This is bad because len(bad) > len(good)
#   even if the limit of 5 characters is respected
# This is equivalent to:
#   bad  = ["a bc", "def", "ghil", "mno", "pq r", "st uv"]
import textwrap
bad = textwrap.wrap(words, limit)

我该怎么办?

【问题讨论】:

标签: python string algorithm


【解决方案1】:

这是bin packing problem;该解决方案是 NP-hard,尽管存在非最优启发式算法,主要是首次拟合递减和最佳拟合递减。实现见https://github.com/type/Bin-Packing。

【讨论】:

  • 谢谢 :) 我发现了这个:mathworld.wolfram.com/Bin-PackingProblem.html - 如果我理解正确的话,最好的非最佳解决方案是这个页面中提出的解决方案(按长度从最长到最短排序并填充桶)。我不知道它是否也适用于 2d 和 3d 问题。
【解决方案2】:

非最优离线快速一维装箱 Python 算法

def binPackingFast(words, limit, sep=" "):
    if max(map(len, words)) > limit:
        raise ValueError("limit is too small")
    words.sort(key=len, reverse=True)
    res, part, others = [], words[0], words[1:]
    for word in others:
        if len(sep)+len(word) > limit-len(part):
            res.append(part)
            part = word
        else:
            part += sep+word
    if part:
        res.append(part)
    return res

性能

在/usr/share/dict/words(由words-3.0-20.fc18.noarch 提供)上测试过,它可以在我慢速双核笔记本电脑上在一秒钟内完成 50 万字,在这些参数下效率至少为 90%:

limit = max(map(len, words))
sep = ""

limit *= 1.5 我得到 92%,limit *= 2 我得到 96%(相同的执行时间)。

最佳(理论)值计算如下:math.ceil(len(sep.join(words))/limit)

没有有效的装箱算法可以保证做得更好

来源:http://mathworld.wolfram.com/Bin-PackingProblem.html

故事的寓意

虽然找到最佳解决方案很有趣,但我认为在大多数情况下,将此算法用于一维离线装箱问题会更好。

资源

备注

【讨论】:

    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多