我需要将一组随机长度的字符串组织成具有最大大小的最少数量的新字符串。是否有一个函数或javascript中的某些东西,或者可以翻译成javascript的东西,这样做呢?
例如,新字符串的最大长度可能为1000个字符。该数组可能包含长度为100,48,29等的字符串。我希望将这些字符串组合成尽可能少的新字符串。
编辑:对不起,如果这没有意义,我尽力了。
答案 0 :(得分:3)
Javascript中没有标准方法,但是已经对此进行了大量的理论工作(即装箱问题)。
http://en.wikipedia.org/wiki/Bin_packing_problem
链接中的一些示例伪代码 - 应该很容易转换为javascript。
所示的算法在每种情况下都不是最佳的。要找到适合您示例的最佳解决方案,您只需要根据您拥有的字符串数量来迭代可能不是那么糟糕的每种可能性。
答案 1 :(得分:1)
为了我自己的娱乐,我写了一个简单的bin打包算法。我选择了一个简单的算法,即按长度对输入字符串进行排序。创建一个新的bin。将第一个(剩余的最长的)字符串放入垃圾箱,然后用最长的字符串填充它,直到不再适合字符串。创建一个新的bin,重复一遍。为了测试它,我分配一组随机长度的字符串并将其用作输入。您可以在此处直观地看到输出:http://jsfiddle.net/jfriend00/FqPKe/。
运行它多次,它的填充百分比在91-98%之间,通常在96%左右。如果要填充更多短字符串,显然填充百分比会更高。
以下是代码:
function generateRandomLengthStringArrays(num, maxLen) {
var sourceChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY1234567890";
var sourceIndex = 0;
var result = [];
var len, temp, fill;
function getNextSourceChar() {
var ch = sourceChars.charAt(sourceIndex++);
if (sourceIndex >= sourceChars.length) {
sourceIndex = 0;
}
return(ch);
}
for (var i = 0; i < num; i++) {
len = Math.floor(Math.random() * maxLen);
temp = new String();
fill = getNextSourceChar();
// create string
for (var j = 0; j < len; j++) {
temp += fill;
}
result.push(temp);
}
return(result);
}
function packIntoFewestBins(input, maxLen) {
// we assume that none of the strings in input are longer than maxLen (they wouldn't fit in any bin)
var result = [];
// algorithm here is to put the longest string into a bin and
// then find the next longest one that will fit into that bin with it
// repeat until nothing more fits in the bin, put next longest into a new bin
// rinse, lather, repeat
var bin, i, tryAgain, binLen;
// sort the input strings by length (longest first)
input.sort(function(a, b) {return(b.length - a.length)});
while (input.length > 0) {
bin = new String(); // create new bin
bin += input.shift(); // put first one in (longest we have left) and remove it
tryAgain = true;
while (bin.length < maxLen && tryAgain) {
tryAgain = false; // if we don't find any more that fit, we'll stop after this iteration
binLen = bin.length; // save locally for speed/convenience
// find longest string left that will fit in the bin
for (i = 0; i < input.length; i++) {
if (input[i].length + binLen <= maxLen) {
bin += input[i];
input.splice(i, 1); // remove this item from the array
tryAgain = true; // try one more time
break; // break out of for loop
}
}
}
result.push(bin);
}
return(result);
}
var binLength = 60;
var numStrings = 100;
var list = generateRandomLengthStringArrays(numStrings, binLength);
var result = packIntoFewestBins(list, binLength);
var capacity = result.length * binLength;
var fillage = 0;
for (var i = 0; i < result.length; i++) {
fillage += result[i].length;
$("#result").append(result[i] + "<br>")
}
$("#summary").html(
"Fill percentage: " + ((fillage/capacity) * 100).toFixed(1) + "%<br>" +
"Number of Input Strings: " + numStrings + "<br>" +
"Number of Output Bins: " + result.length + "<br>" +
"Bin Legnth: " + binLength + "<br>"
);