我有一个项目列表,每个项目都有一个数量。
var items = {
1: 12, // we have 12 x item1
2: 1, // we have 1 x item2
3: 1,
4: 7,
5: 2,
6: 2
};
或者,这可以被视为:
var items = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6];
如何获取这些项目的每个组合的列表,请记住,顺序完全不重要(因此[1,2,3] == [3,2,1]
),并且结果中不是每个项目都必须存在。< / p>
我认为输出看起来像这样:
[1]
[1, 1]
[1, 2]
[1, 3]
...
或者,甚至更好:
{1 : 1} // 1 x item1
{1 : 2} // 2 x item1
{1 : 1, 2 : 1} // 1 x item1, 1 x item2
{1 : 1, 3 : 1}
....
答案 0 :(得分:2)
我认为每件商品的数量都是有限的。
我会在这里使用增量: 从空开始,尽可能添加项目1。完成后,删除所有1并添加2并再次开始添加。当达到容量时,将它们全部删除,再添加2并重新开始。当2s达到容量时,删除它们并添加3.等等......
有点像数字工作。
<小时/> 好吧,让我们尝试编码...使用递增整数键的哈希是一个数组;-) 更容易假设数组的第一个元素是out'floating radix'数字的正确数字。
这是javaScript:
var limits = [1, 3, 5, 2];
function out(arr){
var text = '';
for (var i=0; i < arr.length; i++){
text += arr[i] + '.'
}
var log = document.getElementById('log');
var p = document.createElement('p');
log.appendChild(p);
p.innerHTML = '<span>' + text + '</span>';
}
function generateNextSet(set){
for (var i = 0; i < set.length; i++){
var amount = set[i];
if (amount + 1 > limits[i]){
set[i] = 0;
} else {
set[i] = amount + 1;
return set;
}
}
return false;
}
function generateSets(){
var initial_set = [0, 0, 0, 0]
var set = generateNextSet(initial_set);
out(set);
while (set = generateNextSet(set)) {
out(set);
}
};
在文档中添加一个id为“log”的div,然后以某种方式启动 generateSets()方法来检查输出。
答案 1 :(得分:2)
更新:在发布此答案后,我注意到existing answer采用了相同的方法,但我仍然会保留我的,因为它更详细,甚至还有工作代码:)
如果您只有原始项目池中每个项目的一个实例,并且您的项目代表二进制数字;
var items {
1 : 1,
2 : 1,
4 : 1,
8 : 1,
16: 1,
32: 1
};
将问题简化为生成可由这些数字表示的所有数字的序列:
因此,您的问题可以被视为简单地询问可以由 - 而不是二进制 - 而不是mixed-radix数字系统表示的数字序列。
这意味着,您可以为这个奇怪的编号系统编写一个计数器来迭代值0和MAX。因此,当你已经用尽了数字可能带来的所有可能值时,你将从递增最低有效数字开始并转移到更重要的数字。
var items = {
1: 12, // we have 12 x item1
2: 1, // we have 1 x item2
3: 1,
4: 7,
5: 2,
6: 2
};
var counter = {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0
};
function increment(digit) {
if (digit > 6) {
return false;
}
var value = counter[digit] + 1;
if (value > items[digit]) {
counter[digit] = 0;
return increment(digit + 1);
}
counter[digit] = value;
return true;
}
while (increment(1)) {
var set = [];
for (var digit in counter) {
var value = counter[digit];
for (var i = 0; i < value; i++) {
set.push(digit);
}
}
document.write("<div>" + set + "</div>");
}
输出看起来像这样:
1 1,1 1,1,1 ---- snip ---- 2 1,2 1,1,2 ---- big snip ---- 1,1,1,1,1,1,1,1,2,3,4,4,4,4,4,4,4,5,5,6,6 1,1,1,1,1,1,1,1,1,2,3,4,4,4,4,4,4,4,5,5,6,6 1,1,1,1,1,1,1,1,1,1,2,3,4,4,4,4,4,4,4,5,5,6,6 1,1,1,1,1,1,1,1,1,1,1,2,3,4,4,4,4,4,4,4,5,5,6,6 1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,4,4,4,4,4,4,5,5,6,6
答案 2 :(得分:1)
只需进行正常组合。
对于具有数量大于1的n个数字的每个基本集,循环遍历所有数量:[5,6] - &gt; [5,5,6],[5,6,6],[5,5,6,6]。
[]
[1] -> [1,1], [1,1,1] etc
[1,2] -> [1,1,2], ...
[1,3] -> [1,1,3]
[1,4] -> [1,1,4], ...., [1,4,4], -- all combinations of all multi quantity
[2]
[3]
[4] -> [4,4], [4,4,4] etc
[5] -> [5,5]
[6] -> [6,6]
等等...
另一种方法(伪代码):
Combinations: {N -> N} -> [[N]]
Combinations(s) == CombinationsX(s, [])
CombinationsX: {N -> N} X [N] -> [[N]]
Combinationsx(s, g) ==
if s = {} then return []
else
{a -> b} = hd s
ts = tl s
res = Combinationsx(ts, g)
for q in 1..b do
g = g + [a]
res = res ++ Combinationsx(ts, g)
return res
答案 3 :(得分:0)
combination generation的良好资源是Kenneth H. Rosen在Discrete Mathematics and Its Applications中描述的算法。许多问题都可以使用这种通用算法,最好将它放在工具箱中。