fillSpace: improve divisor selection

This commit is contained in:
Peter Fajdiga
2024-10-25 17:06:20 +02:00
parent 685323546a
commit 2cc716f59e
2 changed files with 72 additions and 5 deletions

View File

@@ -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;
}
}

View File

@@ -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) {