fillSpace: improve divisor selection
This commit is contained in:
@@ -5,23 +5,19 @@ function fillSpace(availableSpace: number, items: { min: number, max: number }[]
|
||||
|
||||
function findMeanSpaceFiller(availableSpace: number, items: { min: number, max: number }[]) {
|
||||
let mean = Math.floor(availableSpace / items.length);
|
||||
while (true) {
|
||||
for (let i = 0; true; i++) {
|
||||
let requiredSpace = 0;
|
||||
let increasable = 0;
|
||||
let decreasable = 0;
|
||||
let low = -Infinity;
|
||||
let high = Infinity;
|
||||
for (const item of items) {
|
||||
const size = clamp(mean, item.min, item.max);
|
||||
requiredSpace += size;
|
||||
if (mean > item.min) {
|
||||
decreasable++;
|
||||
if (size > low) {
|
||||
low = size;
|
||||
}
|
||||
}
|
||||
if (mean < item.max) {
|
||||
increasable++;
|
||||
if (size < high) {
|
||||
high = size;
|
||||
}
|
||||
@@ -32,17 +28,30 @@ function findMeanSpaceFiller(availableSpace: number, items: { min: number, max:
|
||||
const error = requiredSpace - availableSpace;
|
||||
if (error > 0) {
|
||||
// need to decrease mean
|
||||
let decreasable = 0;
|
||||
for (const item of items) {
|
||||
if (mean > item.min && low - error < item.max) {
|
||||
decreasable++;
|
||||
}
|
||||
}
|
||||
if (decreasable > 0) {
|
||||
mean = Math.floor(low - error / decreasable);
|
||||
}
|
||||
} else if (error < 0) {
|
||||
// need to increase mean
|
||||
let increasable = 0;
|
||||
for (const item of items) {
|
||||
if (mean < item.max && high - error > item.min) {
|
||||
increasable++;
|
||||
}
|
||||
}
|
||||
if (increasable > 0) {
|
||||
mean = Math.floor(high - error / increasable);
|
||||
}
|
||||
}
|
||||
|
||||
if (mean === oldMean) {
|
||||
log(`findMeanSpaceFiller ${i} / ${items.length}`);
|
||||
return mean;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,64 @@ tests.register("fillSpace", 1, () => {
|
||||
],
|
||||
expected: [114, 93, 93, 93, 93, 93, 110, 110],
|
||||
},
|
||||
{
|
||||
availableSpace: 801,
|
||||
items: [
|
||||
{ min: 114, max: 800 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 109, max: 800 },
|
||||
{ min: 10, max: 800 },
|
||||
],
|
||||
expected: [114, 93, 93, 93, 93, 93, 111, 111],
|
||||
},
|
||||
{
|
||||
availableSpace: 1029,
|
||||
items: [
|
||||
{ min: 114, max: 800 },
|
||||
{ min: 114, max: 800 },
|
||||
{ min: 114, max: 800 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 10, max: 93 },
|
||||
{ min: 109, max: 800 },
|
||||
{ min: 10, max: 800 },
|
||||
],
|
||||
expected: [114, 114, 114, 93, 93, 93, 93, 93, 111, 111],
|
||||
},
|
||||
{
|
||||
availableSpace: 602,
|
||||
items: [
|
||||
{ min: 10, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
],
|
||||
expected: [200, 200, 200],
|
||||
},
|
||||
{
|
||||
availableSpace: 602,
|
||||
items: [
|
||||
{ min: 204, max: 600 },
|
||||
{ min: 202, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
],
|
||||
expected: [204, 202, 196],
|
||||
},
|
||||
{
|
||||
availableSpace: 803,
|
||||
items: [
|
||||
{ min: 204, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
{ min: 10, max: 600 },
|
||||
],
|
||||
expected: [204, 199, 199, 199],
|
||||
},
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
|
||||
Reference in New Issue
Block a user