Skip to content

Commit cd4830f

Browse files
brunohadlichmgechev
authored andcommittedDec 11, 2018
Added the Burrows-Wheeler algorithm. (mgechev#145)
* Added the Burrows-Wheeler algorithm. * Added the Burrows-Wheeler algorithm.
1 parent 26bb431 commit cd4830f

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed
 

‎doc-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"source": {
66
"include": [
77
"./src/combinatorics/",
8+
"./src/compression/",
89
"./src/data-structures/",
910
"./src/graphics/",
1011
"./src/graphs/others/",
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
(function (exports) {
2+
'use strict';
3+
4+
/**
5+
* Burrows Wheeler.
6+
*
7+
* This algorithm is commonly used as a step in the process of compressing data,
8+
* it rearranges a character string into runs of similar characters making algorithms
9+
* like move-to-front transform and run-length encoding reach higher compression
10+
* rates. This implementation only supports characters with ascii code greater than $(36) as
11+
* 36 is used at the process of encode and decode.
12+
*
13+
* @example
14+
* const burrows = require('path-to-algorithms/src/burrows-wheeler/burrows-wheeler').burrowsWheeler;
15+
* const s = 'ananabanana';
16+
* const encodedStr = burrows.encode(s);
17+
* console.log(encodedStr);
18+
* const decodedStr = burrows.decode(encodedStr);
19+
* console.log(decodedStr);
20+
*
21+
* @module compression/burrows-wheeler/burrows-wheeler
22+
*/
23+
exports.burrowsWheeler = function() {
24+
25+
}
26+
27+
/**
28+
* Consumes n^2 space.
29+
*/
30+
exports.burrowsWheeler.encode = function(str) {
31+
str = '$' + str;
32+
var combinations = [];
33+
for (let i = 0; i < str.length; i += 1) {
34+
combinations.push(str.substring(i) + str.substring(0, i));
35+
}
36+
var sorted = combinations.sort();
37+
var result = [];
38+
for (let i = 0; i < sorted.length; i += 1) {
39+
result.push(combinations[i][str.length - 1]);
40+
}
41+
return result.join('');
42+
}
43+
44+
exports.burrowsWheeler.decode = function(encodedStr) {
45+
const sortedCharSequence = encodedStr.split('').sort().join('');
46+
const leftSide = {};
47+
const rightSide = {};
48+
var maxEachCharLeft = {};
49+
var maxEachCharRight = {};
50+
51+
for (let i = 0; i < encodedStr.length; i += 1) {
52+
var idLeft = sortedCharSequence[i];
53+
if (idLeft in maxEachCharLeft) {
54+
maxEachCharLeft[idLeft] = maxEachCharLeft[idLeft] + 1;
55+
} else {
56+
maxEachCharLeft[idLeft] = 1;
57+
}
58+
idLeft += String(maxEachCharLeft[idLeft]);
59+
60+
var idRight = encodedStr[i];
61+
if (idRight in maxEachCharRight) {
62+
maxEachCharRight[idRight] = maxEachCharRight[idRight] + 1;
63+
} else {
64+
maxEachCharRight[idRight] = 1;
65+
}
66+
idRight += String(maxEachCharRight[idRight]);
67+
68+
leftSide[idLeft] = {char: sortedCharSequence[i], right: idRight};
69+
rightSide[idRight] = {char: encodedStr[i], left: idRight};
70+
}
71+
var result = '';
72+
var firstChar = sortedCharSequence[0];
73+
var searchChar = firstChar + '1';
74+
var endChar = searchChar;
75+
while (rightSide[leftSide[searchChar].right].left !== endChar) {
76+
result += leftSide[searchChar].char;
77+
searchChar = rightSide[leftSide[searchChar].right].left;
78+
}
79+
result += leftSide[searchChar].char;
80+
result = result.substring(1).split('').reverse().join('');
81+
return result;
82+
}
83+
84+
}(typeof exports === 'undefined' ? window : exports));
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var bw = require('../../../src/compression/burrows-wheeler/burrows-wheeler').burrowsWheeler;
2+
3+
describe('Burrows Wheeler', function () {
4+
'use strict';
5+
6+
it('should return "annnnb$aaaaa" for the entry "ananabanana"', function () {
7+
expect(bw.encode('ananabanana')).toEqual('annnnb$aaaaa');
8+
});
9+
10+
it('should return "ananabanana" for the entry "annnnb$aaaaa"', function () {
11+
expect(bw.decode('annnnb$aaaaa')).toEqual('ananabanana');
12+
});
13+
});

0 commit comments

Comments
 (0)