UNPKG

locutus

Version:

Locutus other languages' standard libraries to JavaScript for fun and educational purposes

102 lines (101 loc) 3.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pythonBisect = pythonBisect; exports.pythonBisectLeft = pythonBisectLeft; exports.pythonBisectRight = pythonBisectRight; const _operator_ts_1 = require("./_operator.js"); function pythonBisect(sequence, item, lo, hi) { return bisectCore(sequence, item, lo, hi, 'bisect', 'right'); } function pythonBisectLeft(sequence, item, lo, hi) { return bisectCore(sequence, item, lo, hi, 'bisect_left', 'left'); } function pythonBisectRight(sequence, item, lo, hi) { return bisectCore(sequence, item, lo, hi, 'bisect_right', 'right'); } function bisectCore(sequence, item, lo, hi, functionName, side) { const values = toBisectSequence(sequence, functionName); let left = normalizeLo(lo, functionName); let right = normalizeHi(hi, values.length, functionName); while (left < right) { const middle = Math.floor((left + right) / 2); const candidate = getSequenceItem(values, middle); if (side === 'left' ? pythonLessThan(candidate, item, functionName) : !pythonLessThan(item, candidate, functionName)) { left = middle + 1; } else { right = middle; } } return left; } function toBisectSequence(sequence, functionName) { if (Array.isArray(sequence) || typeof sequence === 'string') { return sequence; } throw new TypeError(`${functionName}() expected an indexable sequence`); } function normalizeLo(value, functionName) { if (value === undefined) { return 0; } const index = toSequenceIndex(value, functionName); if (index < 0) { throw new RangeError('lo must be non-negative'); } return index; } function normalizeHi(value, sequenceLength, functionName) { if (value === undefined || value === null) { return sequenceLength; } return toSequenceIndex(value, functionName); } function toSequenceIndex(value, functionName) { const index = Number((0, _operator_ts_1.toPythonInteger)(value, functionName)); if (!Number.isSafeInteger(index)) { throw new RangeError(`${functionName}() index must fit within JS safe integer precision`); } return index; } function getSequenceItem(sequence, index) { if (index < 0 || index >= sequence.length) { throw new Error(Array.isArray(sequence) ? 'list index out of range' : 'string index out of range'); } return sequence[index]; } function pythonLessThan(left, right, functionName) { if ((0, _operator_ts_1.isNumericLike)(left) && (0, _operator_ts_1.isNumericLike)(right)) { const leftNumber = (0, _operator_ts_1.toPythonNumber)(left, functionName); const rightNumber = (0, _operator_ts_1.toPythonNumber)(right, functionName); if (Number.isNaN(leftNumber) || Number.isNaN(rightNumber)) { return false; } return leftNumber < rightNumber; } if (typeof left === 'string' && typeof right === 'string') { return left < right; } throw new TypeError(`'<' not supported between instances of '${pythonTypeName(left)}' and '${pythonTypeName(right)}'`); } function pythonTypeName(value) { if (typeof value === 'string') { return 'str'; } if (typeof value === 'boolean') { return 'bool'; } if (typeof value === 'bigint' || typeof value === 'number') { return 'int'; } if (Array.isArray(value)) { return 'list'; } if (value === null) { return 'NoneType'; } if (value === undefined) { return 'undefined'; } return typeof value; }