Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gyaresu/3195064 to your computer and use it in GitHub Desktop.
Save gyaresu/3195064 to your computer and use it in GitHub Desktop.
HackerRank.com Challenge #2 (SpaceX) Solution in NodeJS
//
// HackerRank.com Challenge #2 (SpaceX Challenge)
// @hacker mediaupstream, aka Derek Anderson
//
// How to Win:
// 1. Install required npm packages: `npm install request sugar`
// 2. Modify the `username` and `password` variables below to match what you used to signup on
// hackerrank.com with
// 3. Run the script: `$ node hackerchallenge2-spacex.js`
// 4. Wait for about 40 minutes...
//
// The script can be optimized to run each game in parallel, probably.
//
var request = require('request'),
username = 'USERNAME HERE',
password = 'PASSWORD HERE',
gameStart = 1,
gameEnd = 10000;
// I am lazy, and sugar is sweet.
require('sugar');
//
// Quick lookup for our ghetto lexical parser
//
var tokens = {
zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9,
ten: 10, eleven: 11, twelve: 12, thirteen: 13, fourteen: 14, fifteen: 15, sixteen: 16,
seventeen: 17, eighteen: 18, nineteen: 19, twenty: 20, thirty: 30, fourty: 40, fifty: 50,
sixty:60, seventy: 70, eighty: 80, ninety:90
};
//
// Ghetto lexical parser, transforms phrases into numbers
// eg: "one thousand two hundred and six" becomes "1206"
//
var parseWords = function(str){
str = str.replace(',', '').replace('-', ' ').replace(' and', '').split(' ');
var results = [];
for(var i=0; i<str.length; i++){
var cur = str[i];
if(cur.has(/hundred|thousand|million|billion|trillion/)) continue;
var num = tokens[cur];
var next = str[i+1];
if(next){
if(next.has('hundred')) num += '00';
if(next.has('thousand')) num += '000';
if(next.has('million')) num += '00000';
if(next.has('billion')) num += '00000000';
}
results.push(num);
}
var sum = results.sum(function(n){
return parseInt(n, 10);
});
return sum;
};
//
// Decrypts a `string`, using ROT13 style encryption, given the `num` number offset
//
// @param {string} string The encrypted string, eg: 'lbhe zbz'
// @param {number} num The number offset to "shift" the `string` by
// @param {boolean} enc (optional) true to encrypt rather than decrypt
//
var decrypt = function(string, num, enc){
// dictionary of character codes, the numeric values of our ascii characters.
var dict = [
'abcdefghijklmnopqrstuvwxyz'.codes(),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.codes()
];
var buf = ''; // our encrypted / decrypted message will go here
// loop over our string, one character at a time
for(var i=0; i<string.length; i++){
var c = string.charCodeAt(i); // the current character code
var o = (c >= 97) ? dict[0] : dict[1]; // which dict to use
var index = o.findIndex(c); // index of the character in dict
var n = c; // encrypted / decrypted character code
if(c != 32 && c != 45 && c != 44){ // skip "space" "," and "-" chars
index = (!enc) ? (index-num) : (index+num); // shift up or down based on `enc`
// get the new character from our dictionary, given the shifted index from above
n = o.at(index, true);
}
// transform the number (n) into the character code (eg, "A")
// and append it to our buffer, which in turn will start to spell out the
// decrypted / encrypted message
buf += (n).chr();
}
return buf;
};
//
// Wrapper to decrypt with the `enc` flag set to true
//
var encrypt = function(string, num){
return decrypt(string, num, true);
};
//
// Log into HackerRank.com using the Request module
//
var login = function(username, pass, cb){
request({
url: 'https://www.hackerrank.com/users/sign_in',
form: {
'commit': 'Sign in',
'user[login]': username,
'user[password]': pass,
'user[remember_me]': 1
},
method: 'POST'
}, cb);
};
//
// Ask HackerRank.com for a game
// @param {number} n The number of game you want in the range 1-10000
// @param {function} cb A callback with response data
//
var getGame = function(n, cb){
request({
url: 'https://www.hackerrank.com/game.json',
method: 'POST',
form: {
n: n,
remote: true
}
}, cb);
};
//
// Helper method to submit an answer to HackerRank.com
// @param {object} d This object should be in the format:
// {
// id: 12943, // the game ID, not the same as the game number, eg 1-10000
// answer: 102, // your answer
// remote: true
// }
//
var submitAnswer = function(d, cb){
request({
url: 'https://www.hackerrank.com/game.json',
method: 'PUT',
form: d
}, cb);
};
//
// Crack an encrypted string
//
// we are taking advantage of the fact that all decrypted messages
// will contain lexical numbers, eg: "twelve", in essence a brute-force rot13
//
// @param {string} str The encrypted string to decrypt
// @returns {string} a decrypted string
//
var crack = function(str){
var result = '';
for(var i=0; i<35; i++){
var test = decrypt(str, i);
// console.log(test);
if(test.has(/thousand|hundred|and|zero|one|two|three|four|five|six|seven|eight|nine|ten/) ||
test.has(/eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen/) ||
test.has(/twenty|thirty|fourty|fifty|sixty|seventy|eighty|ninety/) ){
result = test;
break;
}
}
return result;
};
//
// Crack the whole game, from range `start` to `stop`
// Also submits the answer, so you'll want to login first before calling this...
//
var crackAll = function(start, stop){
start = start || 1;
stop = stop || 10000;
console.log('cracking '+ start +' to '+ stop +'... this will take awhile.');
for(var i=start; i<=stop; i++){
(function(level){
getGame(level, function(x,y, body){
// something went wrong... probably a server request limiting issue
if(body.has('<')) return console.log('Something went wrong on game #'+ level);
// all is well... process
body = JSON.parse(body);
if(body && body.game && body.game.cph_number){
var answer = crack(body.game.cph_number);
var number = parseWords( answer );
console.log('Message: '+ answer +', Number: '+ number);
if(isNaN( number )){
console.log('- Error');
console.log(level);
console.log(body.game.cph_number);
console.log(answer);
console.log(number);
} else {
submitAnswer({
id: body.game.id,
answer: number,
remote: true
}, function(x,y, resp){
if(!resp.has('Congrats')){
console.log('===');
console.log('incorrect answer: '+ level);
console.log(body.game.cph_number);
console.log(answer);
console.log(number);
}
});
}
}
});
})(i);
}
};
//
// login to hackerrank.com and start crackin'
//
login(username, password, function(err, res, body){
crackAll(gameStart, gameEnd);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment