Here is a recursive algorithm in Javascript. This function returns the totals that each worker will be assigned. Lets say the input array bookLoads is an array of positive numbers that you want to divide as fairly as possible into k-parts (let's say among k workers)
Here is a working fiddle:
https://jsfiddle.net/missyalyssi/jhtk8vnc/3/
function fairWork(bookLoads, numWorkers = 0) {
// recursive version
// utilities
var bestDifference = Infinity;
var bestPartition = {};
var initLoads = {};
var workers = Array.from({length: numWorkers}, (val, idx) => {
initLoads[idx] = 0;
return idx;
});
var bookTotal = bookLoads.reduce((acc, curr) => {return acc + curr}, 0);
var average = bookTotal / bookLoads.length;
// recursive function
function partition(books = bookLoads, workers, loads={}) {
// if only one worker give them all the books
if (workers.length == 1 && books.length > 0) {
var onlyWorker = workers[0];
loads[onlyWorker] += books.reduce((acum, curr, idx, arr) => {
return acum + curr;
},0);
books = [];
}
// base case
if (books.length == 0) {
var keys = Object.keys(loads);
var total = 0;
for (let key = 0; key < keys.length; key++) {
// square so that difference shows
total += Math.pow(Math.abs(average - loads[keys[key]]), 2);
}
if (total < bestDifference) {
bestDifference = total;
bestPartition= loads;
}
return bestPartition;
}
var currBookLoad = books[0];
// add book to curr worker 1
var newWorker1Loads = Object.assign({}, loads);
var worker1 = workers[0];
newWorker1Loads[worker1] = newWorker1Loads[worker1] + currBookLoad || currBookLoad;
partition(books.slice(1), workers, newWorker1Loads)
// give to next worker
var newNextWorkerLoads = Object.assign({}, loads);
var worker2 = workers[1];
newNextWorkerLoads[worker2] = newNextWorkerLoads[worker2] + currBookLoad || currBookLoad;
partition(books.slice(1), workers.slice(1), newNextWorkerLoads)
return bestPartition;
}
// function call
return partition(bookLoads, workers, initLoads)
}
fairWork([3,1,2,3], 3)
//Result will be: Object {0: 3, 1: 3, 2: 3}
fairWork([1,2,3,4,5,6,7,8,9], 3)
//Result will be: Object {0: 15, 1: 13, 2: 17}