From ad6e30f3d4ebf3ab1cad298a614c4f71b72f6767 Mon Sep 17 00:00:00 2001 From: s2224834 <46319860+s2224834@users.noreply.github.com> Date: Tue, 8 Jan 2019 18:25:42 +0000 Subject: [PATCH] Bombe: review, tests, validation --- src/core/lib/Bombe.mjs | 34 ++++----- src/core/lib/Enigma.mjs | 6 +- src/core/operations/Bombe.mjs | 31 ++++++-- src/core/operations/Enigma.mjs | 6 +- tests/operations/tests/Bombe.mjs | 127 +++++++++++++++++++++++++++++++ 5 files changed, 173 insertions(+), 31 deletions(-) diff --git a/src/core/lib/Bombe.mjs b/src/core/lib/Bombe.mjs index 70a2d2cb..53766560 100644 --- a/src/core/lib/Bombe.mjs +++ b/src/core/lib/Bombe.mjs @@ -77,10 +77,7 @@ class Edge { * @returns {number} */ getOther(node) { - if (this.node1 === node) { - return this.node2; - } - return this.node1; + return this.node1 === node ? this.node2 : this.node1; } } @@ -144,10 +141,7 @@ class Scrambler { * @returns {number} */ getOtherEnd(end) { - if (this.end1 === end) { - return this.end2; - } - return this.end1; + return this.end1 === end ? this.end2 : this.end1; } /** @@ -194,8 +188,11 @@ export class BombeMachine { * @param {function} update - Function to call to send status updates (optional) */ constructor(rotors, reflector, ciphertext, crib, update=undefined) { - if (ciphertext.length !== crib.length) { - throw new OperationError("Ciphertext and crib length differ"); + if (ciphertext.length < crib.length) { + throw new OperationError("Crib overruns supplied ciphertext"); + } + if (ciphertext.length > crib.length) { + throw new OperationError("Ciphertext is longer than crib"); } if (crib.length < 2) { // This is the absolute bare minimum to be sane, and even then it's likely too short to @@ -226,7 +223,7 @@ export class BombeMachine { // This is the bundle of wires corresponding to the 26 letters within each of the 26 // possible nodes in the menu - this.wires = new Array(26*26).fill(false); + this.wires = new Array(26*26); // These are the pseudo-Engima devices corresponding to each edge in the menu, and the // nodes in the menu they each connect to @@ -271,9 +268,9 @@ export class BombeMachine { * If we have a way of sending status messages, do so. * @param {string} msg - Message to send. */ - update(msg) { + update(...msg) { if (this.updateFn !== undefined) { - this.updateFn(msg); + this.updateFn(...msg); } } @@ -411,7 +408,10 @@ export class BombeMachine { // For each possible rotor setting const nChecks = Math.pow(26, this.baseRotors.length); for (let i=1; i<=nChecks; i++) { - this.wires.fill(false); + // Benchmarking suggests this is faster than using .fill() + for (let i=0; i 2) { - const msg = `Bombe run with ${this.nLoops} loops in menu (2+ desirable): ${stops} stops, ${Math.floor(100 * i / nChecks)}% done`; - this.update(msg); + // (note this won't be triggered on 3-rotor runs - they run fast enough it doesn't seem necessary) + if (n > 3) { + this.update(this.nLoops, stops, i/nChecks); } } return result; diff --git a/src/core/lib/Enigma.mjs b/src/core/lib/Enigma.mjs index 9fc0f7d0..cfc93933 100644 --- a/src/core/lib/Enigma.mjs +++ b/src/core/lib/Enigma.mjs @@ -103,8 +103,8 @@ export class Rotor { if (!/^[A-Z]$/.test(initialPosition)) { throw new OperationError("Rotor initial position must be exactly one uppercase letter"); } - this.map = new Array(26).fill(); - this.revMap = new Array(26).fill(); + this.map = new Array(26); + this.revMap = new Array(26); const uniq = {}; for (let i=0; i S\)/, + recipeConfig: [ + { + "op": "Bombe", + "args": [ + "BDFHJLCPRTXVZNYEIWGAKMUSQO