Add Malbolge operation in new esoteric programming category

This commit is contained in:
Karsten Silkenbäumer 2019-03-06 23:38:41 +01:00
parent 8148c1a8a8
commit 6913afed00
6 changed files with 147 additions and 0 deletions

5
package-lock.json generated
View file

@ -8172,6 +8172,11 @@
"pify": "^3.0.0" "pify": "^3.0.0"
} }
}, },
"malbolge-vm": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/malbolge-vm/-/malbolge-vm-1.0.2.tgz",
"integrity": "sha1-AXFAPb2Js4qi10yUzalcqRGo9ms="
},
"map-age-cleaner": { "map-age-cleaner": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",

View file

@ -113,6 +113,7 @@
"lodash": "^4.17.11", "lodash": "^4.17.11",
"loglevel": "^1.6.1", "loglevel": "^1.6.1",
"loglevel-message-prefix": "^3.0.0", "loglevel-message-prefix": "^3.0.0",
"malbolge-vm": "^1.0.2",
"moment": "^2.23.0", "moment": "^2.23.0",
"moment-timezone": "^0.5.23", "moment-timezone": "^0.5.23",
"ngeohash": "^0.6.3", "ngeohash": "^0.6.3",

View file

@ -311,6 +311,12 @@
"TCP/IP Checksum" "TCP/IP Checksum"
] ]
}, },
{
"name": "Esoteric Programming",
"ops": [
"Malbolge"
]
},
{ {
"name": "Code tidy", "name": "Code tidy",
"ops": [ "ops": [

View file

@ -0,0 +1,90 @@
/**
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import mb from "malbolge-vm";
/**
* Malbolge operation
*/
class Malbolge extends Operation {
/**
* Malbolge constructor
*/
constructor () {
super();
this.name = "Malbolge";
this.module = "Default";
this.description = "Malbolge, invented by Ben Olmstead in 1998, is an esoteric programming language designed to be as difficult to program in as possible. The first Hello, world! program written in it was produced by a Lisp program using a local beam search of the space of all possible programs. It is modeled as a virtual machine based on ternary digits.";
this.infoURL = "http://esolangs.org/wiki/Malbolge";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "User Input (line by line)",
"type": "text",
"value": ""
}
];
this.patterns = [
{
match: "^(?:[\\x21-\\x7e])?$",
flags: "i",
args: []
}
];
}
/**
* @param {String} input - A Malbolge program
* @param {Object[]} args
* @returns {String}
*/
run (input, args) {
if (input.length === 0) {
return "";
}
const [userInputString] = args,
vm = mb.load(input),
userInputArray = userInputString.split("").map(e => e.charCodeAt(0));
let userInput = null,
output = "",
loop = true,
temp;
while (loop) {
try {
while ((temp = mb.step(vm, userInput)) !== mb.EXIT) {
userInput = null;
if (temp !== null) {
output += String.fromCharCode(temp);
}
}
loop = false;
} catch (err) {
if (err === mb.WANTS_INPUT) {
if (userInputArray.length) {
userInput = userInputArray.shift();
continue;
}
output += "Error: Input required";
loop = false;
} else {
throw new OperationError(err);
}
}
}
return output;
}
}
export default Malbolge;

View file

@ -57,6 +57,7 @@ import "./tests/JWTSign";
import "./tests/JWTVerify"; import "./tests/JWTVerify";
import "./tests/MS"; import "./tests/MS";
import "./tests/Magic"; import "./tests/Magic";
import "./tests/Malbolge";
import "./tests/MorseCode"; import "./tests/MorseCode";
import "./tests/NetBIOS"; import "./tests/NetBIOS";
import "./tests/OTP"; import "./tests/OTP";

View file

@ -0,0 +1,44 @@
/**
* Malbolge tests.
*
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/
import TestRegister from "../TestRegister";
TestRegister.addTests([
{
name: "Malbolge: no program",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "Malbolge",
args: [""],
},
],
},
{
name: "Malbolge: simple program",
input: "('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#\"`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~| 4XzyTT43Qsqq(Lnmkj\"Fhg${z@>",
expectedOutput: "Hello World!",
recipeConfig: [
{
op: "Malbolge",
args: [""],
},
],
},
{
name: "Malbolge: simple cat with infinite user input",
input: "(=BA#9\"=<;:3y7x54-21q/p-,+*)\"!h%B0/.\n~P<\n<:(8&\n66#\"!~}|{zyxwvu\ngJ%",
expectedOutput: "First line\nSecond Line\nError: Input required",
recipeConfig: [
{
op: "Malbolge",
args: ["First line\nSecond Line\n"],
},
],
},
]);