serverless-spy
Version:
CDK-based library for writing elegant integration tests on AWS serverless architecture and an additional web console to monitor events in real time.
196 lines (157 loc) • 3.73 kB
JavaScript
/* eslint no-constant-condition: 0 */
/**
* Mnemonist StaticDisjointSet
* ============================
*
* JavaScript implementation of a static disjoint set (union-find).
*
* Note that to remain performant, this implementation needs to know a size
* beforehand.
*/
var helpers = require('./utils/typed-arrays.js');
/**
* StaticDisjointSet.
*
* @constructor
*/
function StaticDisjointSet(size) {
// Optimizing the typed array types
var ParentsTypedArray = helpers.getPointerArray(size),
RanksTypedArray = helpers.getPointerArray(Math.log2(size));
// Properties
this.size = size;
this.dimension = size;
this.parents = new ParentsTypedArray(size);
this.ranks = new RanksTypedArray(size);
// Initializing parents
for (var i = 0; i < size; i++)
this.parents[i] = i;
}
/**
* Method used to find the root of the given item.
*
* @param {number} x - Target item.
* @return {number}
*/
StaticDisjointSet.prototype.find = function(x) {
var y = x;
var c, p;
while (true) {
c = this.parents[y];
if (y === c)
break;
y = c;
}
// Path compression
while (true) {
p = this.parents[x];
if (p === y)
break;
this.parents[x] = y;
x = p;
}
return y;
};
/**
* Method used to perform the union of two items.
*
* @param {number} x - First item.
* @param {number} y - Second item.
* @return {StaticDisjointSet}
*/
StaticDisjointSet.prototype.union = function(x, y) {
var xRoot = this.find(x),
yRoot = this.find(y);
// x and y are already in the same set
if (xRoot === yRoot)
return this;
this.dimension--;
// x and y are not in the same set, we merge them
var xRank = this.ranks[x],
yRank = this.ranks[y];
if (xRank < yRank) {
this.parents[xRoot] = yRoot;
}
else if (xRank > yRank) {
this.parents[yRoot] = xRoot;
}
else {
this.parents[yRoot] = xRoot;
this.ranks[xRoot]++;
}
return this;
};
/**
* Method returning whether two items are connected.
*
* @param {number} x - First item.
* @param {number} y - Second item.
* @return {boolean}
*/
StaticDisjointSet.prototype.connected = function(x, y) {
var xRoot = this.find(x);
return xRoot === this.find(y);
};
/**
* Method returning the set mapping.
*
* @return {TypedArray}
*/
StaticDisjointSet.prototype.mapping = function() {
var MappingClass = helpers.getPointerArray(this.dimension);
var ids = {},
mapping = new MappingClass(this.size),
c = 0;
var r;
for (var i = 0, l = this.parents.length; i < l; i++) {
r = this.find(i);
if (typeof ids[r] === 'undefined') {
mapping[i] = c;
ids[r] = c++;
}
else {
mapping[i] = ids[r];
}
}
return mapping;
};
/**
* Method used to compile the disjoint set into an array of arrays.
*
* @return {array}
*/
StaticDisjointSet.prototype.compile = function() {
var ids = {},
result = new Array(this.dimension),
c = 0;
var r;
for (var i = 0, l = this.parents.length; i < l; i++) {
r = this.find(i);
if (typeof ids[r] === 'undefined') {
result[c] = [i];
ids[r] = c++;
}
else {
result[ids[r]].push(i);
}
}
return result;
};
/**
* Convenience known methods.
*/
StaticDisjointSet.prototype.inspect = function() {
var array = this.compile();
// Trick so that node displays the name of the constructor
Object.defineProperty(array, 'constructor', {
value: StaticDisjointSet,
enumerable: false
});
return array;
};
if (typeof Symbol !== 'undefined')
StaticDisjointSet.prototype[Symbol.for('nodejs.util.inspect.custom')] = StaticDisjointSet.prototype.inspect;
/**
* Exporting.
*/
module.exports = StaticDisjointSet;