2011-07-24 188 views
0

我需要將一個隨機長度的字符串數組組織成最小數量的具有最大大小的新字符串。有沒有一個函數或什麼在JavaScript中,或者可以轉換爲JavaScript的東西,這將做到這一點?排序功能?

例如,新字符串的最大長度可能爲1000個字符。數組可能有長度爲100,48,29等的字符串。我想將這些字符串組合成儘可能少的新字符串。

編輯:對不起,如果這沒有意義,我盡我所能。

+1

請不要濫用標籤領域。 – SLaks

+0

用你想要的東西(根本不清楚)編輯你的問題,選擇一種語言,並顯示你已經嘗試過的東西。 – Mat

+0

顯然這已被稱爲垃圾箱包裝問題。 我沒有濫用標籤。這是一個普遍的編程問題;事實上,我需要它的JavaScript是無關緊要的。 – mowwwalker

回答

1

對於我自己的娛樂,我寫了一個簡單的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>" 

); 
+0

謝謝,我會用這樣的東西。這不正是我所期待的,但我的期望可能不現實。我希望有一些東西可以檢查每個可能的字符串組合,找到適合它們的字符串,並留下最少的空間。我不確定這個處理過程是如何工作的,不管它是否會讓服務器停止工作,但我並不完全使用巨大的字符串或小型垃圾箱。 – mowwwalker

+0

這是一個有趣的計算機科學問題。如果有很多字符串,那麼檢查所有可能的組合的強力方法將會非常計算密集(需要檢查的組合數量龐大)。你沒有具體說明包裝水平有多重要,所以我們沒有太多的關注。 – jfriend00

+0

謝謝,太糟糕了我之前並沒有意識到這一點:我寫了蠻力方法,對我來說,因爲我很新,很難,而且我的電腦無法處理它。 – mowwwalker

3

Javascript中沒有標準方法,但在這方面已經做了大量的理論工作(即bin裝箱問題)。

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

的鏈接某些樣本僞碼 - 應該是微不足道翻譯爲JavaScript。

顯示的算法在每種情況下都不是最佳的。爲了找到你的例子的最佳解決方案,你只需要遍歷每一個可能不會那麼糟糕的可能性,這取決於你有多少個字符串。

+0

實際上並不是很多,這是一個非常小的項目。我正在考慮試圖用這種方式自己寫,但我認爲我不能這樣做。 – mowwwalker