Skip to content

Instantly share code, notes, and snippets.

@razetime
Created December 26, 2020 16:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save razetime/98fcd696ccb0f615e9bf17ccda3f527a to your computer and use it in GitHub Desktop.
Save razetime/98fcd696ccb0f615e9bf17ccda3f527a to your computer and use it in GitHub Desktop.
Moanfuck implementation in js
// moanfuck implementation in JavaScript
// Use as: interpret(<mf code>)
// or: interpret(convert(<bf code>)) if you want to try using bf code.
// logs to the console.
// borrowed from https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/string/levenshtein-distance/levenshteinDistance.js
function levenshteinDistance(a, b) {
// Create empty edit distance matrix for all possible modifications of
// substrings of a to substrings of b.
const distanceMatrix = Array(b.length + 1).fill(null).map(() => Array(a.length + 1).fill(null));
// Fill the first row of the matrix.
// If this is first row then we're transforming empty string to a.
// In this case the number of transformations equals to size of a substring.
for (let i = 0; i <= a.length; i += 1) {
distanceMatrix[0][i] = i;
}
// Fill the first column of the matrix.
// If this is first column then we're transforming empty string to b.
// In this case the number of transformations equals to size of b substring.
for (let j = 0; j <= b.length; j += 1) {
distanceMatrix[j][0] = j;
}
for (let j = 1; j <= b.length; j += 1) {
for (let i = 1; i <= a.length; i += 1) {
const indicator = a[i - 1] === b[j - 1] ? 0 : 1;
distanceMatrix[j][i] = Math.min(
distanceMatrix[j][i - 1] + 1, // deletion
distanceMatrix[j - 1][i] + 1, // insertion
distanceMatrix[j - 1][i - 1] + indicator, // substitution
);
}
}
return distanceMatrix[b.length][a.length];
}
// 0 + AH
// 1 - OH
// 2 > YES
// 3 < FUCK
// 4 , MORE
// 5 . YEAH
// 6 [ AHH
// 7 ] OOH
// 8 # BABY (debug breakpoint)
function interpret(code, input) {
var instructions = ["AH", "OH", "YES", "FUCK", "MORE", "YEAH", "AHH", "OOH", "BABY"];
var cell = 0;
var output = "";
var inputpos = 0;
var data = [];
var loop = [];
var next = 0;
var closest = function (a) {
var dist = instructions.map(x => levenshteinDistance(x, a));
return dist.indexOf(Math.min(...dist));
};
var fCode = code.toUpperCase().split(" ").map(x => closest(x))
while (next < fCode.length) {
switch (fCode[next]) {
case 0:
if (~loop[0]) {
data[cell] = (data[cell] || 0) + 1;
}
break;
case 1:
if (~loop[0]) {
data[cell] = (data[cell] || 0) - 1;
}
break;
case 2:
if (~loop[0]) {
cell++;
}
break;
case 3:
if (~loop[0]) {
cell--;
}
break;
case 4:
if (~loop[0]) {
data[cell] = input.charCodeAt(inputpos);
inputpos++;
}
break;
case 5:
if (~loop[0]) {
output = output + String.fromCharCode(data[cell]);
}
break;
case 6:
loop.unshift(data[cell] ? next : -1);
break;
case 7:
if (~loop[0] && data[cell]) {
next = loop[0];
} else {
loop.shift();
}
break;
case 8:
console.log("Current state:", data)
break;
default:
console.log("idk what the hell you did but you got this message");
}
next++;
}
console.log(output)
}
function convert(code) {
var instructions = ["AH", "OH", "YES", "FUCK", "MORE", "YEAH", "AHH", "OOH", "BABY"];
var bf = "+-><,.[]#";
var c = code.split('');
var newC = c.map(x => instructions[bf.indexOf(x)]).join(" ");
console.log(newC);
return newC;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment