From 344838c30ed59161bab9fb9a6af221779accd10a Mon Sep 17 00:00:00 2001 From: zhabinka Date: Wed, 9 Jan 2019 00:44:29 +0300 Subject: [PATCH] Added Run Length Encoding --- .../run-length-encoding.js | 32 ++++++++++ .../run-length-encoding.spec.js | 59 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 javascript/run-length-encoding/run-length-encoding.js create mode 100644 javascript/run-length-encoding/run-length-encoding.spec.js diff --git a/javascript/run-length-encoding/run-length-encoding.js b/javascript/run-length-encoding/run-length-encoding.js new file mode 100644 index 0000000..ac6a676 --- /dev/null +++ b/javascript/run-length-encoding/run-length-encoding.js @@ -0,0 +1,32 @@ +const encode = (str) => { + const iter = (s, arr) => { + if (s.length === 0) { + return arr; + } + const regex = new RegExp(`${s[0]}+`); + const charsGroup = s.match(regex)[0]; + + return iter(s.substr(charsGroup.length), arr.concat(charsGroup)); + }; + + const groups = iter(str, []); + + return groups + .map(el => (el.length === 1 ? el : `${el.length}${el[0]}`)) + .join(''); +}; + + +const decode = (str) => { + if (str === '') { + return str; + } + + return str + .match(/\d*.{1}/g) + .map(el => (el.length > 1 ? el : `1${el}`)) + .map(el => el.slice(-1).repeat(el.match(/\d*/))) + .join(''); +}; + +export { encode, decode }; diff --git a/javascript/run-length-encoding/run-length-encoding.spec.js b/javascript/run-length-encoding/run-length-encoding.spec.js new file mode 100644 index 0000000..c0d6da2 --- /dev/null +++ b/javascript/run-length-encoding/run-length-encoding.spec.js @@ -0,0 +1,59 @@ +import { encode, decode } from './run-length-encoding'; + +describe('run-length encode a string', () => { + test('encode empty string', () => { + expect(encode('')).toEqual(''); + }); + + test('single characters only are encoded without count', () => { + expect(encode('XYZ')).toEqual('XYZ'); + }); + + test('encode string with no single characters', () => { + expect(encode('AABBBCCCC')).toEqual('2A3B4C'); + }); + + test('encode string with single characters mixed with repeated characters', () => { + expect(encode('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB')).toEqual('12WB12W3B24WB'); + }); + + test('encode string with multiple whitespaces', () => { + expect(encode(' hsqq qww ')).toEqual('2 hs2q q2w2 '); + }); + + test('encode string with lowercase characters', () => { + expect(encode('aabbbcccc')).toEqual('2a3b4c'); + }); +}); + +describe('run-length decode a string', () => { + test('decode empty string', () => { + expect(decode('')).toEqual(''); + }); + + test('decode string with single characters only', () => { + expect(decode('XYZ')).toEqual('XYZ'); + }); + + test('decode string with no single characters', () => { + expect(decode('2A3B4C')).toEqual('AABBBCCCC'); + }); + + test('decode string with single characters mixed with repeated characters', () => { + expect(decode('12WB12W3B24WB')).toEqual('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'); + }); + + test('decode string with multiple whitespaces', () => { + expect(decode('2 hs2q q2w2 ')).toEqual(' hsqq qww '); + }); + + test('decode string with lowercase characters', () => { + expect(decode('2a3b4c')).toEqual('aabbbcccc'); + }); +}); + +describe('run-length encode and then decode', () => { + test('encode followed by decode gives original string', () => { + expect(decode(encode('zzz ZZ zZ'))).toEqual('zzz ZZ zZ'); + }); +});