export class OrderedNumbers { constructor(private numbers: number[] = [], private readonly unique = true) { if (!this.isValid) { this.sort(); if (this.unique) { this.makeUnique(); } } } private get isValid(): boolean { for (const [index, number] of this.numbers.entries()) { if (index > 0 && number < this.numbers[index - 1]) { return false; } } return this.isUnique; } private sort(): number[] { return this.numbers.sort((a, b) => a - b); } private static filterUnique( value: number, index: number, numbers: number[], ): boolean { return numbers.indexOf(value) === index; } private get isUnique(): boolean { return this.numbers.filter(OrderedNumbers.filterUnique).length === this.numbers.length; } private makeUnique(): number[] { this.numbers = this.numbers.filter(OrderedNumbers.filterUnique); return this.numbers; } public get list(): number[] { return this.numbers; } public get max(): number { return this.numbers.slice(-1)[0]; } public contains(number: number): boolean { return this.numbers.indexOf(number) !== -1; } public add(number: number): number[] { if (this.unique && this.contains(number)) { return this.list; } const max = this.max; this.numbers.push(number); if (max < number) { return this.list; } this.sort(); return this.list; } public remove(number: number): number[] { if (!this.contains(number)) { return this.list; } this.numbers = this.list.filter((n) => n !== number); return this.numbers; } public findNextLargerValue( number: number, fromIndex = 0, toIndex = this.numbers.length, ): number | undefined { if (this.list.length === 0) { return undefined; } if (number > this.max) { return undefined; } if (number < this.numbers[0]) { return this.numbers[0]; } if (this.contains(number)) { return this.numbers[this.numbers.indexOf(number) + 1]; } const length = toIndex - fromIndex; if (length > 1) { const middle = fromIndex + Math.floor(length / 2); return this.numbers[middle] > number ? this.findNextLargerValue(number, fromIndex, middle) : this.findNextLargerValue(number, middle + 1, toIndex); } return this.numbers[fromIndex] > number ? this.numbers[fromIndex] : this.numbers[fromIndex + 1]; } }