UNPKG

typescript-algorithms-and-datastructures

Version:
184 lines 7.34 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class BitMatrix { constructor(rowSize, colSize) { this.rowCount = 0; this.colCount = 0; this.rowCount = rowSize; this.colCount = colSize; this.buffer = new Uint32Array(this.calculateBufferSize(this.colCount * this.rowCount)); } clone() { const clone = new BitMatrix(this.rowCount, this.colCount); clone.setBuffer(this.buffer.slice(0)); return clone; } count() { return this.buffer.reduce((total, chunk) => this.bitsCountInNumber(chunk) + total, 0); } get(rowIndex, colIndex) { this.validateIndex(rowIndex, colIndex); const index = this.getBitPosition(rowIndex, colIndex); const chunkOffset = Math.floor(index / 32); const bitOffset = index - chunkOffset * 32; return !!(this.buffer[chunkOffset] & (1 << bitOffset)); } getColIndexes(column) { const output = []; for (let i = 0; i < this.rowCount; i++) { if (this.get(i, column)) { output.push(i); } } return output; } getRowIndexes(row) { const output = []; for (let i = 0; i < this.colCount; i++) { if (this.get(row, i)) { output.push(i); } } return output; } getIndexes(resultPerColumn = false) { let result = []; let index = 0; if (resultPerColumn) { while (index < this.colCount) { result.push(this.getColIndexes(index)); index++; } } else { while (index < this.rowCount) { result.push(this.getRowIndexes(index)); index++; } } return result; } reset() { this.buffer.fill(0); return this; } resize(rowCount, colCount) { if (rowCount < 0 || colCount < 0) { throw new RangeError(`Invalid new BitMatrix size ${rowCount}x${colCount}`); } const setIndexes = this.getIndexes(); this.buffer = new Uint32Array(this.calculateBufferSize(rowCount * colCount)); this.rowCount = rowCount; this.colCount = colCount; setIndexes.filter((setIndexes, row) => row < rowCount) .forEach((setIndexes, row) => { setIndexes.forEach(column => { if (column < this.colCount) { this.set(row, column, true); } }); }); return this; } setBuffer(newBuffer) { if (!newBuffer || newBuffer.length !== this.buffer.length) { throw new Error(`Invalid buffer ${newBuffer}`); } this.buffer = newBuffer; return this; } size() { return [this.rowCount, this.colCount]; } spliceColumn(startIndex, deleteCount) { if (isNaN(deleteCount) || deleteCount < 1) { return; } if (startIndex < 0) { startIndex = this.colCount + startIndex; if (startIndex < 0) { throw new RangeError(`${startIndex} is less than 0`); } } else if (startIndex >= this.colCount) { throw new RangeError(`${startIndex} exceeds the matrix size ${this.colCount}`); } const tempBuffer = this.getIndexes(); this.reset(); this.resize(this.rowCount, this.colCount - deleteCount); tempBuffer.forEach((indexes, row) => { indexes.forEach(id => { if (id < startIndex || id >= startIndex + deleteCount) { let normalizedId = id >= startIndex + deleteCount ? id - deleteCount : id; this.set(row, normalizedId, true); } }); }); } spliceRow(startIndex, deleteCount) { if (isNaN(deleteCount) || deleteCount < 1) { return; } if (startIndex < 0) { startIndex = this.colCount + startIndex; if (startIndex < 0) { throw new RangeError(`${startIndex} is less than 0`); } } else if (startIndex >= this.colCount) { throw new RangeError(`${startIndex} exceeds the matrix size ${this.colCount}`); } const tempBuffer = this.getIndexes().filter((setIds, row) => row < startIndex || row >= startIndex + deleteCount); this.reset(); this.resize(this.rowCount - deleteCount, this.colCount); tempBuffer.forEach((indexes, row) => { indexes.forEach(id => { this.set(row, id, true); }); }); } set(rowIndex, colIndex, value) { this.validateIndex(rowIndex, colIndex); const index = this.getBitPosition(rowIndex, colIndex); const chunkOffset = Math.floor(index / 32); const offset = index - chunkOffset * 32; if (value) { this.buffer[chunkOffset] |= (1 << offset); } else { this.buffer[chunkOffset] &= ~(1 << offset); } return this; } calculateBufferSize(bitsCount) { return Math.ceil(bitsCount / 32) * 4; } getBitPosition(rowIndex, colIndex) { return this.colCount * rowIndex + colIndex; } bitsCountInNumber(value) { value -= ((value >>> 1) & 0x55555555); value = (value & 0x33333333) + ((value >>> 2) & 0x33333333); return (((value + (value >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24); } validateIndex(rowIndex, colIndex) { if (rowIndex >= this.rowCount || rowIndex < 0) { throw new RangeError(`Row index is incorrect. Maximum allowed index: ${this.rowCount - 1}. Actual index ${rowIndex}`); } if (colIndex >= this.colCount || colIndex < 0) { throw new RangeError(`Column index is incorrect. Maximum allowed index: ${this.colCount - 1}. Actual index ${colIndex}`); } } } exports.BitMatrix = BitMatrix; }); //# sourceMappingURL=BitMatrix.js.map