UNPKG

aoc-copilot

Version:

Advent of Code automatic runner for examples and inputs

106 lines 3.69 kB
"use strict"; /** * These functions implement a min heap which can be used to pop the lowest * key. It uses an array as the heap, and each row in the heap must be an * array with the key as the first element: * * heap: [number, ...T][] * * The main thing to keep in mind is that a heap sort just ensures that the * parent key <= child keys, it won't be in ascending order. * * The >> operator is the bit shift operator. It's used to calculate the index * of the parent of a node. This is one of the unique characteristics of a * heap -- no pointers are needed to keep track of child or parent indexes, * the structure of the heap itself determines that: * 0 root * 1 parent 0 * 2 parent 0 * 3 parent 1 * 4 parent 1 * 5 parent 2 * 6 parent 2 * 7 parent 3 * * parent(7) = 7 >> 1 = 3 (0111 >> 1 = 0011) * children(2) = 2 * 2 + 1 = 5 and 5 + 1 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.heapify = heapify; exports.pop = pop; exports.push = push; /** * Replace the root node of the given heap with the given node, and return the * previous root. Returns the given node if the heap is empty. Similar to * calling pop and push, but more efficient. */ function _exchange(arr, value) { if (arr.length === 0) return value; // Get the root node, so to return it later let oldValue = arr[0]; // Inject the replacing node using the sift-down process _siftDown(arr, 0, value); return oldValue; } /** * Reorder the given array in-place so that it becomes a valid heap. Elements * in the given array must have a [0] property (e.g. arrays). That [0] value * serves as the key to establish the heap order. The rest of such an element * is just payload. It also returns the heap. */ function heapify(arr) { // Establish heap with an incremental, bottom-up process for (let i = arr.length >> 1; i--;) _siftDown(arr, i); return arr; } /** * Extract the root of the given heap and return it (the subarray). Returns * undefined if the heap is empty */ function pop(arr) { // Pop the last leaf from the given heap, and exchange it with its root return arr.length == 0 ? undefined : _exchange(arr, arr.pop()); // Returns the old root } /** * Inserts the given node into the given heap. Return the heap. */ function push(arr, value) { let key = value[0]; let i = arr.length; // First assume the insertion spot is at the very end (as a leaf) let j; // Then follow the path to the root, moving values down for as long as they // are greater than the value to be inserted while ((j = (i - 1) >> 1) >= 0 && key < arr[j][0]) { arr[i] = arr[j]; i = j; } // Found the insertion spot arr[i] = value; return arr; } /** * The node at the given index of the given heap is sifted down in * its subtree until it does not have a child with a lesser value. */ function _siftDown(arr, i = 0, value = arr[i]) { if (i < arr.length) { let key = value[0]; // Grab the value to compare with while (true) { // Choose the child with the least value let j = i * 2 + 1; if (j + 1 < arr.length && arr[j][0] > arr[j + 1][0]) j++; // If no child has lesser value, then we've found the spot! if (j >= arr.length || key <= arr[j][0]) break; // Copy the selected child node one level up... arr[i] = arr[j]; // ...and consider the child slot for putting our sifted node i = j; } arr[i] = value; // Place the sifted node at the found spot } } //# sourceMappingURL=heap.js.map