0

I need to organize an array of strings of random length into the least number of new strings with a max size. Is there a function or something in javascript, or something that can be translated to javascript, that will do this?

For example, the new strings might have max lengths of 1000 characters. The array might have strings of lengths 100, 48, 29, etc. I would want to combine those strings into as few new strings as possible.

edit: Sorry if this doesn't make sense, I tried my best.

3
  • 1
    Please do not abuse the tags field. Commented Jul 24, 2011 at 19:51
  • Edit your question with an example of what you want (it's not clear at all), pick one language, and show what you have tried. Commented Jul 24, 2011 at 19:52
  • Apparently this is already called the bin packing problem. I wasn't abusing the tags. This is a general programming problem; the fact that I need it for javascript is irrelevant. Commented Jul 24, 2011 at 19:56

2 Answers 2

3

No standard method in Javascript, but plenty of theoretical work has been done on this (i.e. the bin packing problem).

http://en.wikipedia.org/wiki/Bin_packing_problem

Some sample pseudo code in the link - should be trivial to translate to javascript.

The algorithm shown isn't going to be optimal in every case. To find the optimal solution to your example you'll just need to iterate over every possibility which might not be that bad depending on how many strings you have.

Sign up to request clarification or add additional context in comments.

1 Comment

Not very many actually, this is a very small project. I was considering trying to write it myself this way, but I don't think I'll be able to.
1

For my own entertainment, I wrote a simple bin packing algorithm. I picked a simple algorithm which is to sort the input strings by length. Create a new bin. Put the first (longest remaining) string into the bin and then keep filling it up with the longest strings that will fit until no more strings will fit. Create a new bin, repeat. To test it, I allocate an array of strings of random lengths and use that as input. You can see the output visually here: http://jsfiddle.net/jfriend00/FqPKe/.

Running it a bunch of times, it gets a fill percentage of between 91-98%, usually around 96%. Obviously the fill percentage is higher if there are more short strings to fill with.

Here's the code:

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>"

);

3 Comments

Thanks, I'll use something like this. Wasn't exactly what I was looking for, but my expectations were probably unrealistic. I was hoping for something that might check every possible combination of the strings to find the one that fits them with the least space left over. I'm not sure how the processing of this would work, whether it would bog down the servers or not, but I'm not exactly using huge strings or tiny bins.
It's an interesting computer science problem. The brute force method of checking all possible combinations would be very compute intensive (an enormous number of combinations to check) if there were very many strings. You didn't specify how important the level of packing was so we didn't have much to go on there.
Thanks, too bad I didn't realize this before :(. I wrote the brute force method, which, for me, because I'm quite new, was pretty hard, and my computer couldn't handle it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.