Add min covered

This commit is contained in:
Andras Schmelczer 2025-04-08 22:21:22 +01:00
parent 1bd9331bfa
commit bda5f37385
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
2 changed files with 99 additions and 0 deletions

View file

@ -0,0 +1,48 @@
import { CoveredValues } from "./min-covered";
describe("CoveredValues", () => {
test("should initialize with the given min value", () => {
const covered = new CoveredValues(5);
expect(covered.min).toBe(5);
});
test("should add values greater than min", () => {
const covered = new CoveredValues(0);
covered.add(3);
expect(covered.min).toBe(0);
covered.add(1);
expect(covered.min).toBe(1);
covered.add(4);
expect(covered.min).toBe(1);
covered.add(2);
expect(covered.min).toBe(4);
});
test("should ignore duplicate values", () => {
const covered = new CoveredValues(0);
covered.add(3);
covered.add(3);
covered.add(3);
expect(covered.min).toBe(0);
covered.add(1);
covered.add(2);
expect(covered.min).toBe(3);
});
test("should handle multiple consecutive values", () => {
const covered = new CoveredValues(132);
for (let i = 250; i > 132; i--) {
expect(covered.min).toBe(132);
covered.add(i);
}
expect(covered.min).toBe(250);
});
test("should handle adding values lower than current min", () => {
const covered = new CoveredValues(5);
covered.add(3);
expect(covered.min).toBe(5);
covered.add(6);
expect(covered.min).toBe(6);
});
});

View file

@ -0,0 +1,51 @@
/**
* A class that tracks the minimum covered value in a sequence of numbers.
* It keeps track of a minimum value based on the seen values.
*
* It expects integers slightly out of order and makes sure that the value of `min` is
* always the minimum of the seen values. This is done with bounded memory usage.
*
* @example
* ```typescript
* const covered = new CoveredValues(0);
* covered.add(2); // seenValues = [2], min = 0
* covered.add(1); // seenValues = [], min = 2
* covered.min; // returns 2
* ```
*/
export class CoveredValues {
private seenValues: number[] = [];
public constructor(private minValue: number) {}
public add(value: number): void {
if (value < this.minValue) {
return;
}
let i = 0;
while (i < this.seenValues.length && this.seenValues[i] < value) {
i++;
}
if (i === this.seenValues.length) {
this.seenValues.push(value);
} else if (this.seenValues[i] === value) {
return;
} else {
this.seenValues.splice(i, 0, value);
}
while (
this.seenValues.length > 0 &&
this.seenValues[0] === this.minValue + 1
) {
this.seenValues.shift();
this.minValue++;
}
}
public get min(): number {
return this.minValue;
}
}