"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Deque = void 0; var ArrayContainer_1 = require("../internal/container/linear/ArrayContainer"); var ArrayIterator_1 = require("../internal/iterator/ArrayIterator"); var ArrayReverseIterator_1 = require("../internal/iterator/ArrayReverseIterator"); var NativeArrayIterator_1 = require("../internal/iterator/disposable/NativeArrayIterator"); var Pair_1 = require("../utility/Pair"); var InvalidArgument_1 = require("../exception/InvalidArgument"); var global_1 = require("../iterator/global"); var ErrorGenerator_1 = require("../internal/exception/ErrorGenerator"); /** * Double ended queue. * * @author Jeongho Nam - https://github.com/samchon */ var Deque = /** @class */ (function (_super) { __extends(Deque, _super); function Deque() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var _this = _super.call(this) || this; // CONSTRUCTORS BRANCH if (args.length === 0) { _this.clear(); } if (args.length === 1 && args[0] instanceof Array) { // INITIALIZER CONSTRUCTOR var array = args[0]; var first = new NativeArrayIterator_1.NativeArrayIterator(array, 0); var last = new NativeArrayIterator_1.NativeArrayIterator(array, array.length); _this.assign(first, last); } else if (args.length === 1 && args[0] instanceof Deque) { // COPY CONSTRUCTOR var container = args[0]; _this.assign(container.begin(), container.end()); } else if (args.length === 2) { // ASSIGN CONSTRUCTOR _this.assign(args[0], args[1]); } return _this; } Deque.prototype.assign = function (first, second) { // CLEAR PREVIOUS CONTENTS this.clear(); // INSERT ITEMS this.insert(this.end(), first, second); }; /** * @inheritDoc */ Deque.prototype.clear = function () { // CLEAR CONTENTS this.matrix_ = [[]]; // RE-INDEX this.size_ = 0; this.capacity_ = Deque.MIN_CAPACITY; }; /** * @inheritDoc */ Deque.prototype.resize = function (n) { n = Deque._Emend(n, "resize"); var expansion = n - this.size(); if (expansion > 0) this.insert(this.end(), expansion, undefined); else if (expansion < 0) this.erase(this.end().advance(-expansion), this.end()); }; /** * Reserve {@link capacity} enable to store *n* elements. * * @param n The capacity to reserve. */ Deque.prototype.reserve = function (n) { this._Reserve(Deque._Emend(n, "reserve")); }; Deque.prototype._Reserve = function (n) { // NEW MEMBERS TO BE ASSSIGNED var matrix = [[]]; var length = this._Compute_col_size(n); //-------- // RE-FILL //-------- for (var r = 0; r < this.matrix_.length; ++r) { var row = this.matrix_[r]; for (var c = 0; c < row.length; ++c) { var new_row = matrix[matrix.length - 1]; if (matrix.length < Deque.ROW_SIZE && new_row.length === length) { new_row = []; matrix.push(new_row); } new_row.push(row[c]); } } // ASSIGN MEMBERS this.matrix_ = matrix; this.capacity_ = n; }; /** * Shrink {@link capacity} to actual {@link size}. */ Deque.prototype.shrink_to_fit = function () { this._Reserve(this.size()); }; /** * @inheritDoc */ Deque.prototype.swap = function (obj) { this._Swap(obj); }; Deque.prototype._Swap = function (obj) { var _a, _b, _c; // SWAP CONTENTS _a = __read([obj.matrix_, this.matrix_], 2), this.matrix_ = _a[0], obj.matrix_ = _a[1]; _b = __read([obj.size_, this.size_], 2), this.size_ = _b[0], obj.size_ = _b[1]; _c = __read([obj.capacity_, this.capacity_], 2), this.capacity_ = _c[0], obj.capacity_ = _c[1]; }; Deque._Emend = function (n, method) { n = Math.floor(n); if (n <= 0) throw new InvalidArgument_1.InvalidArgument("Error on Deque.".concat(method, "(): n must be positive integer -> (n = ").concat(n, ")")); return n; }; /* ========================================================= ACCESSORS - BASIC ELEMENTS - INDEX ACCESSORS ============================================================ BASIC ELEMENTS --------------------------------------------------------- */ /** * @inheritDoc */ Deque.prototype.size = function () { return this.size_; }; /** * The capacity to store elements. * * @return The capacity. */ Deque.prototype.capacity = function () { return this.capacity_; }; /** * @inheritDoc */ Deque.prototype.nth = function (index) { return new Deque.Iterator(this, index); }; /** * @inheritDoc */ Deque.prototype[Symbol.iterator] = function () { return new Deque.ForOfAdaptor(this.matrix_); }; Deque.prototype.source = function () { return this; }; /* --------------------------------------------------------- INDEX ACCESSORS --------------------------------------------------------- */ Deque.prototype._At = function (index) { var indexPair = this._Fetch_index(index); return this.matrix_[indexPair.first][indexPair.second]; }; Deque.prototype._Set = function (index, val) { var indexPair = this._Fetch_index(index); this.matrix_[indexPair.first][indexPair.second] = val; }; Deque.prototype._Fetch_index = function (index) { // Fetch row and column's index. var row; for (row = 0; row < this.matrix_.length; row++) { var array = this.matrix_[row]; if (index < array.length) break; index -= array.length; } if (row === this.matrix_.length) row--; return new Pair_1.Pair(row, index); }; Deque.prototype._Compute_col_size = function (capacity) { if (capacity === void 0) { capacity = this.capacity_; } // Get column size; {@link capacity_ capacity} / {@link ROW_SIZE row}. return Math.floor(capacity / Deque.ROW_SIZE); }; /* ========================================================= ELEMENTS I/O - PUSH & POP - INSERT - ERASE ============================================================ PUSH & POP --------------------------------------------------------- */ /** * @inheritDoc */ Deque.prototype.push = function () { var items = []; for (var _i = 0; _i < arguments.length; _i++) { items[_i] = arguments[_i]; } if (items.length === 0) return this.size(); // INSERT BY RANGE var first = new NativeArrayIterator_1.NativeArrayIterator(items, 0); var last = new NativeArrayIterator_1.NativeArrayIterator(items, items.length); this._Insert_by_range(this.end(), first, last); // RETURN SIZE return this.size(); }; /** * @inheritDoc */ Deque.prototype.push_front = function (val) { // ADD CAPACITY & ROW this._Try_expand_capacity(this.size_ + 1); this._Try_add_row_at_front(); // INSERT VALUE this.matrix_[0].unshift(val); ++this.size_; }; /** * @inheritDoc */ Deque.prototype.push_back = function (val) { // ADD CAPACITY & ROW this._Try_expand_capacity(this.size_ + 1); this._Try_add_row_at_back(); // INSERT VALUE this.matrix_[this.matrix_.length - 1].push(val); ++this.size_; }; /** * @inheritDoc */ Deque.prototype.pop_front = function () { if (this.empty() === true) throw ErrorGenerator_1.ErrorGenerator.empty(this.constructor, "pop_front"); // EREASE FIRST ELEMENT this.matrix_[0].shift(); if (this.matrix_[0].length === 0 && this.matrix_.length > 1) this.matrix_.shift(); // SHRINK SIZE this.size_--; }; Deque.prototype._Pop_back = function () { // ERASE LAST ELEMENT var lastArray = this.matrix_[this.matrix_.length - 1]; lastArray.pop(); if (lastArray.length === 0 && this.matrix_.length > 1) this.matrix_.pop(); // SHRINK SIZE this.size_--; }; /* --------------------------------------------------------- INSERT --------------------------------------------------------- */ Deque.prototype._Insert_by_range = function (pos, first, last) { var size = this.size_ + (0, global_1.distance)(first, last); if (size === this.size_) // FIRST === LAST return pos; if (pos.equals(this.end()) === true) { // EXPAND CAPACITY IF REQUIRED this._Try_expand_capacity(size); // INSERT TO END this._Insert_to_end(first, last); // CHANGE POS TO RETURN pos = this.nth(this.size_); } else { // INSERT ITEMS IN THE MIDDLE if (size > this.capacity_) { // A TEMPORARY DEQUE var deque = new Deque(); deque._Reserve(Math.max(size, Math.floor(this.capacity_ * Deque.MAGNIFIER))); // INSERT ITEM SEQUENTIALLY deque._Insert_to_end(this.begin(), pos); deque._Insert_to_end(first, last); deque._Insert_to_end(pos, this.end()); // AND SWAP THIS WITH THE TEMP this._Swap(deque); } else this._Insert_to_middle(pos, first, last); } this.size_ = size; return pos; }; Deque.prototype._Insert_to_middle = function (pos, first, last) { var _a, _b; var col_size = this._Compute_col_size(); // POSITION OF MATRIX var indexes = this._Fetch_index(pos.index()); var row = this.matrix_[indexes.first]; var col = indexes.second; // MOVE BACK SIDE TO TEMPORARY ARRAY var back_items = row.splice(col); // INSERT ITEMS for (; !first.equals(last); first = first.next()) { if (row.length === col_size && this.matrix_.length < Deque.ROW_SIZE) { row = new Array(); var spliced_array = this.matrix_.splice(++indexes.first); this.matrix_.push(row); (_a = this.matrix_).push.apply(_a, __spreadArray([], __read(spliced_array), false)); } row.push(first.value); } // INSERT ITEMS IN THE BACK SIDE for (var i = 0; i < back_items.length; ++i) { if (row.length === col_size && this.matrix_.length < Deque.ROW_SIZE) { row = new Array(); var spliced_array = this.matrix_.splice(++indexes.first); this.matrix_.push(row); (_b = this.matrix_).push.apply(_b, __spreadArray([], __read(spliced_array), false)); } row.push(back_items[i]); } }; Deque.prototype._Insert_to_end = function (first, last) { // INSERT ITEMS IN THE BACK for (; !first.equals(last); first = first.next()) { // ADD ROW IF REQUIRED this._Try_add_row_at_back(); // INSERT VALUE this.matrix_[this.matrix_.length - 1].push(first.value); } }; Deque.prototype._Try_expand_capacity = function (size) { if (size <= this.capacity_) return false; // MAX (CAPACITY * 1.5, TARGET SIZE) size = Math.max(size, Math.floor(this.capacity_ * Deque.MAGNIFIER)); this._Reserve(size); return true; }; Deque.prototype._Try_add_row_at_front = function () { var _a; var col_size = this._Compute_col_size(); if (this.matrix_[0].length >= col_size && this.matrix_.length < Deque.ROW_SIZE) { this.matrix_ = (_a = [[]]).concat.apply(_a, __spreadArray([], __read(this.matrix_), false)); return true; } else return false; }; Deque.prototype._Try_add_row_at_back = function () { var col_size = this._Compute_col_size(); if (this.matrix_[this.matrix_.length - 1].length >= col_size && this.matrix_.length < Deque.ROW_SIZE) { this.matrix_.push([]); return true; } else return false; }; /* --------------------------------------------------------- ERASE --------------------------------------------------------- */ Deque.prototype._Erase_by_range = function (first, last) { if (first.index() >= this.size()) return first; // INDEXING var size; if (last.index() >= this.size()) // LAST IS END() size = this.size() - first.index(); // LAST IS NOT END() else size = last.index() - first.index(); this.size_ -= size; // ERASING var first_row = null; var second_row = null; var i = 0; while (size !== 0) { // FIND MATCHED ROW AND COLUMN var indexes = this._Fetch_index(first.index()); var row = this.matrix_[indexes.first]; var col = indexes.second; // EARSE FROM THE ROW var my_delete_size = Math.min(size, row.length - col); row.splice(col, my_delete_size); // TO MERGE if (row.length !== 0) if (i === 0) first_row = row; else second_row = row; // ERASE THE ENTIRE ROW IF REQUIRED if (row.length === 0 && this.matrix_.length > 1) this.matrix_.splice(indexes.first, 1); // TO THE NEXT STEP size -= my_delete_size; ++i; } // MERGE FIRST AND SECOND ROW if (first_row !== null && second_row !== null && first_row.length + second_row.length <= this._Compute_col_size()) { first_row.push.apply(first_row, __spreadArray([], __read(second_row), false)); this.matrix_.splice(this.matrix_.indexOf(second_row), 1); } return first; }; return Deque; }(ArrayContainer_1.ArrayContainer)); exports.Deque = Deque; /** * */ (function (Deque) { // BODY Deque.Iterator = ArrayIterator_1.ArrayIterator; Deque.ReverseIterator = ArrayReverseIterator_1.ArrayReverseIterator; //---- // CONSTANTS //---- /** * Row size of the {@link Deque.matrix_ matrix} which contains elements. * * Note that the {@link ROW_SIZE} affects on time complexity of accessing and inserting element. * Accessing element is {@link ROW_SIZE} times slower than ordinary {@link Vector} and inserting element * in middle position is {@link ROW_SIZE} times faster than ordinary {@link Vector}. * * When the {@link ROW_SIZE} returns 8, time complexity of accessing element is O(8) and inserting * element in middle position is O(N/8). ({@link Vector}'s time complexity of accessement is O(1) * and inserting element is O(N)). */ Deque.ROW_SIZE = 8; /** * Minimum {@link Deque.capacity}. * * Although a {@link Deque} has few elements, even no element is belonged to, the {@link Deque} * keeps the minimum {@link Deque.capacity} at least. */ Deque.MIN_CAPACITY = 36; /** * Expansion ratio. */ Deque.MAGNIFIER = 1.5; /** * @internal */ var ForOfAdaptor = /** @class */ (function () { function ForOfAdaptor(matrix) { this.matrix_ = matrix; this.row_ = 0; this.col_ = 0; } ForOfAdaptor.prototype.next = function () { if (this.row_ === this.matrix_.length) return { done: true, value: undefined, }; else { var val = this.matrix_[this.row_][this.col_]; if (++this.col_ === this.matrix_[this.row_].length) { ++this.row_; this.col_ = 0; } return { done: false, value: val, }; } }; ForOfAdaptor.prototype[Symbol.iterator] = function () { return this; }; return ForOfAdaptor; }()); Deque.ForOfAdaptor = ForOfAdaptor; })(Deque = exports.Deque || (exports.Deque = {})); exports.Deque = Deque; //# sourceMappingURL=Deque.js.map