将数字分组到大小为 X 的最少数量的存储桶中
Group numbers into least number of buckets of size X
查找有关如何将数字集合分组到大小为 X 的最少数量的存储桶中的示例。
例如,如果我有这个数字数组:
var myCompartments = { 4, 6, 2, 8, 6, 3, 1, 1, 4, 2, 7, 2, 8, 3, 9 };
我想使用以下存储桶大小将它们分组到存储桶中:
var bucketSize = 12;
我正在寻找的是一个函数或算法,它将这些分组到与 bucketSize 匹配的最少数量的存储桶中,然后将剩余的数字(不适合(放在自己的列表中。
我希望看到的示例结果:
var buckets = [
{ 4, 6, 2 },
{ 8, 3, 1 },
{ 6, 4, 2 },
{ 9, 3 }
];
var leftovers = {1, 7, 2, 8 };
如果它可以输出类似于示例结果,那就太好了。"剩余"列表中的项目数量越少越好。
到目前为止,我所拥有的只是循环浏览集合并在有空间的情况下添加到存储桶中,如果没有空间,则创建一个新存储桶。这是低效的,最终会得到很多部分已满的存储桶。我使用的是angularJS,所以这里使用了一些快捷方法:
var bucketSize = 12;
var buckets = [
{ remainingCapacity: bucketSize, items: [] }
];
var myCompartments = [
{ isAssigned: false, size: 4 },
{ isAssigned: false, size: 6 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 8 },
{ isAssigned: false, size: 6 },
{ isAssigned: false, size: 3 },
{ isAssigned: false, size: 1 },
{ isAssigned: false, size: 1 },
{ isAssigned: false, size: 4 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 7 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 8 },
{ isAssigned: false, size: 3 },
{ isAssigned: false, size: 9 }
];
myCompartments.forEach(function(compartment) {
buckets.forEach(function(bucket) {
if (bucket.remainingCapacity >= compartment.size && !compartment.isAssigned) {
bucket.remainingCapacity -= compartment.size;
compartment.isAssigned = true;
bucket.items.push(compartment);
}
});
// if compartment still not assigned, add to a new bucket
if (!compartment.isAssigned && bucketSize >= compartment.size) {
compartment.isAssigned = true;
var remainingCapacity = bucketSize - compartment.size;
var newBucket = { remainingCapacity: remainingCapacity, items: [] };
newBucket.items.push(compartment);
buckets.push(newBucket);
}
});
编辑 - 我创建了一个 plunker,用于输出创建的存储桶进行调试
这并不漂亮,但它有效。
它多次遍历数据,每次都对数组值进行随机排序,以尝试找到将项目分组到特定大小的存储桶中的更好顺序。
普伦克
$(function() {
var bucketSize = 12;
var buckets = [{
remainingCapacity: bucketSize,
pieces: []
}];
var pieces = [
{ isAssigned: false, size: 4 },
{ isAssigned: false, size: 6 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 8 },
{ isAssigned: false, size: 6 },
{ isAssigned: false, size: 3 },
{ isAssigned: false, size: 1 },
{ isAssigned: false, size: 1 },
{ isAssigned: false, size: 4 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 7 },
{ isAssigned: false, size: 2 },
{ isAssigned: false, size: 8 },
{ isAssigned: false, size: 3 },
{ isAssigned: false, size: 9 }
];
var unassignedCount = pieces.length;
var count = 1000;
while (count--) {
shuffle(pieces);
var p = pieces.length;
var b = 0;
while (p--) {
var piece = pieces[p];
b = buckets.length;
while (b--) {
var bucket = buckets[b];
// add to bucket if there is room and piece is not assigned
if (bucket.remainingCapacity >= piece.size && !piece.isAssigned) {
bucket.remainingCapacity -= piece.size;
piece.isAssigned = true;
bucket.pieces.push(piece);
}
}
// if not assigned and not bigger than bucketSize, add to new bucket
if (!piece.isAssigned && piece.size <= bucketSize) {
var remainingCapacity = bucketSize - piece.size;
var newBucket = {
remainingCapacity: remainingCapacity,
pieces: []
};
newBucket.pieces.push(piece);
buckets.push(newBucket);
}
pieces.splice(p, 1);
}
b = buckets.length;
while (b--) {
var bucket = buckets[b];
if (bucket.remainingCapacity > 0) {
p = bucket.pieces.length;
while (p--) {
var piece = bucket.pieces[p];
piece.isAssigned = false;
pieces.push(piece);
bucket.pieces.splice(p, 1);
}
buckets.splice(b, 1);
}
}
unassignedCount = pieces.length;
}
function shuffle(array) {
var currentIndex = array.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
document.write('number of buckets: ' + buckets.length + '<br><br>');
document.write('number of remaining pieces: ' + unassignedCount + '<br> <br>');
buckets.forEach(function(bucket) {
document.write('bucket:<br>');
document.write('remaining capacity: ' + bucket.remainingCapacity + '<br>');
document.write('items:<br>');
bucket.pieces.forEach(function(piece) {
document.write('size: ' + piece.size + '<br>');
});
document.write('<br>');
});
document.write('<br>leftovers: ');
pieces.forEach(function(piece) {
if (!piece.isAssigned) {
document.write(piece.size + ', ');
}
});
});
如果其他人有更优雅的解决方案,我会很想看看你想出了什么! 谢谢。
相关文章:
- 使用全局变量来存储数字(JavaScript)
- 将数字转换为16位浮点(存储为字节)并返回
- 将数字存储在数组中会混淆如何根据值而不是索引来操作这些项目
- 如何查找和替换包含数字的名称并将该数字存储在变量中
- 是否可以在数组中同时存储值的数字和名称
- 在 JavaScript 中将小数字合并为一个是个好主意吗?(作为存储优化解决方案)
- 将数字分组到大小为 X 的最少数量的存储桶中
- 从字符串中提取数字并将其存储在数组Javascript中
- 以何种格式记录/存储数字数据以供进一步的JavaScript处理
- Regex/Javascript函数将价格存储为基于美分的数字
- 生成和存储电子(数字)签名
- 存储和增加数字,即使在刷新页面后
- 不能存储非数字字符
- 使用.replace()在HTML5数据属性上存储jQuery $.data()检索到的数字时未捕获的TypeError
- 将不同的数字存储到数组中
- 如何对本地存储中的嵌套键进行数字排序
- 存储一个随机生成的数字
- Javascript存储一个数字,以便以后与web存储一起使用
- 如何从字符串中提取数字并存储在数组中
- 如何在数组中存储的字符串中查找数字的和