Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Last active September 5, 2019 22:13
Show Gist options
  • Save dfkaye/29e28a2a1005704e59467417432203b3 to your computer and use it in GitHub Desktop.
Save dfkaye/29e28a2a1005704e59467417432203b3 to your computer and use it in GitHub Desktop.
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
// This version, 5 Sept 2019
// First version, 18 Dec 2018
// See original Math Problem gist by @tevko
// https://gist.github.com/tevko/20f8fc446d219f4714517aab19c5dd71
// See postscript at the end of this gist for next thoughts...
// Set up our constraints first.
var count = 8;
var mintime = 45;
var budget = 600;
var remainder = budget;
/*
* First we have to allocate every task at least one pass, the minimum runtime
* and decrement that amount from the remainder.
*/
var tasks = Array(count).fill(0).map(function(v, i) {
// decrement step
remainder -= mintime;
// allocation step
return { name: 'task_' + i, runtime: mintime };
});
// Verify that our remainder is correct
// 600 - (8 * 45)
// 600 - 360
// Should be 240.
console.log({ remainder, passing: remainder === 240 });
function getRandomIntInclusive(min, max) {
// The maximum is inclusive and the minimum is inclusive.
return Math.ceil(Math.random() * (max - min + 1) + 1);
}
// Procedural looping part.
var i = 0;
/*
* While there is time remaining to allocate, keep iterating the tasks, adding
* more time to each runtime.
* When the index reaches the number of tasks, reset it to 0 and start over.
* Stop iterating when remaining time is less than 1 second.
*/
while (remainder > 0) {
if (i == count) {
i = 0;
}
var task = tasks[i++];
var time = getRandomIntInclusive(task.runtime, remainder);
if (time > 0) {
/*
* Two reasons for this check:
*
* 1. The randomizing function can return a negative value once the
* remainder is sufficiently small. Subtracting negative time from
* the remainder increases it, resulting in an infinite loop.
*
* 2. If no positive time is returned, might as well skip to the next
* task rather than "perfecting" the current task.
*/
console.log({ time, remainder });
/*
* Increase the current task's runtime and decrement the remaining time to
* be allocated.
*/
task.runtime += time;
remainder -= time;
if (remainder < 1) {
break;
}
}
}
// How'd we do?
var total = tasks.reduce(function(total, task) {
console.log(task);
return total + task.runtime;
}, 0);
console.log({ total });
// Sample run.
/*
{ name: "task_0", runtime: 178 }
{ name: "task_1", runtime: 111 }
{ name: "task_2", runtime: 57 }
{ name: "task_3", runtime: 52 }
{ name: "task_4", runtime: 49 }
{ name: "task_5", runtime: 49 }
{ name: "task_6", runtime: 50 }
{ name: "task_7", runtime: 54 }
{ total: 600 }
*/
/*
* Concluding Unscientific Postscript:
*
* I'm not sure the times are efficiently allocated. Given 2 more seconds, for
* example, in this test the first task could be run 4 times. As it is, there is
* a potential unusable allocation of 43 seconds that could applied to other
* tasks.
*
* On the other hand, we have no guarantee of task completion given even the 45-
* second minimum runtime. If we had a tolerance value for each task, say, task
* 0 takes no longer than 50 seconds, task 1 takes no longer than 100 seconds,
* etc., the tolerance ranges are 5 and 55 seconds, respectively. Knwoing *any*
* of those, we could reallocate runtime deltas more effectively.
*/
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment