Cover image by Pexels from Pixabay
Introduction
These are my solutions to a set of programming challenges by scrimba dubbed JavaScriptmas which ran from December 01, 2020 to December 24, 2020.
These challenges are mostly beginner programming problems. You might encounter one or two in a technical interview for an entry level job. If you are a beginner in JavaScript, it might help consolidate your JavaScript knowledge. I have documented my solutions here. The same solutions can also be found on Scrimba by following the link below each challenge description. You are free to play with the code.
If you are interested, I have also compiled these challenges in a GitHub repository which you can find at the link below.You are free to fork it under your own account and modify the solutions.
nibble0101 / javascriptmas
Beginner-friendly coding challenges in JavaScript.
Javascriptmas
This is a set of programming challenges from scrimba.com dubbed 24 days of JavaScriptmas. It runs from December 01, 2020 - December 24, 2020. Each day a JavaScript challenge is posted and participants are free to attempt and share their solution on twitter. If you want to contribute to this set of solutions, read the contribution instructions.
Challenges
Candies
Solution 1
function candies(children, candy) {
return Math.floor(candy / children) * children;
}
Solution 2
function candies(children, candy) {
return candy - (candy % children);
}
Deposit profit
Solution
function depositProfit(deposit, rate, threshold) {
const years = Math.log(threshold / deposit) / Math.log(1 + rate / 100);
return Number.isInteger(years) ? years +
…If you have a better solution or notice an inefficient or incorrect solution, feel free to open a pull request after reading the contribution guidelines or leave your solution in the comments section below. You never know someone might find it useful. I have written unit tests in jest which you can find at the GitHub repository.
Challenges
n
children have got m
pieces of candy. They went to eat as much candy as they can, but each child must eat exactly the same amount of candy as any other child. Determine how many pieces of candy will be eaten by all the children together. Individual pieces of candy cannot be split.
Example
For n = 3
and m = 10
, the output should be candies(n, m) = 9
. Each child will eat 3 pieces. So the answer is 9.
/**
* @params integer
* @params integer
* @returns integer
*/
function candies(children, candy) {
}
Solution 1
function candies(children, candy) {
return Math.floor(candy / children) * children;
}
Solution 2
function candies(children, candy) {
return candy - (candy % children);
}
You have deposited a specific amount of dollars into your bank account. Each year your balance increases at the same growth rate. Find out how long it would take for your balance to pass a specific threshold with the assumption that you don't make any additional deposits.
Example
For deposit = 100
, rate = 20
and threshold = 170
, the output should be depositProfit(deposit, rate, threshold) = 3
. Each year the amount of money on your account increases by 20%. It means that throughout the years your balance would be)
- year 0: 100
- year 1: 120
- year 2: 144
- year 3: 172.8
Thus, it will take 3 years for your balance to pass the threshold, which is the answer.
/**
*@params number
*@params number
*@params number
*@returns number
*/
function depositProfit(deposit, rate, threshold) {
}
Solution
function depositProfit(deposit, rate, threshold) {
const years = Math.log(threshold / deposit) / Math.log(1 + rate / 100);
return Number.isInteger(years) ? years + 1 : Math.ceil(years);
}
Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a two-dimensional array.
Example
-
chunkyMonkey(["a", "b", "c", "d"], 2)
should return[["a", "b"], ["c", "d"]]
-
chunkyMonkey([0, 1, 2, 3, 4, 5], 4)
should return[[0, 1, 2, 3], [4, 5]]
/**
*@params any[]
*@params integer
*@returns Array<Array<any>>
*/
function chunkyMonkey(values, size) {
}
Solution
function chunkyMonkey(values, size) {
const chunkedArray = [];
const arrayLength = values.length;
for (let i = 0; i < arrayLength; i += size) {
chunkedArray.push(values.slice(i, i + size));
}
return chunkedArray;
}
Given a year, return the century it is in. The first century spans from the year 1 up to and including the year 100. The second century from the year 101 up to and including the year 200.
Example
- For
year = 1905
, the output should becenturyFromYear(year) = 20
. - For
year = 1700
, the output should becenturyFromYear(year) = 17
.
/**
*@params integer
*@returns integer
*/
function centuryFromYear(num) {
}
Solution
function centuryFromYear(num) {
return num % 100 ? Math.ceil(num / 100) : num / 100;
}
Reverse the provided string.You may need to turn the string into an array before you can reverse it. Your result must be a string.
Examples
-
reverseAString("hello")
returns"olleh"
-
reverseAString("Howdy")
returns"ydwoH"
/**
*@params string
*@returns string
*/
function reverseAString(str) {
}
Solution 1
function reverseAString(str) {
return str.split('').reverse().join('');
}
Solution 2
function reverseAString(str) {
let reversedString = ''; const { length } = str;
for (let i = 0; i < length; i += 1) {
reversedString = str[i] + reversedString;
}
return reversedString;
}
Given an array of strings, sort them in the order of increasing lengths. If two strings have the same length, their relative order must be the same as in the initial array.
Example
/**
*@params [string]
*@returns [string]
*/
function sortByLength(strs) {
}
Solution
function sortByLength(strs) {
return strs.sort((a, b) => a.length - b.length);
}
You are given a string str
that consists of only lowercase English letters. If vowels ('a', 'e', 'i', 'o', 'u') are given a value of 1 and consonants are given a value of 2,return the sum of all of the letters in the input string.
Example
- For
str = "abcde"
the output should becountVowelConsonant(str) = 8
.
/**
*@params string
*@returns integer
*/
function countVowelConsonant(str) {
}
Solution
function countVowelConsonant(str) {
return str.split('').reduce((count, char) => ('aeiou'.indexOf(char) === -1 ? count + 2 : count + 1), 0);
}
In this challenge a casino has asked you to make an online dice that works just like it would in real life. Using the dice face that represents ‘one’ which has been made for you, make the faces for ‘two’, ‘three’, ‘four’, ‘five’ and ‘six’. Now when the users clicks the dice on the screen the dice is expected to show one of the faces randomly.
Note
You can check the scrimba playground below for the HTML, CSS and JavaScript files.
Given a positive integer num
, return the sum of all odd Fibonacci numbers that are less than or equal to num
. The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5, 8. For example sumOddFibonacciNumbers(10)
should return 10 because all odd Fibonacci numbers less than or equal to 10 are 1, 1, 3, 5.
Examples
-
sumOddFibonacciNumbers(10)
should return10
-
sumOddFibonacciNumbers(1000)
should return1785
-
sumOddFibonacciNumbers(4000000)
should return4613732
/**
*@params integer
*@returns integer
*/
function sumOddFibonacciNumbers(num){
}
Solution
function sumOddFibonacciNumbers(num) {
if (num < 2) return 2;
const cache = [1, 1];
let sumOfOddFibNums = 2;
while (cache[0] + cache[1] <= num) {
const nextFibNum = cache[0] + cache[1];
if (nextFibNum % 2) {
sumOfOddFibNums += nextFibNum;
}
cache[0] = cache[1];
cache[1] = nextFibNum;
}
return sumOfOddFibNums;
}
Given an array of integers, find the pair of adjacent elements that has the largest product and return the product.
Examples
- For
inputArray = [3, 6, -2, -5, 7, 3]
adjacentElementsProduct(inputArray)
should return 21 because 7 and 3 produce the largest product
/**
*@params number[]
*@returns integer
*/
function adjacentElementsProduct(nums){
}
Solution
function adjacentElementsProduct(nums) {
if (nums.length < 2) return nums[0];
let product = nums[0] * nums[1];
const lastIndex = nums.length - 1;
for (let i = 1; i < lastIndex; i += 1) {
if (nums[i] * nums[i + 1] > product) {
product = nums[i] * nums[i + 1];
}
}
return product;
}
You are given an array of integers representing coordinates of obstacles situated on a straight line. Assume that you are jumping from the point with coordinate 0 to the right. You are allowed only to make jumps of the same length represented by some integer. Find the minimal length of the jump enough to avoid all obstacles.
Examples
- For
inputArray = [5, 3, 6, 7, 9]
avoidObstacles(inputArray)
should return 4.
/**
*@params number[]
*@returns integer
*/
function avoidObstacles(nums) {
}
Solution
function avoidObstacles(nums) {
if (!Array.isArray(nums) || !nums.length) {
throw new Error('Requires integer array');
}
const largestObstacle = Math.max(...nums);
/*
OR:
const largestObstacle = nums.reduce((prev, curr) => {
return curr > prev ? curr : prev;
});
*/
for (let jump = 2; jump <= largestObstacle; jump += 1) {
if (nums.every((obstacle) => obstacle % jump !== 0)) {
return jump;
}
}
return largestObstacle + 1;
}
Check if the given string is a correct time representation of the 24-hour clock.
Examples
- For
time = "13:58"
,validTime(time)
should returntrue
. - For
time = "25:51"
,validTime(time)
should returnfalse
. - For
time = "02:76"
,validTime(time)
should returnfalse
.
/**
*@params string
*@returns boolean
*/
function validTime(str){
}
Solution
function validTime(str) {
if (typeof str !== 'string' || !str.includes(':')) {
return false;
}
let [hour, minutes] = str.trim().split(':');
hour = hour.trim();
minutes = minutes.trim();
if (/\D/.test(hour) || /\D/.test(minutes)) {
return false;
}
hour = parseInt(hour, 10);
minutes = parseInt(minutes, 10);
return hour >= 0 && hour < 24 && minutes >= 0 && minutes < 60;
}
Given an array of integers, remove each kth element from it.
Example
- For
inputArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
andk = 3
the output ofextractEachKth(inputArray, k)
should be[1, 2, 4, 5, 7, 8, 10]
.
/**
*@params number[]
*@params integer
*@returns number[]
*/
function extractEachKth(nums, index){
}
Solution
function extractEachKth(nums, index) {
return nums.filter((__, i) => (i + 1) % index !== 0);
}
Array maximal adjacent difference
Given an array of integers, find the maximal absolute difference between any two of its adjacent elements.
Examples
- For
inputArray = [2, 4, 1, 0]
arrayMaximalAdjacentDifference(inputArray)
should return 3 - For
inputArray = [2, 9, 1, 0]
arrayMaximalAdjacentDifference(inputArray)
should return 8
/**
*@params number[]
*@returns number
*/
function arrayMaximalAdjacentDifference(nums){
}
Solution
function arrayMaximalAdjacentDifference(nums) {
if (!Array.isArray(nums) || !nums.length) {
throw new Error('Invalid argument');
}
if (nums.length < 2) return nums[0];
let maxAbsoluteDiff = Math.abs(nums[0] - nums[1]);
const lastIndex = nums.length - 1;
for (let i = 1; i < lastIndex; i += 1) {
const diff = Math.abs(nums[i] - nums[i + 1]);
if (maxAbsoluteDiff < diff) {
maxAbsoluteDiff = diff;
}
}
return maxAbsoluteDiff;
}
In this challenge, one is required to make carousel work using JavaScript. The HTML, CSS and JavaScript files can be found in the Scrimba playground by following the link below.
Solution
const previousButton = document.querySelector('.previous');
const nextButton = document.querySelector('.next');
const allImages = document.querySelectorAll('img.card');
const gallery = document.querySelector('.gallery');
const imageCount = allImages.length;
let visibleImageId = 0;
function togglePreviousButtonBlur(action = 'INCREASE_OPACITY') {
if (action === 'LOWER_OPACITY') {
previousButton.style.opacity = 0.3;
return;
}
previousButton.style.opacity = 1;
}
function toggleNextButtonBlur(action = 'INCREASE_OPACITY') {
if (action === 'LOWER_OPACITY') {
nextButton.style.opacity = 0.3;
return;
}
nextButton.style.opacity = 1;
}
function translateGallery(visibleImageId) {
const currentVisibleImage = document.querySelector('.current');
currentVisibleImage.classList.remove('current');
allImages[visibleImageId].classList.add('current');
gallery.style.transform = `translateX(${visibleImageId * -220}px)`;
}
function previousButtonClickHandler() {
if (visibleImageId === 0) return;
translateGallery(--visibleImageId);
if (visibleImageId === 0) {
togglePreviousButtonBlur('LOWER_OPACITY');
return;
}
togglePreviousButtonBlur();
toggleNextButtonBlur();
}
function nextButtonClickHandler() {
if (visibleImageId === imageCount - 1) return;
translateGallery(++visibleImageId);
if (visibleImageId === imageCount - 1) {
toggleNextButtonBlur('LOWER_OPACITY');
return;
}
toggleNextButtonBlur();
togglePreviousButtonBlur();
}
previousButton.addEventListener('click', previousButtonClickHandler);
nextButton.addEventListener('click', nextButtonClickHandler);
Transform a given sentence into a new one with dashes between each two consecutive letters.
Example
- For
inputStr = "aba caba"
,insertDashes(inputStr)
should return"a-b-a c-a-b-a"
.
/**
*@params string
*@returns string
*/
function insertDashes(str){
}
Solution
function insertDashes(str) {
return str
.split(' ')
.map((word) => word.split('').join('-'))
.join(' ');
}
Given a string, find the number of different characters in it.
Example
- For
inputStr = "cabca"
,differentSymbolsNaive(inputStr)
should return 3 because there are three different characters a, b and c.
/**
*@params string
*@returns number
*/
function differentSymbolsNaive(str){
}
Solution 1
function differentSymbolsNaive(str) {
if (typeof str !== 'string') {
throw new Error('Invalid input');
}
let uniqueChars = '';
const { length } = str;
for (let i = 0; i < length; i += 1) {
if (!uniqueChars.includes(str[i])) {
uniqueChars += str[i];
}
}
return uniqueChars.length;
}
Solution 2
function differentSymbolsNaive(str) {
if (typeof str !== 'string') {
throw new Error('Invalid input');
}
return new Set(str).size;
}
Solution 3
function differentSymbolsNaive(str) {
if (typeof str !== 'string') {
throw new Error('Invalid input');
}
const uniqueChars = {};
return str.split('').reduce((charCount, char) => {
if (uniqueChars[char]) {
return charCount;
}
uniqueChars[char] = char;
return charCount + 1;
}, 0);
}
Given an array of integers, for each position i
, search among the previous positions for the last (from the left) position that contains a smaller value. Store that value at position i
in the answer. If no such value can be found, store -1 instead.
Examples
- For
inputArray = [3, 5, 2, 4, 5]
,arrayPreviousLess(inputArray)
should return[-1, 3, -1, 2, 4]
.
/**
*@params number[]
*@returns number[]
*/
function arrayPreviousLess(nums) {
}
Solution 1
function arrayPreviousLess(nums) {
if (!Array.isArray(nums)) {
throw new Error('Invalid input');
}
const { length } = nums;
const arrayClone = [...nums];
// eslint-disable-next-line no-restricted-syntax
outerLoop: for (let i = 0; i < length; i += 1) {
if (typeof nums[i] !== 'number') {
throw new Error('Invalid input');
}
for (let j = i - 1; j >= 0; j -= 1) {
if (nums[i] > nums[j]) {
arrayClone[i] = nums[j];
// eslint-disable-next-line no-continue
continue outerLoop;
}
}
arrayClone[i] = -1;
}
return arrayClone;
}
Solution 2
function arrayPreviousLess(nums) {
if (!Array.isArray(nums)) {
throw new Error('Invalid input');
}
const arrayClone = [...nums];
nums.forEach((element, index) => {
if (typeof element !== 'number') {
throw new Error('Invalid input');
}
for (let i = index - 1; i >= 0; i -= 1) {
if (element > nums[i]) {
arrayClone[index] = nums[i];
return;
}
}
arrayClone[index] = -1;
});
return arrayClone;
}
Check whether the given string is a subsequence of the plaintext alphabet
Examples
- For
inputStr = "effg"
,alphabetSubsequence(inputStr)
should returnfalse
- For
inputStr = "cdce"
,alphabetSubsequence(inputStr)
should returnfalse
- For
inputStr = "ace"
,alphabetSubsequence(inputStr)
should returntrue
- For
inputStr = "bxz"
,alphabetSubsequence(inputStr)
should returntrue
/**
*@param string
*@returns boolean
*/
function alphabetSubsequence(str){
}
Solution
function alphabetSubsequence(str) {
if (typeof str !== 'string' || !str.length) {
throw new Error('Invalid input');
}
const lowerCaseStr = str.toLowerCase();
const lastIndex = str.length - 1;
for (let i = 0; i < lastIndex; i += 1) {
const thisCharCode = lowerCaseStr.charCodeAt(i);
const nextCharCode = lowerCaseStr.charCodeAt(i + 1);
if (nextCharCode <= thisCharCode) {
return false;
}
if (thisCharCode < 97 || thisCharCode > 122) {
return false;
}
}
const lastCharCode = lowerCaseStr[lastIndex];
return !(lastCharCode < 97 || lastCharCode > 122);
}
GoDaddy makes a lot of different top-level domains available to its customers. A top-level domain is one that goes directly after the last dot (.
) in the domain name, for example .com
in example.com
. To help the users choose from available domains, GoDaddy is introducing a new feature that shows the type of the chosen top-level domain. You have to implement this feature. To begin with, you want to write a function that labels the domains as "commercial", "organization", "network" or "information" for .com, .org, .net or .info respectively. For the given list of domains, return the list of their labels.
Example
- For
domains = ["en.wiki.org", "codefights.com", "happy.net", "code.info"]
,domainType(domains)
should return["organization", "commercial", "network", "information"]
.
/**
*@params Array<string>
*@returns Array<string>
*/
function domainType(domains){
}
Solution
function domainType(domains) {
return domains.map((domain) => {
const domainNameComponents = domain.split('.');
const topLevelDomain = domainNameComponents[domainNameComponents.length - 1];
switch (topLevelDomain) {
case 'com':
return 'commercial';
case 'org':
return 'organization';
case 'net':
return 'network';
case 'info':
return 'information';
default:
}
});
}
You have two integer arrays a
and b
, and an integer target value v
. Determine whether there is a pair of numbers, one number taken from a
and another from b
that can be added together to get a sum of v
. Return true
if such a pair exists, otherwise return false
.
Examples
- For
a = [1, 2, 3]
,b = [10, 20, 30, 40]
andv = 42
,sumOfTwo(a, b, v)
should returntrue
.
/**
*@params number[]
*@params number[]
*@params number
*@returns boolean
*/
function sumOfTwo(nums1, nums2, value){
}
Solution
function sumOfTwo(nums1, nums2, value) {
for (let i = 0; i < nums1.length; i += 1) {
for (let j = 0; j < nums2.length; j += 1) {
if (nums1[i] + nums2[j] === value) {
return true;
}
}
}
return false;
}
Given a rectangular matrix and an integer column, return an array containing the elements of the columnth column of the given matrix. The leftmost column is the 0th column.
Example
- For
inputMatrix = [[1, 1, 1, 2], [0, 5, 0, 4], [2, 1, 3, 6]]
andcolumn = 2
,extractMatrixColumn(inputMatrix, column)
should return[1, 0, 3]
.
/**
*@params Array<Array<number>>
*@returns number[]
*/
function extractMatrixColumn(matrix, column) {
}
Solution
function extractMatrixColumn(matrix, column) {
return matrix.map((row) => row[column]);
}
In this challenge, you are expected to make a Social Media Character Counter! You need to display the available characters LEFT. Using the Keydown event should help you here. When the characters reach 20 and below, we want them to turn red. So we will use Javascript to add that styling to it. If the characters drop below 0, we want the button to be disabled BUT if there are only 0 characters left, we should still be able to tweet.
You can find the HTML, CSS and JavaScript files at the link below.
Make a counter that increments every 75 milliseconds in the spin()
function and display whether the player wins or losses in the stop()
function.
Note
Check the HTML, CSS and JavaScript files on Scrimba by following the link below.
You can also fork the GitHub repository for the challenges in the link below.
nibble0101 / javascriptmas
Beginner-friendly coding challenges in JavaScript.
If you found these challenges useful, feel free to tweet or share them on any other platform. Others might find them useful too.
Top comments (3)
My compliments for the name of the repo/project :)
great work nibble ❣️
Thanks