Skip to content

Commit 0a0217c

Browse files
committed
2 parents 3faa9d3 + 822a4fa commit 0a0217c

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed

src/core/config/Categories.json

+1
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@
490490
"P-list Viewer",
491491
"Disassemble x86",
492492
"Pseudo-Random Number Generator",
493+
"Generate De Bruijn Sequence",
493494
"Generate UUID",
494495
"Generate TOTP",
495496
"Generate HOTP",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @author gchq77703 [[email protected]]
3+
* @copyright Crown Copyright 2019
4+
* @license Apache-2.0
5+
*/
6+
7+
import Operation from "../Operation";
8+
import OperationError from "../errors/OperationError";
9+
10+
/**
11+
* Generate De Bruijn Sequence operation
12+
*/
13+
class GenerateDeBruijnSequence extends Operation {
14+
15+
/**
16+
* GenerateDeBruijnSequence constructor
17+
*/
18+
constructor() {
19+
super();
20+
21+
this.name = "Generate De Bruijn Sequence";
22+
this.module = "Default";
23+
this.description = "Generates rolling keycode combinations given a certain alphabet size and key length.";
24+
this.infoURL = "https://wikipedia.org/wiki/De_Bruijn_sequence";
25+
this.inputType = "string";
26+
this.outputType = "string";
27+
this.args = [
28+
{
29+
name: "Alphabet size (k)",
30+
type: "number",
31+
value: 2
32+
},
33+
{
34+
name: "Key length (n)",
35+
type: "number",
36+
value: 3
37+
}
38+
];
39+
}
40+
41+
/**
42+
* @param {string} input
43+
* @param {Object[]} args
44+
* @returns {string}
45+
*/
46+
run(input, args) {
47+
const [k, n] = args;
48+
49+
if (k < 2 || k > 9) {
50+
throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
51+
}
52+
53+
if (n < 2) {
54+
throw new OperationError("Invalid key length, required to be at least 2.");
55+
}
56+
57+
if (Math.pow(k, n) > 50000) {
58+
throw new OperationError("Too many permutations, please reduce k^n to under 50,000.");
59+
}
60+
61+
const a = [];
62+
for (let i = 0; i < k * n; i++) a.push(0);
63+
64+
const sequence = [];
65+
66+
(function db(t = 1, p = 1) {
67+
if (t > n) {
68+
if (n % p !== 0) return;
69+
for (let j = 1; j <= p; j++) {
70+
sequence.push(a[j]);
71+
}
72+
return;
73+
}
74+
75+
a[t] = a[t - p];
76+
db(t + 1, p);
77+
for (let j = a[t - p] + 1; j < k; j++) {
78+
a[t] = j;
79+
db(t + 1, t);
80+
}
81+
})();
82+
83+
return sequence.join("");
84+
}
85+
}
86+
87+
export default GenerateDeBruijnSequence;

tests/operations/index.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ import "./tests/Rabbit.mjs";
133133
import "./tests/LevenshteinDistance.mjs";
134134
import "./tests/SwapCase.mjs";
135135
import "./tests/HKDF.mjs";
136+
import "./tests/GenerateDeBruijnSequence.mjs";
136137

137138
// Cannot test operations that use the File type yet
138139
// import "./tests/SplitColourChannels.mjs";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* De Brujin Sequence tests.
3+
*
4+
* @author gchq77703 [[email protected]]
5+
* @copyright Crown Copyright 2017
6+
* @license Apache-2.0
7+
*/
8+
import TestRegister from "../TestRegister";
9+
10+
TestRegister.addTests([
11+
{
12+
name: "Small Sequence",
13+
input: "",
14+
expectedOutput: "00010111",
15+
recipeConfig: [
16+
{
17+
"op": "Generate De Bruijn Sequence",
18+
"args": [2, 3]
19+
}
20+
]
21+
},
22+
{
23+
name: "Long Sequence",
24+
input: "",
25+
expectedOutput: "0000010000200003000110001200013000210002200023000310003200033001010010200103001110011200113001210012200123001310013200133002010020200203002110021200213002210022200223002310023200233003010030200303003110031200313003210032200323003310033200333010110101201013010210102201023010310103201033011020110301111011120111301121011220112301131011320113301202012030121101212012130122101222012230123101232012330130201303013110131201313013210132201323013310133201333020210202202023020310203202033021030211102112021130212102122021230213102132021330220302211022120221302221022220222302231022320223302303023110231202313023210232202323023310233202333030310303203033031110311203113031210312203123031310313203133032110321203213032210322203223032310323203233033110331203313033210332203323033310333203333111112111131112211123111321113311212112131122211223112321123311312113131132211323113321133312122121231213212133122131222212223122321223312313123221232312332123331313213133132221322313232132331332213323133321333322222322233223232233323233233333",
26+
recipeConfig: [
27+
{
28+
"op": "Generate De Bruijn Sequence",
29+
"args": [4, 5]
30+
}
31+
]
32+
}
33+
]);

0 commit comments

Comments
 (0)