Skip to content

Instantly share code, notes, and snippets.

@DenisVerkhoturov
Last active October 24, 2019 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DenisVerkhoturov/b64c791b4393e8f8a3b06d050c1640d8 to your computer and use it in GitHub Desktop.
Save DenisVerkhoturov/b64c791b4393e8f8a3b06d050c1640d8 to your computer and use it in GitHub Desktop.
import _ from 'lodash';
_.mixin({
splitOn: (array, needSplit) => {
function splitting(chunks, current) {
const [init, last] = [_.initial(chunks) || [], _.last(chunks) || []];
const previous = _.last(last);
return needSplit(current, previous) ? [ ...chunks, [current] ] : [ ...init, [ ...last, current ] ];
}
return _.isEmpty(array) ? [] : _.reduce(_.tail(array), splitting, [ [ _.first(array) ] ]);
}
});
export function distribute(points, locator) {
function spread(clump) {
const size = _.sumBy(clump, 'size');
const middle = (_.first(clump)[locator] + _.last(clump)[locator]) / 2;
const locating = ({ distributed, edge }, item) => ({
distributed: [...distributed, { ...item, [locator]: edge + item.size / 2} ],
edge: edge + item.size
});
const { distributed } = _.reduce(clump, locating, { distributed: [], edge: middle - size / 2 });
return { items: distributed, size, [locator]: middle };
}
function iterate(clumps) {
const needsRedistribution = _.some(clumps, clump => clump.length > 1);
return needsRedistribution ? iterate(_.map(clumps, spread)) : _.chain(clumps).map('items').flatten().value();
}
const hasSpareSpace = (left, right) => (left[locator] - left.size / 2) - (right[locator] + right.size / 2) >= 0;
const clumps = _.chain(points).sortBy(locator).splitOn(hasSpareSpace).map(spread).value();
return iterate(clumps);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment