ESM: Tidied up Set operations

This commit is contained in:
n1474335 2018-04-11 17:29:02 +00:00
parent 955a082614
commit e99331f305
12 changed files with 81 additions and 487 deletions

6
.gitignore vendored
View File

@ -5,4 +5,8 @@ build
docs/*
!docs/*.conf.json
!docs/*.ico
.vscode
.vscode
src/core/config/modules/*
src/core/config/OperationConfig.json
src/core/operations/index.mjs

View File

@ -142,7 +142,7 @@ module.exports = function (grunt) {
configFile: "./.eslintrc.json"
},
configs: ["Gruntfile.js"],
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*"],
core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"],
web: ["src/web/**/*.{js,mjs}"],
node: ["src/node/**/*.{js,mjs}"],
tests: ["test/**/*.{js,mjs}"],

View File

@ -118,6 +118,6 @@
"build": "grunt prod",
"test": "grunt test",
"docs": "grunt docs",
"lint": "grunt"
"lint": "grunt lint"
}
}

View File

@ -1,197 +0,0 @@
import FlowControl from "../../FlowControl.js";
import Arithmetic from "../../operations/Arithmetic.js";
import Base from "../../operations/Base.js";
import Base58 from "../../operations/Base58.js";
import Base64 from "../../operations/Base64.js";
import BCD from "../../operations/BCD.js";
import BitwiseOp from "../../operations/BitwiseOp.js";
import ByteRepr from "../../operations/ByteRepr.js";
import Convert from "../../operations/Convert.js";
import DateTime from "../../operations/DateTime.js";
import Endian from "../../operations/Endian.js";
import Entropy from "../../operations/Entropy.js";
import Filetime from "../../operations/Filetime.js";
import FileType from "../../operations/FileType.js";
import Hexdump from "../../operations/Hexdump.js";
import HTML from "../../operations/HTML.js";
import MAC from "../../operations/MAC.js";
import MorseCode from "../../operations/MorseCode.js";
import MS from "../../operations/MS.js";
import NetBIOS from "../../operations/NetBIOS.js";
import Numberwang from "../../operations/Numberwang.js";
import OS from "../../operations/OS.js";
import OTP from "../../operations/OTP.js";
import PHP from "../../operations/PHP.js";
import QuotedPrintable from "../../operations/QuotedPrintable.js";
import Rotate from "../../operations/Rotate.js";
import SeqUtils from "../../operations/SeqUtils.js";
import StrUtils from "../../operations/StrUtils.js";
import Tidy from "../../operations/Tidy.js";
import Unicode from "../../operations/Unicode.js";
import UUID from "../../operations/UUID.js";
import XKCD from "../../operations/XKCD.js";
/**
* Default module.
*
* The Default module is for operations that are expected to be very commonly used or
* do not require any libraries. This module is loaded into the app at compile time.
*
* Libraries:
* - Utils.js
* - otp
* - crypto
* - bignumber.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
const OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Default = {
"To Hexdump": Hexdump.runTo,
"From Hexdump": Hexdump.runFrom,
"To Hex": ByteRepr.runToHex,
"From Hex": ByteRepr.runFromHex,
"To Octal": ByteRepr.runToOct,
"From Octal": ByteRepr.runFromOct,
"To Charcode": ByteRepr.runToCharcode,
"From Charcode": ByteRepr.runFromCharcode,
"To Decimal": ByteRepr.runToDecimal,
"From Decimal": ByteRepr.runFromDecimal,
"To Binary": ByteRepr.runToBinary,
"From Binary": ByteRepr.runFromBinary,
"To Hex Content": ByteRepr.runToHexContent,
"From Hex Content": ByteRepr.runFromHexContent,
"To Base64": Base64.runTo,
"From Base64": Base64.runFrom,
"Show Base64 offsets": Base64.runOffsets,
"To Base32": Base64.runTo32,
"From Base32": Base64.runFrom32,
"To Base58": Base58.runTo,
"From Base58": Base58.runFrom,
"To Base": Base.runTo,
"From Base": Base.runFrom,
"To BCD": BCD.runToBCD,
"From BCD": BCD.runFromBCD,
"To HTML Entity": HTML.runToEntity,
"From HTML Entity": HTML.runFromEntity,
"Strip HTML tags": HTML.runStripTags,
"Parse colour code": HTML.runParseColourCode,
"Unescape Unicode Characters": Unicode.runUnescape,
"To Quoted Printable": QuotedPrintable.runTo,
"From Quoted Printable": QuotedPrintable.runFrom,
"Swap endianness": Endian.runSwapEndianness,
"ROT13": Rotate.runRot13,
"ROT47": Rotate.runRot47,
"Rotate left": Rotate.runRotl,
"Rotate right": Rotate.runRotr,
"Bit shift left": BitwiseOp.runBitShiftLeft,
"Bit shift right": BitwiseOp.runBitShiftRight,
"XOR": BitwiseOp.runXor,
"XOR Brute Force": BitwiseOp.runXorBrute,
"OR": BitwiseOp.runOr,
"NOT": BitwiseOp.runNot,
"AND": BitwiseOp.runAnd,
"ADD": BitwiseOp.runAdd,
"SUB": BitwiseOp.runSub,
"To Morse Code": MorseCode.runTo,
"From Morse Code": MorseCode.runFrom,
"Format MAC addresses": MAC.runFormat,
"Encode NetBIOS Name": NetBIOS.runEncodeName,
"Decode NetBIOS Name": NetBIOS.runDecodeName,
"Offset checker": StrUtils.runOffsetChecker,
"To Upper case": StrUtils.runUpper,
"To Lower case": StrUtils.runLower,
"Split": StrUtils.runSplit,
"Filter": StrUtils.runFilter,
"Escape string": StrUtils.runEscape,
"Unescape string": StrUtils.runUnescape,
"Head": StrUtils.runHead,
"Tail": StrUtils.runTail,
"Hamming Distance": StrUtils.runHamming,
"Remove whitespace": Tidy.runRemoveWhitespace,
"Remove null bytes": Tidy.runRemoveNulls,
"Drop bytes": Tidy.runDropBytes,
"Take bytes": Tidy.runTakeBytes,
"Pad lines": Tidy.runPad,
"Reverse": SeqUtils.runReverse,
"Sort": SeqUtils.runSort,
"Unique": SeqUtils.runUnique,
"Count occurrences": SeqUtils.runCount,
"Add line numbers": SeqUtils.runAddLineNumbers,
"Remove line numbers": SeqUtils.runRemoveLineNumbers,
"Expand alphabet range": SeqUtils.runExpandAlphRange,
"Convert distance": Convert.runDistance,
"Convert area": Convert.runArea,
"Convert mass": Convert.runMass,
"Convert speed": Convert.runSpeed,
"Convert data units": Convert.runDataSize,
"Parse UNIX file permissions": OS.runParseUnixPerms,
"Parse DateTime": DateTime.runParse,
"Translate DateTime Format": DateTime.runTranslateFormat,
"From UNIX Timestamp": DateTime.runFromUnixTimestamp,
"To UNIX Timestamp": DateTime.runToUnixTimestamp,
"Sleep": DateTime.runSleep,
"Microsoft Script Decoder": MS.runDecodeScript,
"Entropy": Entropy.runEntropy,
"Frequency distribution": Entropy.runFreqDistrib,
"Chi Square": Entropy.runChiSq,
"Detect File Type": FileType.runDetect,
"Scan for Embedded Files": FileType.runScanForEmbeddedFiles,
"Generate UUID": UUID.runGenerateV4,
"Numberwang": Numberwang.run,
"Generate TOTP": OTP.runTOTP,
"Generate HOTP": OTP.runHOTP,
"Fork": FlowControl.runFork,
"Merge": FlowControl.runMerge,
"Register": FlowControl.runRegister,
"Label": FlowControl.runComment,
"Jump": FlowControl.runJump,
"Conditional Jump": FlowControl.runCondJump,
"Return": FlowControl.runReturn,
"Comment": FlowControl.runComment,
"PHP Deserialize": PHP.runDeserialize,
"Sum": Arithmetic.runSum,
"Subtract": Arithmetic.runSub,
"Multiply": Arithmetic.runMulti,
"Divide": Arithmetic.runDiv,
"Mean": Arithmetic.runMean,
"Median": Arithmetic.runMedian,
"Standard Deviation": Arithmetic.runStdDev,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
"XKCD Random Number": XKCD.runRandomNumber,
/*
Highlighting functions.
This is a temporary solution as highlighting should be entirely
overhauled at some point.
*/
"From Base64-highlight": Base64.highlightFrom,
"From Base64-highlightReverse": Base64.highlightTo,
"To Base64-highlight": Base64.highlightTo,
"To Base64-highlightReverse": Base64.highlightFrom,
"From Hex-highlight": ByteRepr.highlightFrom,
"From Hex-highlightReverse": ByteRepr.highlightTo,
"To Hex-highlight": ByteRepr.highlightTo,
"To Hex-highlightReverse": ByteRepr.highlightFrom,
"From Charcode-highlight": ByteRepr.highlightFrom,
"From Charcode-highlightReverse": ByteRepr.highlightTo,
"To Charcode-highlight": ByteRepr.highlightTo,
"To Charcode-highlightReverse": ByteRepr.highlightFrom,
"From Binary-highlight": ByteRepr.highlightFromBinary,
"From Binary-highlightReverse": ByteRepr.highlightToBinary,
"To Binary-highlight": ByteRepr.highlightToBinary,
"To Binary-highlightReverse": ByteRepr.highlightFromBinary,
"From Hexdump-highlight": Hexdump.highlightFrom,
"From Hexdump-highlightReverse": Hexdump.highlightTo,
"To Hexdump-highlight": Hexdump.highlightTo,
"To Hexdump-highlightReverse": Hexdump.highlightFrom,
};
export default OpModules;

View File

@ -4,7 +4,6 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Operation from "../Operation";
/**
@ -20,14 +19,14 @@ class CartesianProduct extends Operation {
this.name = "Cartesian Product";
this.module = "Default";
this.description = "Get the cartesian product of two sets";
this.description = "Calculates the cartesian product of multiple sets of data, returning all possible combinations.";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Sample delimiter",
type: "binaryString",
value: Utils.escapeHtml("\\n\\n")
value: "\\n\\n"
},
{
name: "Item delimiter",
@ -39,19 +38,22 @@ class CartesianProduct extends Operation {
/**
* Validate input length
*
* @param {Object[]} sets
* @throws {Error} if not two sets
* @throws {Error} if fewer than 2 sets
*/
validateSampleNumbers(sets) {
if (!sets || (sets.length !== 2)) {
if (!sets || sets.length < 2) {
throw "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?";
}
}
/**
* Run the product operation
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.sampleDelim, this.itemDelimiter] = args;
@ -63,7 +65,7 @@ class CartesianProduct extends Operation {
return e;
}
return Utils.escapeHtml(this.runCartesianProduct(...sets.map(s => s.split(this.itemDelimiter))));
return this.runCartesianProduct(...sets.map(s => s.split(this.itemDelimiter)));
}
/**
@ -71,12 +73,23 @@ class CartesianProduct extends Operation {
*
* @param {Object[]} a
* @param {Object[]} b
* @returns {String[]}
* @param {Object[]} c
* @returns {string}
*/
runCartesianProduct(a, b) {
return Array(Math.max(a.length, b.length))
.fill(null)
.map((item, index) => `(${a[index] || undefined},${b[index] || undefined})`)
runCartesianProduct(a, b, ...c) {
/**
* https://stackoverflow.com/a/43053803/7200497
* @returns {Object[]}
*/
const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
/**
* https://stackoverflow.com/a/43053803/7200497
* @returns {Object[][]}
*/
const cartesian = (a, b, ...c) => (b ? cartesian(f(a, b), ...c) : a);
return cartesian(a, b, ...c)
.map(set => `(${set.join(",")})`)
.join(this.itemDelimiter);
}
}

View File

@ -4,7 +4,6 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Operation from "../Operation";
/**
@ -20,7 +19,7 @@ class PowerSet extends Operation {
this.name = "Power Set";
this.module = "Default";
this.description = "Generate the power set of a set";
this.description = "Calculates all the subsets of a set.";
this.inputType = "string";
this.outputType = "string";
this.args = [
@ -34,8 +33,10 @@ class PowerSet extends Operation {
/**
* Generate the power set
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.itemDelimiter] = args;
@ -43,7 +44,7 @@ class PowerSet extends Operation {
const inputArray = input.split(this.itemDelimiter).filter(a => a);
if (inputArray.length) {
return Utils.escapeHtml(this.runPowerSet(inputArray));
return this.runPowerSet(inputArray);
}
return "";

View File

@ -4,7 +4,6 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Operation from "../Operation";
/**
@ -20,14 +19,14 @@ class SetDifference extends Operation {
this.name = "Set Difference";
this.module = "Default";
this.description = "Get the Difference of two sets";
this.description = "Calculates the difference of two sets.";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Sample delimiter",
type: "binaryString",
value: Utils.escapeHtml("\\n\\n")
value: "\\n\\n"
},
{
name: "Item delimiter",
@ -39,6 +38,7 @@ class SetDifference extends Operation {
/**
* Validate input length
*
* @param {Object[]} sets
* @throws {Error} if not two sets
*/
@ -50,8 +50,10 @@ class SetDifference extends Operation {
/**
* Run the difference operation
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.sampleDelim, this.itemDelimiter] = args;
@ -63,7 +65,7 @@ class SetDifference extends Operation {
return e;
}
return Utils.escapeHtml(this.runSetDifference(...sets.map(s => s.split(this.itemDelimiter))));
return this.runSetDifference(...sets.map(s => s.split(this.itemDelimiter)));
}
/**

View File

@ -1,4 +1,9 @@
import Utils from "../Utils";
/**
* @author d98762625 [d98762625@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
/**
@ -14,14 +19,14 @@ class SetIntersection extends Operation {
this.name = "Set Intersection";
this.module = "Default";
this.description = "Get the intersection of two sets";
this.description = "Calculates the intersection of two sets.";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Sample delimiter",
type: "binaryString",
value: Utils.escapeHtml("\\n\\n")
value: "\\n\\n"
},
{
name: "Item delimiter",
@ -33,6 +38,7 @@ class SetIntersection extends Operation {
/**
* Validate input length
*
* @param {Object[]} sets
* @throws {Error} if not two sets
*/
@ -44,8 +50,10 @@ class SetIntersection extends Operation {
/**
* Run the intersection operation
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.sampleDelim, this.itemDelimiter] = args;
@ -57,7 +65,7 @@ class SetIntersection extends Operation {
return e;
}
return Utils.escapeHtml(this.runIntersect(...sets.map(s => s.split(this.itemDelimiter))));
return this.runIntersect(...sets.map(s => s.split(this.itemDelimiter)));
}
/**

View File

@ -4,7 +4,6 @@
* @license Apache-2.0
*/
import Utils from "../Utils";
import Operation from "../Operation";
/**
@ -20,14 +19,14 @@ class SetUnion extends Operation {
this.name = "Set Union";
this.module = "Default";
this.description = "Get the union of two sets";
this.description = "Calculates the union of two sets.";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Sample delimiter",
type: "binaryString",
value: Utils.escapeHtml("\\n\\n")
value: "\\n\\n"
},
{
name: "Item delimiter",
@ -39,6 +38,7 @@ class SetUnion extends Operation {
/**
* Validate input length
*
* @param {Object[]} sets
* @throws {Error} if not two sets
*/
@ -50,8 +50,10 @@ class SetUnion extends Operation {
/**
* Run the union operation
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.sampleDelim, this.itemDelimiter] = args;
@ -63,7 +65,7 @@ class SetUnion extends Operation {
return e;
}
return Utils.escapeHtml(this.runUnion(...sets.map(s => s.split(this.itemDelimiter))));
return this.runUnion(...sets.map(s => s.split(this.itemDelimiter)));
}
/**

View File

@ -20,7 +20,7 @@ class SymmetricDifference extends Operation {
this.name = "Symmetric Difference";
this.module = "Default";
this.description = "Get the symmetric difference of two sets";
this.description = "Calculates the symmetric difference of two sets.";
this.inputType = "string";
this.outputType = "string";
this.args = [
@ -39,6 +39,7 @@ class SymmetricDifference extends Operation {
/**
* Validate input length
*
* @param {Object[]} sets
* @throws {Error} if not two sets
*/
@ -50,8 +51,10 @@ class SymmetricDifference extends Operation {
/**
* Run the difference operation
* @param input
* @param args
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
[this.sampleDelim, this.itemDelimiter] = args;
@ -63,7 +66,7 @@ class SymmetricDifference extends Operation {
return e;
}
return Utils.escapeHtml(this.runSymmetricDifference(...sets.map(s => s.split(this.itemDelimiter))));
return this.runSymmetricDifference(...sets.map(s => s.split(this.itemDelimiter)));
}
/**

View File

@ -12,18 +12,7 @@ TestRegister.addTests([
{
name: "Cartesian Product",
input: "1 2 3 4 5\n\na b c d e",
expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e)",
recipeConfig: [
{
op: "Cartesian Product",
args: ["\n\n", " "],
},
],
},
{
name: "Cartesian Product: wrong sample count",
input: "1 2\n\n3 4 5\n\na b c d e",
expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
expectedOutput: "(1,a) (1,b) (1,c) (1,d) (1,e) (2,a) (2,b) (2,c) (2,d) (2,e) (3,a) (3,b) (3,c) (3,d) (3,e) (4,a) (4,b) (4,c) (4,d) (4,e) (5,a) (5,b) (5,c) (5,d) (5,e)",
recipeConfig: [
{
op: "Cartesian Product",
@ -34,7 +23,7 @@ TestRegister.addTests([
{
name: "Cartesian Product: too many on left",
input: "1 2 3 4 5 6\n\na b c d e",
expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e) (6,undefined)",
expectedOutput: "(1,a) (1,b) (1,c) (1,d) (1,e) (2,a) (2,b) (2,c) (2,d) (2,e) (3,a) (3,b) (3,c) (3,d) (3,e) (4,a) (4,b) (4,c) (4,d) (4,e) (5,a) (5,b) (5,c) (5,d) (5,e) (6,a) (6,b) (6,c) (6,d) (6,e)",
recipeConfig: [
{
op: "Cartesian Product",
@ -45,7 +34,7 @@ TestRegister.addTests([
{
name: "Cartesian Product: too many on right",
input: "1 2 3 4 5\n\na b c d e f",
expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e) (undefined,f)",
expectedOutput: "(1,a) (1,b) (1,c) (1,d) (1,e) (1,f) (2,a) (2,b) (2,c) (2,d) (2,e) (2,f) (3,a) (3,b) (3,c) (3,d) (3,e) (3,f) (4,a) (4,b) (4,c) (4,d) (4,e) (4,f) (5,a) (5,b) (5,c) (5,d) (5,e) (5,f)",
recipeConfig: [
{
op: "Cartesian Product",
@ -56,7 +45,7 @@ TestRegister.addTests([
{
name: "Cartesian Product: item delimiter",
input: "1-2-3-4-5\n\na-b-c-d-e",
expectedOutput: "(1,a)-(2,b)-(3,c)-(4,d)-(5,e)",
expectedOutput: "(1,a)-(1,b)-(1,c)-(1,d)-(1,e)-(2,a)-(2,b)-(2,c)-(2,d)-(2,e)-(3,a)-(3,b)-(3,c)-(3,d)-(3,e)-(4,a)-(4,b)-(4,c)-(4,d)-(4,e)-(5,a)-(5,b)-(5,c)-(5,d)-(5,e)",
recipeConfig: [
{
op: "Cartesian Product",
@ -67,7 +56,7 @@ TestRegister.addTests([
{
name: "Cartesian Product: sample delimiter",
input: "1 2 3 4 5_a b c d e",
expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e)",
expectedOutput: "(1,a) (1,b) (1,c) (1,d) (1,e) (2,a) (2,b) (2,c) (2,d) (2,e) (3,a) (3,b) (3,c) (3,d) (3,e) (4,a) (4,b) (4,c) (4,d) (4,e) (5,a) (5,b) (5,c) (5,d) (5,e)",
recipeConfig: [
{
op: "Cartesian Product",

View File

@ -64,235 +64,4 @@ TestRegister.addTests([
},
],
},
// {
// name: "Set Operations: Intersection",
// input: "1 2 3 4 5\n\n3 4 5 6 7",
// expectedOutput: "3 4 5",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Intersection"],
// },
// ],
// },
// {
// name: "Set Operations: Intersection: only one set",
// input: "1 2 3 4 5 6 7 8",
// expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Intersection"],
// },
// ],
// },
// {
// name: "Set Operations: Intersection: item delimiter",
// input: "1-2-3-4-5\n\n3-4-5-6-7",
// expectedOutput: "3-4-5",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", "-", "Intersection"],
// },
// ],
// },
// {
// name: "Set Operations: Intersection: sample delimiter",
// input: "1-2-3-4-5z3-4-5-6-7",
// expectedOutput: "3-4-5",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["z", "-", "Intersection"],
// },
// ],
// },
// {
// name: "Set Operations: Set Difference",
// input: "1 2 3 4 5\n\n3 4 5 6 7",
// expectedOutput: "1 2",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Set Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Set Difference: wrong sample count",
// input: "1 2 3 4 5_3_4 5 6 7",
// expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
// recipeConfig: [
// {
// op: "Set Operations",
// args: [" ", "_", "Set Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Set Difference: item delimiter",
// input: "1;2;3;4;5\n\n3;4;5;6;7",
// expectedOutput: "1;2",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", ";", "Set Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Set Difference: sample delimiter",
// input: "1;2;3;4;5===3;4;5;6;7",
// expectedOutput: "1;2",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["===", ";", "Set Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Symmetric Difference",
// input: "1 2 3 4 5\n\n3 4 5 6 7",
// expectedOutput: "1 2 6 7",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Symmetric Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Symmetric Difference: wrong sample count",
// input: "1 2\n\n3 4 5\n\n3 4 5 6 7",
// expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Symmetric Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Symmetric Difference: item delimiter",
// input: "a_b_c_d_e\n\nc_d_e_f_g",
// expectedOutput: "a_b_f_g",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", "_", "Symmetric Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Symmetric Difference: sample delimiter",
// input: "a_b_c_d_eAAAAAc_d_e_f_g",
// expectedOutput: "a_b_f_g",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["AAAAA", "_", "Symmetric Difference"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product",
// input: "1 2 3 4 5\n\na b c d e",
// expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e)",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product: wrong sample count",
// input: "1 2\n\n3 4 5\n\na b c d e",
// expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product: too many on left",
// input: "1 2 3 4 5 6\n\na b c d e",
// expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e) (6,undefined)",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product: too many on right",
// input: "1 2 3 4 5\n\na b c d e f",
// expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e) (undefined,f)",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product: item delimiter",
// input: "1-2-3-4-5\n\na-b-c-d-e",
// expectedOutput: "(1,a)-(2,b)-(3,c)-(4,d)-(5,e)",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", "-", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Cartesian Product: sample delimiter",
// input: "1 2 3 4 5_a b c d e",
// expectedOutput: "(1,a) (2,b) (3,c) (4,d) (5,e)",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["_", " ", "Cartesian Product"],
// },
// ],
// },
// {
// name: "Set Operations: Power set: nothing",
// input: "",
// expectedOutput: "",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Power Set"],
// },
// ],
// },
// {
// name: "Set Operations: Power set: Too many samples",
// input: "1 2 3\n\n4",
// expectedOutput: "Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Power Set"],
// },
// ],
// },
// {
// name: "Set Operations: Power set",
// input: "1 2 4",
// expectedOutput: "\n4\n2\n1\n2 4\n1 4\n1 2\n1 2 4\n",
// recipeConfig: [
// {
// op: "Set Operations",
// args: ["\n\n", " ", "Power Set"],
// },
// ],
// },
]);