This post aim is to provide HackerRank algorithm solutions in JavaScript as there are so many of them available out there. I am not pretending to have the best algorithm possible but at least the following answers passed. There is no hints about the expected time complexity as there is on Codility, so many solutions can pass.

This kind of tests can help you going through Toptal interview process or any other big US company. If you wish to apply to Toptal, here is a referral link that will link your account to mine if you are successful!

This post in on going, I will add new solutions from time to time.

Warmup

Diagonal Difference

Given a square matrix of size N x N , calculate the absolute difference between the sums of its diagonals…

https://www.hackerrank.com/challenges/diagonal-difference

function main() {
    var n = parseInt(readLine());
    var a = [];
    for(a_i = 0; a_i < n; a_i++){
       a[a_i] = readLine().split(" ");
       a[a_i] = a[a_i].map(Number);
    }

    let sumPrimaryDiagonal = sumSecondaryDiagonal = 0;
    
    for (i = 0, len = a.length; i < len; i++){
        let line = a[i];
        sumPrimaryDiagonal += line[i];
        sumSecondaryDiagonal += line[(len - 1) - i];
    }
    console.log(Math.abs(sumPrimaryDiagonal - sumSecondaryDiagonal))
}

Plus Minus

Given an array of integers, calculate which fraction of its elements are positive, which fraction of its elements are negative, and which fraction of its elements are zeroes, respectively. Print the decimal value of each fraction on a new line…

https://www.hackerrank.com/challenges/plus-minus

function main() {
    var n = parseInt(readLine());
    arr = readLine().split(' ');
    arr = arr.map(Number);

    let positive = negative = zero = 0;
    for (i = 0; i < n; i++){
        let current = arr[i];
        if (current > 0){
            positive += 1;
        } else if (current < 0){
            negative += 1;            
        } else {
            zero += 1;
        }
        
    }
    console.log((positive / n).toFixed(6));
    console.log((negative / n).toFixed(6));
    console.log((zero / n).toFixed(6));
}

Staircase

Consider a staircase of size n = 4 :

   #
  ##
 ###
####

Observe that its base and height are both equal to n, and the image is drawn using # symbols and spaces. The last line is not preceded by any spaces. Write a program that prints a staircase of size n

https://www.hackerrank.com/challenges/staircase

function main() {
    var n = parseInt(readLine());
    for (i = 1; i <= n; i++){
        line = Array(n).fill(' ');
        for (j = 0; j < i; j++){
            line[j] = '#';
        }
        console.log(line.reverse().join(''))
    }
}

Time Conversion

Given a time in 12-hour AM/PM format, convert it to military (24-hour) time…

https://www.hackerrank.com/challenges/time-conversion

function main() {
    var time = readLine();
    let hours = time.substr(0, 2);
    let mins = time.substr(3, 2);
    let secs = time.substr(6, 2);
    let pmOrAm = time.substr(-2, 2);

    if (hours === '12' &amp;&amp; pmOrAm === 'AM'){
        console.log(`00:${mins}:${secs}`)
    } else if (hours !== '12' &amp;&amp; pmOrAm === 'PM'){
        console.log(`${parseInt(hours) + 12}:${mins}:${secs}`)
    } else {
        console.log(`${hours}:${mins}:${secs}`)
    }  
}

Circular Array Rotation

John Watson performs an operation called a right circular rotation on an array of integers, [a0, a1, … an-1]. After performing one right circular rotation operation, the array is transformed from [a0, a1, … an-1] to [an-1, a0, … an-2].

Watson performs this operation k times. To test Sherlock’s ability to identify the current element at a particular position in the rotated array, Watson asks q queries, where each query consists of a single integer, m, for which you must print the element at index m in the rotated array (i.e., the value of am)…

https://www.hackerrank.com/challenges/circular-array-rotation

function main() {
    var n_temp = readLine().split(' ');
    var n = parseInt(n_temp[0]);
    var k = parseInt(n_temp[1]);
    var q = parseInt(n_temp[2]);
    a = readLine().split(' ');
    a = a.map(Number);

    for (i = 0; i < k; i++){
        circularRotation(a);
    }

    for(var a0 = 0; a0 < q; a0++){
        var m = parseInt(readLine());
        console.log(a[m])
    }

    function circularRotation(array) {
        const lastValue = array[array.length - 1];
        array.pop();
        return array.unshift(lastValue);
    }
}

Strings

Mars Exploration

Letters in some of the SOS messages are altered by cosmic radiation during transmission. Given the signal received by Earth as a string, S , determine how many letters of Sami’s SOS have been changed by radiation….

https://www.hackerrank.com/challenges/mars-exploration

function main() {
    var S = readLine();
    const expectedSignal = 'SOS';
    let errorCount = 0;

    for (i = 0, len = S.length; i < len; i += 3) {
        const currentSignal = S.slice(i, i + 3);
        if (currentSignal === expectedSignal) continue;
        if (currentSignal[0] !== expectedSignal[0]) errorCount += 1;
        if (currentSignal[1] !== expectedSignal[1]) errorCount += 1;
        if (currentSignal[2] !== expectedSignal[2]) errorCount += 1;
    }
    console.log(errorCount);
}

Funny String

Suppose you have a String, S, of length N that is indexed from 0 to N - 1. You also have some String, R, that is the reverse of String S. S is funny if the condition |S[i] - S[i - 1]| = |R[i] - R[i -1]| is true for every character i from 1 to N - 1

https://www.hackerrank.com/challenges/funny-string

function processData(input) {
    const [tempT, ...cases] = input.split("\n");
    const T = parseInt(tempT);
    
    for (j = 0, lenCases = cases.length; j < lenCases; j += 1) {
        const currentCase = cases[j];
        let funny = true;
        for (i = 1, len = currentCase.length; i <= len - 1; i += 1){
            if (
                Math.abs(currentCase[i].charCodeAt(0) - currentCase[i - 1].charCodeAt(0)) 
                !== Math.abs(currentCase[len - i - 1].charCodeAt(0) - currentCase[len - i].charCodeAt(0))){
                funny = false;
                break;
            }
        }
        console.log(funny ? 'Funny' : 'Not Funny');
    }
}

Gemstones

John has discovered various rocks. Each rock is composed of various elements, and each element is represented by a lower-case Latin letter from ‘a’ to ‘z’. An element can be present multiple times in a rock. An element is called a gem-element if it occurs at least once in each of the rocks.

Given the list of N rocks with their compositions, display the number of gem-elements that exist in those rocks….

https://www.hackerrank.com/challenges/gem-stones

function processData(input) {
    const [tempN, ...rocks] = input.split("\n");
    const N = parseInt(tempN);

    const asciiA = 'a'.charCodeAt(0);
    const latinLetters = Array(26);
    
    // Fill latinLetters with empty arrays
    for (i = 0; i < 26; i += 1) {latinLetters[i] = [];}

    for (let i = 0; i < N; i += 1){
        const rock = rocks[i]
        for (let j = 0, rockLen = rock.length; j < rockLen; j += 1){
            latinLetters[rock[j].charCodeAt(0) - asciiA][i] = true;
        }
    }
    const gemElements = latinLetters.filter(
        (gem) => gem.filter((rockPresence) => rockPresence === true).length === N
    ).length

    console.log(gemElements);
}

Alternating Characters

Shashank likes strings in which consecutive characters are different. For example, he likes ABABA, while he doesn’t like ABAA. Given a string containing characters A and B only, he wants to change it into a string he likes. To do this, he is allowed to delete the characters in the string.

Your task is to find the minimum number of required deletions…..

https://www.hackerrank.com/challenges/alternating-characters

function processData(input) {
    const [tempT, ...strings] = input.split("\n");
    const T = parseInt(tempT);
    
    for (i = 0; i < T; i += 1){
        let string = strings[i];
        let deletions = 0;
        for (j = 1, len = string.length; j <= len; j += 1){
            if (string[j - 1] === string[j]) deletions += 1;
        }
        console.log(deletions);
    }
}

Sorting

Insertion Sort - Part 1

Given a sorted list with an unsorted number e in the rightmost cell, can you write some simple code to insert e into the array so that it remains sorted?

Print the array every time a value is shifted in the array until the array is fully sorted. The goal of this challenge is to follow the correct order of insertion sort.

Guideline: You can copy the value of e to a variable and consider its cell “empty”. Since this leaves an extra cell empty on the right, you can shift everything over until V can be inserted. This will create a duplicate of each value, but when you reach the right spot, you can replace it with e

https://www.hackerrank.com/challenges/insertionsort1

function processData(input) {
    const [Size, Arr] = input.split("\n");
    insertionSort(Arr.split(" ").map((val) => parseInt(val)));
}

function insertionSort(arr) {
    const e = arr[arr.length - 1];
    
    for(let i=arr.length-2; i>=0; i--) {
        let value = arr[i];
        if (value > e) {
            arr[i + 1] = value;            
            console.log(arr.join(' '))
            if (i === 0) {
                arr[i] = e;
                console.log(arr.join(' '))
            }
        } else if (value < e) {
            arr[i + 1] = e;
            console.log(arr.join(' '))
            break;
        }
       
    }
}

Insertion Sort - Part 2

In Insertion Sort Part 1, you sorted one element into an array. Using the same approach repeatedly, can you sort an entire unsorted array?

Guideline: You already can place an element into a sorted array. How can you use that code to build up a sorted array, one element at a time? Note that in the first step, when you consider an element with just the first element - that is already “sorted” since there’s nothing to its left that is smaller.

In this challenge, don’t print every time you move an element. Instead, print the array after each iteration of the insertion-sort, i.e., whenever the next element is placed at its correct position.

Since the array composed of just the first element is already “sorted”, begin printing from the second element and on….

https://www.hackerrank.com/challenges/insertionsort2

function processData(input) {
    const [SizeString, Arr] = input.split("\n");
    const Size = parseInt(SizeString);
    let arr = Arr.split(" ").map((val) => parseInt(val));

    for (i = 1; i <= Size - 1; i += 1){
        const toSort = arr.slice(0, i + 1);
        const rest = arr.slice(i + 1, Size)
        arr = insertionSort(toSort).concat(rest);
        console.log(arr.join(' '));
    } 
}

function insertionSort(arr) {
    const e = arr[arr.length - 1];
    for(let i=arr.length-2; i>=0; i--) {
        let value = arr[i];
        if (value > e) {
            arr[i + 1] = value;
            if (i === 0) {
                arr[i] = e;
            }
        } else if (value < e) {
            arr[i + 1] = e;
            break;
        }
    }
    return arr
}

Ice Cream Parlor

Each time Sunny and Johnny take a trip to the Ice Cream Parlor, they pool together m dollars for ice cream. On any given day, the parlor offers a line of n flavors. Each flavor, i, is numbered sequentially with a unique ID number from 1 to n and has a cost, ci , associated with it.

Given the value of m and the cost of each flavor for t trips to the Ice Cream Parlor, help Sunny and Johnny choose two flavors such that they spend their entire pool of money (m) during each visit. For each trip to the parlor, print the ID numbers for the two types of ice cream that Sunny and Johnny purchase as two space-separated integers on a new line. You must print the smaller ID first and the larger ID second.….

https://www.hackerrank.com/challenges/icecream-parlor

function processData(input) {
    const [tTemp, ...tripsTemps] = input.split("\n");
    const t = parseInt(tTemp);
    const trips = [];
    
    // prepare input
    for (i = 0; i < t; i += 1){        
        trips.push({
            m: parseInt(tripsTemps[3 * i]), // money
            f: parseInt(tripsTemps[1 + (3 * i)]), // flavors
            c: tripsTemps[2 + (3 * i)].split(' ').map((cost) => parseInt(cost)) // cost
        })
    }

    for (j = 0, len = trips.length; j < len; j += 1){
        const { m, f, c } = trips[j];
        let cost, compareCost;
        let costIndex, compareCostIndex;
        costLoop:
        for (k = 0; k < f - 1; k += 1){
           cost = c[k];
           if (cost >= m) continue;
           for (l = k + 1; l < f; l += 1){
            compareCost = c[l];
               if (cost + compareCost === m) {
                   costIndex = k + 1;
                   compareCostIndex = l + 1;
                   break costLoop;
               }
           }            
        }
        console.log(costIndex, compareCostIndex)
    }
}

Greedy

Luck Balance

Lena is preparing for an important coding competition that is preceded by N sequential preliminary contests. She believes in “saving luck”, and wants to check her theory. Each contest is described by two integers, Li and Ti:

  • Li is the amount of luck that can be gained by winning the contest. If Lena wins the contest, her luck balance will decrease by Li; if she loses it, her luck balance will increase by Li.
  • Ti denotes the contest’s importance rating. It’s equal to 1 if the contest is important, and it’s equal to 0 if it’s unimportant. If Lena loses no more than K important contests, what is the maximum amount of luck she can have after competing in all the preliminary contests? This value may be negative…

https://www.hackerrank.com/challenges/luck-balance

function processData(input) {
    const [firstLine, ...rest] = input.split("\n")
    const firstLineSplit = input.split(" ")
    const N = parseInt(firstLineSplit[0])
    const K = parseInt(firstLineSplit[1])
    const preparedInput = rest.map(item => {
        const tuppleSplit = item.split(" ");
        const L = parseInt(tuppleSplit[0])
        const T = parseInt(tuppleSplit[1])
        return [L, T];
    })
    const importantContest = preparedInput.filter(item => item[1] === 1)
    const importantContestByLuckAsc = importantContest.sort((a, b) => a[0] - b[0])
    const unimportantContest = preparedInput.filter(item => item[1] === 0)
 
    const importantContestByLuckAscToWin = importantContestByLuckAsc
        .splice(0, importantContest.length - K)
    const importantContestByLuckAscToLoose = importantContestByLuckAsc;
    
    const sumLuck = (sum, item) => sum + item[0];
    
    const sumImportantLuckToLoose = importantContestByLuckAscToWin.reduce(sumLuck, 0)
    const sumImportantLuckToGain = importantContestByLuckAscToLoose.reduce(sumLuck, 0)
    const sumUnimportantLuckToGain = unimportantContest.reduce(sumLuck, 0)

    console.log((sumImportantLuckToGain + sumUnimportantLuckToGain) - sumImportantLuckToLoose)    
}