From 2cc716f59e951549f73976b58a0d1015bd0863f2 Mon Sep 17 00:00:00 2001 From: Peter Fajdiga Date: Fri, 25 Oct 2024 17:06:20 +0200 Subject: [PATCH] fillSpace: improve divisor selection --- src/lib/utils/fillSpace.ts | 19 +++++++--- src/tests/units/utils/fillSpace.ts | 58 ++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/lib/utils/fillSpace.ts b/src/lib/utils/fillSpace.ts index 3c72e3f..bf0be42 100644 --- a/src/lib/utils/fillSpace.ts +++ b/src/lib/utils/fillSpace.ts @@ -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; } } diff --git a/src/tests/units/utils/fillSpace.ts b/src/tests/units/utils/fillSpace.ts index 50c9f91..fec54dc 100644 --- a/src/tests/units/utils/fillSpace.ts +++ b/src/tests/units/utils/fillSpace.ts @@ -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) {