Last active
April 4, 2020 14:37
-
-
Save Driim/e23871472539de70796d37567acff8b7 to your computer and use it in GitHub Desktop.
The solution of the coder problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const readline = require('readline'); | |
const defaultKeys = { | |
1: ['a', 'b', 'c'], | |
2: ['d', 'e', 'f'], | |
3: ['g', 'h', 'i'], | |
4: ['j', 'k', 'l'], | |
5: ['m', 'n', 'o'], | |
6: ['p', 'q', 'r', 's'], | |
7: ['t', 'u', 'v'], | |
8: ['w', 'x', 'y', 'z'], | |
} | |
function keysToMap(keys) { | |
const map = new Map(); | |
Object.keys(keys).forEach((key) => { | |
keys[key].forEach((letter, clicks) => { | |
map.set(letter, { key, clicks }); | |
}) | |
}) | |
return map; | |
} | |
function encode(message, keys) { | |
const keyMap = keysToMap(keys); | |
return [...message] | |
.reduce((result, letter, i) => { | |
const char = letter.toLowerCase(); | |
const { key, clicks } = keyMap.get(char); | |
const code = (clicks + i + 1) % keys[key].length; | |
const encoded = (char !== letter) | |
? keys[key][code].toUpperCase() | |
: keys[key][code]; | |
return result.concat(encoded); | |
}, ''); | |
} | |
function decode(message, keys) { | |
const keyMap = keysToMap(keys); | |
return [...message] | |
.reduce((result, letter, index) => { | |
const char = letter.toLowerCase(); | |
const { key, clicks } = keyMap.get(char); | |
const code = keys[key].findIndex((_value, i) => { | |
return (i - clicks + 1 + index) % keys[key].length === 0 | |
}); | |
const decoded = (char !== letter) | |
? keys[key][code].toUpperCase() | |
: keys[key][code]; | |
return result.concat(decoded); | |
}, ''); | |
} | |
async function run() { | |
const args = process.argv.slice(2); | |
switch (args[0]) { | |
case 'file': { | |
let keys = defaultKeys; | |
const file = args[1]; | |
if (!file) { | |
throw new Error('need file'); | |
} | |
const keysFile = args[2]; | |
if (keysFile) { | |
keys = JSON.parse(await fs.promises.readFile(keysFile)); | |
} | |
const fileStream = fs.createReadStream(file); | |
const lines = readline.createInterface({ | |
input: fileStream, | |
crlfDelay: Infinity | |
}); | |
lines.on('line', (line) => { | |
if (line === '#') | |
return; | |
console.log(decode(line, keys)); | |
}); | |
break; | |
} | |
case 'test': { | |
/* | |
* I decided not to use assert, instead I made the tests more visual. | |
*/ | |
console.log('\nEncoding Tests'); | |
console.log(`ABCD encoded: ${encode('ABCD', defaultKeys)} - BACE`); | |
console.log(`IhateSMS encoded: ${encode('IhateSMS', defaultKeys)} - GgaudQNS`); | |
console.log(`ccd encoded: ${encode('ccd', defaultKeys)} - abd`); | |
console.log('\nDecoding Tests'); | |
console.log(`BACE decoded: ${decode('BACE', defaultKeys)} - ABCD`); | |
console.log(`GgaudQNS decoded: ${decode('GgaudQNS', defaultKeys)} - IhateSMS`); | |
console.log(`abd decoded: ${decode('abd', defaultKeys)} - ccd`); | |
break; | |
} | |
default: { | |
throw new Error('You should call: "node coder.js test" or "node coder.js file <input> <keymap> keymap is optional"'); | |
} | |
} | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment