RosettaCodeData/Task/Burrows-Wheeler-transform/JavaScript/burrows-wheeler-transform.js

77 lines
2.0 KiB
JavaScript

class BWT {
static STX = "\u0002";
static ETX = "\u0003";
static bwt(s) {
if (s.includes(BWT.STX) || s.includes(BWT.ETX)) {
throw new Error("String cannot contain STX or ETX");
}
const ss = BWT.STX + s + BWT.ETX;
const table = [];
for (let i = 0; i < ss.length; i++) {
const before = ss.substring(i);
const after = ss.substring(0, i);
table.push(before + after);
}
table.sort();
let sb = "";
for (const str of table) {
sb += str.charAt(str.length - 1);
}
return sb;
}
static ibwt(r) {
const len = r.length;
const table = [];
for (let i = 0; i < len; ++i) {
table.push("");
}
for (let j = 0; j < len; ++j) {
for (let i = 0; i < len; ++i) {
table[i] = r.charAt(i) + table[i];
}
table.sort();
}
for (const row of table) {
if (row.endsWith(BWT.ETX)) {
return row.substring(1, len - 1);
}
}
return "";
}
static makePrintable(s) {
// substitute ^ for STX and | for ETX to print results
return s.replace(BWT.STX, "^").replace(BWT.ETX, "|");
}
static main() {
const tests = [
"banana",
"appellee",
"dogwood",
"TO BE OR NOT TO BE OR WANT TO BE OR NOT?",
"SIX.MIXED.PIXIES.SIFT.SIXTY.PIXIE.DUST.BOXES",
"\u0002ABC\u0003"
];
for (const test of tests) {
console.log(BWT.makePrintable(test));
process.stdout.write(" --> ");
let t = "";
try {
t = BWT.bwt(test);
console.log(BWT.makePrintable(t));
} catch (e) {
console.log("ERROR: " + e.message);
}
const r = BWT.ibwt(t);
console.log(` --> ${r}\n`);
}
}
}
BWT.main();