/** * @author d98762625 [d98762625@gmail.com] * @copyright Crown Copyright 2018 * @license Apache-2.0 */ import Operation from "../Operation"; /** * Power Set operation */ class PowerSet extends Operation { /** * Power set constructor */ constructor() { super(); this.name = "Power Set"; this.module = "Default"; this.description = "Calculates all the subsets of a set."; this.inputType = "string"; this.outputType = "string"; this.args = [ { name: "Item delimiter", type: "binaryString", value: "," }, ]; } /** * Generate the power set * * @param {string} input * @param {Object[]} args * @returns {string} */ run(input, args) { [this.itemDelimiter] = args; // Split and filter empty strings const inputArray = input.split(this.itemDelimiter).filter(a => a); if (inputArray.length) { return this.runPowerSet(inputArray); } return ""; } /** * Return the power set of the inputted set. * * @param {Object[]} a * @returns {Object[]} */ runPowerSet(a) { // empty array items getting picked up a = a.filter(i => i.length); if (!a.length) { return []; } /** * Decimal to binary function * @param {*} dec */ const toBinary = (dec) => (dec >>> 0).toString(2); const result = new Set(); // Get the decimal number to make a binary as long as the input const maxBinaryValue = parseInt(Number(a.map(i => "1").reduce((p, c) => p + c)), 2); // Make an array of each binary number from 0 to maximum const binaries = [...Array(maxBinaryValue + 1).keys()] .map(toBinary) .map(i => i.padStart(toBinary(maxBinaryValue).length, "0")); // XOR the input with each binary to get each unique permutation binaries.forEach((binary) => { const split = binary.split(""); result.add(a.filter((item, index) => split[index] === "1")); }); // map for formatting & put in length order. return [...result] .map(r => r.join(this.itemDelimiter)).sort((a, b) => a.length - b.length) .map(i => `${i}\n`).join(""); } } export default PowerSet;