feat: experiment with different implementations of LSEQ
This commit is contained in:
commit
1e45ef9314
23 changed files with 3578 additions and 0 deletions
72
typescript/src/index.ts
Normal file
72
typescript/src/index.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
const ALPHABET =
|
||||
"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
function idToNumbers(id: string): number[] {
|
||||
const nums = id.split("").map((char) => ALPHABET.indexOf(char));
|
||||
return nums;
|
||||
}
|
||||
|
||||
type Maybe<T> = T | null;
|
||||
|
||||
function isNone<T>(value: Maybe<T>): value is null {
|
||||
return value === null;
|
||||
}
|
||||
|
||||
export class LSEQ {
|
||||
// true = allocate near min, false = allocate near max
|
||||
private strategies: boolean[];
|
||||
private random: () => number;
|
||||
|
||||
constructor(random: () => number = Math.random) {
|
||||
this.random = random;
|
||||
this.strategies = [random() < 0.5];
|
||||
}
|
||||
|
||||
public alloc(before: Maybe<string>, after: Maybe<string>): string {
|
||||
// Convert to numeric arrays, using boundary values for null
|
||||
const p = isNone(before) ? [0] : idToNumbers(before);
|
||||
const q = isNone(after) ? [63] : idToNumbers(after);
|
||||
|
||||
// Walk through digits looking for space
|
||||
let depth = 0;
|
||||
const result = [];
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const pVal = depth < p.length ? p[depth] : 0;
|
||||
const qVal = depth < q.length ? q[depth] : 63;
|
||||
|
||||
const interval = qVal - pVal;
|
||||
|
||||
// If we have space between values at this depth
|
||||
if (interval > 1) {
|
||||
// Pick a value in the available range
|
||||
const range = interval - 1;
|
||||
const addVal = 1 + Math.floor(this.random() * range);
|
||||
let newValue;
|
||||
if (this.strategies[depth]) {
|
||||
newValue = pVal + addVal;
|
||||
} else {
|
||||
newValue = qVal - addVal;
|
||||
}
|
||||
|
||||
// Take the prefix from p up to depth and append our new value
|
||||
result.push(newValue);
|
||||
|
||||
return result.map((n) => ALPHABET[n]).join("");
|
||||
}
|
||||
result.push(pVal);
|
||||
|
||||
// If values are the same or adjacent at this depth,
|
||||
// continue to next depth
|
||||
depth++;
|
||||
if (depth > this.strategies.length) {
|
||||
this.strategies.push(this.random() < 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function compareLSEQ(a: string, b: string): number {
|
||||
if (a === b) return 0;
|
||||
return a < b ? -1 : 1;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue