diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index 40d62cdc2..b721bc711 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1,5 +1,4 @@ import { getRandomIntInclusive } from "../utils/helpers/getRandomIntInclusive"; -import { MinHeap } from "../utils/Heap"; import { comprGenChar, comprLZGenerate, comprLZEncode, comprLZDecode } from "../utils/CompressionContracts"; import { HammingEncode, HammingDecode, HammingEncodeProperly } from "../utils/HammingCodeTools"; @@ -994,7 +993,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ const distance: [number][] = new Array(height); //const prev: [[number, number] | undefined][] = new Array(height); - const queue = new MinHeap<[number, number]>(); + const queue: [number, number][] = []; for (let y = 0; y < height; y++) { distance[y] = new Array(width).fill(Infinity) as [number]; @@ -1015,21 +1014,15 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ // Prepare starting point distance[0][0] = 0; - queue.push([0, 0], 0); + queue.push([0, 0]); // Take next-nearest position and expand potential paths from there - while (queue.size > 0) { - const [y, x] = queue.pop() as [number, number]; + while (queue.length > 0) { + const [y, x] = queue.shift() as [number, number]; for (const [yN, xN] of neighbors(y, x)) { - const d = distance[y][x] + 1; - if (d < distance[yN][xN]) { - if (distance[yN][xN] == Infinity) - // Not reached previously - queue.push([yN, xN], d); - // Found a shorter path - else queue.changeWeight(([yQ, xQ]) => yQ == yN && xQ == xN, d); - //prev[yN][xN] = [y, x]; - distance[yN][xN] = d; + if (distance[yN][xN] == Infinity) { + queue.push([yN, xN]); + distance[yN][xN] = distance[y][x] + 1; } } } diff --git a/src/utils/Heap.ts b/src/utils/Heap.ts deleted file mode 100644 index 634da4fe4..000000000 --- a/src/utils/Heap.ts +++ /dev/null @@ -1,133 +0,0 @@ -/** Binary heap. */ -abstract class BinHeap { - /** - * Heap data array consisting of [weight, payload] pairs, arranged by weight - * to satisfy heap condition. - * - * Encodes the binary tree by storing tree root at index 0 and - * left child of element i at `i * 2 + 1` and - * right child of element i at `i * 2 + 2`. - */ - protected data: [number, T][]; - - constructor() { - this.data = []; - } - - /** Get number of elements in the heap. */ - public get size(): number { - return this.data.length; - } - - /** Add a new element to the heap. */ - public push(value: T, weight: number): void { - const i = this.data.length; - this.data[i] = [weight, value]; - this.heapifyUp(i); - } - - /** Get the value of the root-most element of the heap, without changing the heap. */ - public peek(): T | undefined { - if (this.data.length == 0) return undefined; - - return this.data[0][1]; - } - - /** Remove the root-most element of the heap and return the removed element's value. */ - public pop(): T | undefined { - if (this.data.length == 0) return undefined; - - const value = this.data[0][1]; - - this.data[0] = this.data[this.data.length - 1]; - this.data.length = this.data.length - 1; - - this.heapifyDown(0); - - return value; - } - - /** Change the weight of an element in the heap. */ - public changeWeight(predicate: (value: T) => boolean, weight: number): void { - // Find first element with matching value, if any - const i = this.data.findIndex((e) => predicate(e[1])); - if (i == -1) return; - - // Update that element's weight - this.data[i][0] = weight; - - // And re-heapify if needed - const p = Math.floor((i - 1) / 2); - - if (!this.heapOrderABeforeB(this.data[p][0], this.data[i][0])) - // Needs to shift root-wards? - this.heapifyUp(i); - // Try shifting deeper - else this.heapifyDown(i); - } - - /** Restore heap condition, starting at index i and traveling towards root. */ - protected heapifyUp(i: number): void { - // Swap the new element up towards root until it reaches root position or - // settles under under a suitable parent - while (i > 0) { - const p = Math.floor((i - 1) / 2); - - // Reached heap-ordered state already? - if (this.heapOrderABeforeB(this.data[p][0], this.data[i][0])) break; - - // Swap - const tmp = this.data[p]; - this.data[p] = this.data[i]; - this.data[i] = tmp; - - // And repeat at parent index - i = p; - } - } - - /** Restore heap condition, starting at index i and traveling away from root. */ - protected heapifyDown(i: number): void { - // Swap the shifted element down in the heap until it either reaches the - // bottom layer or is in correct order relative to it's children - while (i < this.data.length) { - const l = i * 2 + 1; - const r = i * 2 + 2; - let toSwap = i; - - // Find which one of element i and it's children should be closest to root - if (l < this.data.length && this.heapOrderABeforeB(this.data[l][0], this.data[toSwap][0])) toSwap = l; - if (r < this.data.length && this.heapOrderABeforeB(this.data[r][0], this.data[toSwap][0])) toSwap = r; - - // Already in order? - if (i == toSwap) break; - - // Not in order. Swap child that should be closest to root up to 'i' and repeat - const tmp = this.data[toSwap]; - this.data[toSwap] = this.data[i]; - this.data[i] = tmp; - - i = toSwap; - } - } - - /** - * Should element with weight `weightA` be closer to root than element with - * weight `weightB`? - */ - protected abstract heapOrderABeforeB(weightA: number, weightB: number): boolean; -} - -/** Binary max-heap. */ -export class MaxHeap extends BinHeap { - heapOrderABeforeB(weightA: number, weightB: number): boolean { - return weightA > weightB; - } -} - -/** Binary min-heap. */ -export class MinHeap extends BinHeap { - heapOrderABeforeB(weightA: number, weightB: number): boolean { - return weightA < weightB; - } -}