diff --git a/utils/javascript/SortedList.mjs b/utils/javascript/SortedList.mjs new file mode 100644 index 0000000..84985d0 --- /dev/null +++ b/utils/javascript/SortedList.mjs @@ -0,0 +1,65 @@ +export class SortedList { + + #data = []; + + add(value) { + + // Simple cases that we can short-circuit on + if (this.#data.length === 0 || this.#data.at(-1) < value) { + this.#data.push(value); + return; + }; + if (this.#data.at(0) > value) { + this.#data.unshift(value); + return + }; + + let locationToAdd; + let lStart = 0; + let lEnd = this.#data.length; + do { + let midpoint = Math.floor((lStart + lEnd) / 2); + + if (lStart > lEnd) { + // console.log(`breaking for ${value} at lStart=${lStart}, lEnd=${lEnd}`) + locationToAdd = lStart; + break + }; + + let valAtMidpoint =this.#data.at(midpoint); + if (valAtMidpoint < value) { + // console.log(`${valAtMidpoint} < ${value}, using second half of list`) + lStart = midpoint + 1; + } + else if (valAtMidpoint > value) { + // console.log(`${valAtMidpoint} > ${value}, using first half of list`) + lEnd = midpoint - 1; + } + else { + locationToAdd = midpoint; + } + } while (locationToAdd === undefined); + + // console.log(`locationToAdd (${value}) = ${locationToAdd}`); + this.#data.splice(locationToAdd, 0, value); + }; + + get size() { + return this.#data.length; + } + + at(index) { + return this.#data.at(index); + } + + *iter() { + // console.log(JSON.stringify(this.#data)) + const size = this.#data.length; + for (var i = 0; i < size; i++) { + // if (i === size - 1) { + // yield this.#data[i] + // } + yield this.#data[i]; + } + }; +} \ No newline at end of file