Add De Bruijn Operation

This commit is contained in:
GCHQ 77703 2019-02-15 14:23:16 +00:00
parent 8148c1a8a8
commit 1f09c03d48
4 changed files with 122 additions and 0 deletions

View File

@ -370,6 +370,7 @@
"Chi Square",
"Disassemble x86",
"Pseudo-Random Number Generator",
"Generate De Bruijn Sequence",
"Generate UUID",
"Generate TOTP",
"Generate HOTP",

View File

@ -0,0 +1,87 @@
/**
* @author gchq77703 [gchq77703@gchq.gov.uk]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
/**
* Generate De Bruijn Sequence operation
*/
class GenerateDeBruijnSequence extends Operation {
/**
* GenerateDeBruijnSequence constructor
*/
constructor() {
super();
this.name = "Generate De Bruijn Sequence";
this.module = "Default";
this.description = "Generates rolling keycode combinations given a certain alphabet size and key length.";
this.infoURL = "https://wikipedia.org/wiki/De_Bruijn_sequence";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Alphabet size (k)",
type: "number",
value: 2
},
{
name: "Key length (n)",
type: "number",
value: 3
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [k, n] = args;
if (k < 2 || k > 9) {
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
}
if (n < 2) {
throw new OperationError("Invalid key length, required to be at least 2.");
}
if (Math.pow(k, n) > 50000) {
throw new OperationError("Too many permutations, please reduce k^n to under 50,000.");
}
const a = [];
for (let i = 0; i < k * n; i++) a.push(0);
const sequence = [];
(function db(t = 1, p = 1) {
if (t > n) {
if (n % p !== 0) return;
for (let j = 1; j <= p; j++) {
sequence.push(a[j]);
}
return;
}
a[t] = a[t - p];
db(t + 1, p);
for (let j = a[t - p] + 1; j < k; j++) {
a[t] = j;
db(t + 1, t);
}
})();
return sequence.join("");
}
}
export default GenerateDeBruijnSequence;

View File

@ -45,6 +45,7 @@ import "./tests/DateTime";
import "./tests/ExtractEmailAddresses";
import "./tests/Fork";
import "./tests/FromDecimal";
import "./tests/GenerateDeBruijnSequence";
import "./tests/Hash";
import "./tests/HaversineDistance";
import "./tests/Hexdump";

View File

@ -0,0 +1,33 @@
/**
* De Brujin Sequence tests.
*
* @author gchq77703 [gchq77703@gchq.gov.uk]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../TestRegister";
TestRegister.addTests([
{
name: "Small Sequence",
input: "",
expectedOutput: "00010111",
recipeConfig: [
{
"op": "Generate De Bruijn Sequence",
"args": [2, 3]
}
]
},
{
name: "Long Sequence",
input: "",
expectedOutput: "0000010000200003000110001200013000210002200023000310003200033001010010200103001110011200113001210012200123001310013200133002010020200203002110021200213002210022200223002310023200233003010030200303003110031200313003210032200323003310033200333010110101201013010210102201023010310103201033011020110301111011120111301121011220112301131011320113301202012030121101212012130122101222012230123101232012330130201303013110131201313013210132201323013310133201333020210202202023020310203202033021030211102112021130212102122021230213102132021330220302211022120221302221022220222302231022320223302303023110231202313023210232202323023310233202333030310303203033031110311203113031210312203123031310313203133032110321203213032210322203223032310323203233033110331203313033210332203323033310333203333111112111131112211123111321113311212112131122211223112321123311312113131132211323113321133312122121231213212133122131222212223122321223312313123221232312332123331313213133132221322313232132331332213323133321333322222322233223232233323233233333",
recipeConfig: [
{
"op": "Generate De Bruijn Sequence",
"args": [4, 5]
}
]
}
])