| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- 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];
- }
- }
|