diff --git a/src/permutations_heap.js b/src/permutations_heap.js new file mode 100644 index 0000000..1af6317 --- /dev/null +++ b/src/permutations_heap.js @@ -0,0 +1,43 @@ +/** + * Implementation of [Heap's Algorithm](https://en.wikipedia.org/wiki/Heap%27s_algorithm) + * for generating permutations. + * + * @param {Array} elements any type of data + * @returns {Array} array of permutations + */ +function permutationsHeap(elements) { + const indexes = new Array(elements.length); + const permutations = [elements.slice()]; + + for (let i = 0; i < elements.length; i++) { + indexes[i] = 0; + } + + for (let i = 0; i < elements.length; ) { + if (indexes[i] < i) { + // At odd indexes, swap from indexes[i] instead + // of from the beginning of the array + let swapFrom = 0; + if (i % 2 !== 0) { + swapFrom = indexes[i]; + } + + // swap between swapFrom and i, using + // a temporary variable as storage. + const temp = elements[swapFrom]; + elements[swapFrom] = elements[i]; + elements[i] = temp; + + permutations.push(elements.slice()); + indexes[i]++; + i = 0; + } else { + indexes[i] = 0; + i++; + } + } + + return permutations; +} + +export default permutationsHeap; diff --git a/test/permutations_heap.test.js b/test/permutations_heap.test.js new file mode 100644 index 0000000..fbc06f0 --- /dev/null +++ b/test/permutations_heap.test.js @@ -0,0 +1,19 @@ +import assert from "node:assert/strict"; +import { describe, it } from "node:test"; +import * as ss from "../index.js"; + +describe("permutationsHeap", function () { + it("generates 1 permutation", function () { + assert.deepEqual(ss.permutationsHeap([1]), [[1]]); + }); + it("generates 1, 2, 3 permutations", function () { + assert.deepEqual(ss.permutationsHeap([1, 2, 3]), [ + [1, 2, 3], + [2, 1, 3], + [3, 1, 2], + [1, 3, 2], + [2, 3, 1], + [3, 2, 1] + ]); + }); +});