Day 4/30 Days of CodeWars: JavaScript Edition

nats_tech_notes

Nat's Tech Notes

Posted on June 16, 2022

Day 4/30 Days of CodeWars: JavaScript Edition

CodeWars challenges solved
1) Highest and Lowest (7 kyu)
2) Sum of the first nth term of Series (7 kyu)
3) Remove the minimum (7 kyu)


Kata 1: Highest and Lowest

Instructions

In this little assignment you are given a string of space separated numbers, and have to return the highest and lowest number.

Examples

highAndLow("1 2 3 4 5");  // return "5 1"
highAndLow("1 2 -3 4 5"); // return "5 -3"
highAndLow("1 9 3 4 -5"); // return "9 -5"
Enter fullscreen mode Exit fullscreen mode

Notes

  • All numbers are valid Int32, no need to validate them.
  • There will always be at least one number in the input string.
  • Output string must be two numbers separated by a single space, and highest number is first.

Breaking down the problem with P.R.E.P.

Parameters
The function expects one parameter: a string of one or more valid, space separated numbers.

Returns
The function should return one value: a string with the highest number, followed by a single space and ending with the lowest number.

Examples
The following test cases are provided by CodeWars.

("8 3 -5 42 -1 0 0 -9 4 7 4 -4"), "42 -9"
("1 2 3"), "3 1"
Enter fullscreen mode Exit fullscreen mode

The string of numbers between the parentheses are the numbers passed to the function, followed by the string of numbers that should be returned from the function.

Pseudo code
See pseudo code section for each solution


Solution 1: Looping over the numbers

Pseudo code

1) Turn the string of numbers into an array of numbers.
2) Declare variable 'highest' and set it to the first number.
3) Declare a variable 'lowest' and set it to the first number.
4) Loop over the array starting at index 1.
5) Set 'highest' to the current number in the loop if it's higher.
6) Set 'lowest' the current number in the loop if it's lower.
7) Return a string of highest and lowest with a space in between.
Enter fullscreen mode Exit fullscreen mode

Solution

function highAndLow(numbers){
  const arr = numbers.split(' ').map(Number);
  let highest = arr[0];
  let lowest = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] > highest) highest = arr[i];
    if (arr[i] < lowest) lowest = arr[i];
  }
  return highest + ' ' + lowest;
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) The .split() string method splits a string into substrings and returns an array of those substrings. The splitting is done based on the parameter provided when calling the method - in this case a single space signifying it should be split whenever a single space is encountered.

2) The .map() array method is used in combination with the Number object to convert the substrings returned from the .split() method into actual numbers (instead of strings containing numbers). This is important to avoid errors when we do the comparisons inside the for loop.

3) When declaring the highest and lowest variables, we use the let keyword, since their values will change. Both variables are initialized with a default value of whatever number is first in the array. This is done using the bracket notation - arr[0].

4) Unlike most loops when iterating over an array, the loop starts at index 1 instead of index 0 since we just want to compare if any values besides the first number in the array are higher or lower than the current highest and lowest value. We loop until the end of the array and increment the index by 1 each iteration. This is fairly standard procedure in cases like these.

5) Since only one action/line of code is executed for each if statement, the {} can be omitted.

6) Because of type coercion in JavaScript, the highest variable is converted to a string when the ' ' is added to it and it remains a string when the lowest variable is added.


Solution 2: Sorting the numbers

Pseudo code

1) Turn the string of numbers into an array of numbers.
2) Sort the array of numbers from lowest to highest.
3) Return a string with the last and first numbers of the array.
Enter fullscreen mode Exit fullscreen mode

Solution

function highAndLow(numbers){
  const sortedNums = numbers.split(' ').sort((a, b) => a - b);
  return [sortedNums[sortedNums.length - 1], sortedNums[0]].join(' ');
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) The .sort() array method loops over an array, sorts its values and returns the sorted array. In this case, it is passed a callback function that compares two numbers - a and b - and sorts them accordingly. So if b is smaller than a, the b value will be pushed to the left of the a value until all values have been sorted correctly.

2) Inside the return statement, a new array is created containing the last number in the sortedNums array (sortedNums[sortedNums - 1]) and the first number (sortedNums[0]). That array is then converted into a string using the .join() array method, which similar to the .split() method receives a parameter signifying how the array should be joined into a string.


Solution 3: Extracting the max and min number

Pseudo code

1) Turn the string of numbers into an array of numbers.
2) Get the max (highest) number out of all the numbers.
3) Get the min (lowest) number out of all the numbers.
4) Return a string containing the highest and lowest numbers.
Enter fullscreen mode Exit fullscreen mode

Solution

function highAndLow(numbers){
  const numArr = numbers.split(' ');
  return `${Math.max(...numArr)} ${Math.min(...numArr)}`;
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) A template literal is returned containing two expressions calculating the largest and smallest number in numArr. Expressions and variables inside template literals are denoted with the ${code} syntax.

2) The Math.max() and Math.min() functions are used to return the largest and smallest numbers respectively from a list of numbers passed as parameters.

3) The spread operator (...) has many use cases, but in this case is used to turn the array of numbers into individual arguments that are passed to the Math.max() and Math.min() functions.


Kata 2: Sum of the first nth term of Series

Instructions

Your task is to write a function which returns the sum of the following series up to nth term (parameter).

Series: 1 + 1/4 + 1/7 + 1/10 + 1/13 + 1/16 +...
Enter fullscreen mode Exit fullscreen mode

Rules:

  • You need to round the answer to 2 decimal places and return it as String.
  • If the given value is 0 then it should return 0.00
  • You will only be given Natural Numbers as arguments.

Examples:(Input --> Output)

1 --> 1 --> "1.00"
2 --> 1 + 1/4 --> "1.25"
5 --> 1 + 1/4 + 1/7 + 1/10 + 1/13 --> "1.57"
Enter fullscreen mode Exit fullscreen mode

Breaking down the problem with P.R.E.P.

Parameters
The function expects one parameter: a natural number representing the amount of numbers/fractions that should be added to the total sum.

Returns
The function should return one value: a string containing a number.

The number inside the string should be 0.00 if the argument the function is called with is 0. Otherwise, it should be a number rounded up to two decimal places.

Examples
The following test cases are provided by CodeWars. These do not include the ones mentioned in the instructions above.

(3), "1.39"
(4), "1.49"
Enter fullscreen mode Exit fullscreen mode

The first number represents the nth number passed to the function as an argument, followed by the string that should be returned from the function.

Pseudo code
See pseudo code section for each solution


Solution 1: Looping n times to add to the sum

Pseudo code

1) Declare a variable 'sum' with a default value of 0.
2) Loop n amount of times to add the calculation to the sum.
3) Return the sum.
Enter fullscreen mode Exit fullscreen mode

Solution

function SeriesSum(n) {
   let sum = 0;
   for (let i = 0; i < n; i++) {
     sum += 1 / (3 * i + 1);
   }
   return sum.toFixed(2);
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) Each loop, a fraction is added to the sum value, which is calculated by multiplying the current index by 3 and then adding 1 to that. So the first iteration the fraction would be 1/1 since 3 * 0 = 0 + 1 = 1, followed by 1/4 since 3 * 1 = 3 + 1 = 4 and so forth. However, if n is 0, the loop won't iterate since i must be smaller than n for the loop to execute and 0 is not smaller than 0.

2) The .toFixed() method is used to format the number to its correct amount of decimals, in this case 2.


Solution 2: Reducing an array of n length to its sum

Pseudo code

1) Create an array of n items.
2) Loop over the array.
3) Each iteration, add the calculation to the sum value.
4) Return the sum.
Enter fullscreen mode Exit fullscreen mode

Solution

function SeriesSum(n) {
   return [...Array(n)].reduce((sum, curr, i) 
       => sum + 1 / (3 * i + 1), 0).toFixed(2);
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) The Array object is used in combination with [] and the spread syntax (seen in solution 3 of kata 1) to create an array holding n amount of undefined values. The number of items the array should contain is passed to the object as a parameter.

2) The .reduce() array method is then used to loop over the newly created array and execute a reducer callback function. The callback function can receive 4 parameters: the sum, also referred to as the accumulator or previous value, the current value, a.k.a. the value in the current iteration of the loop, the index and the array object which can access the array itself. Not all parameters need to be used - and in fact often times only the first two are - but they do always occur in the same order. Since we need access to the index parameter, the 2nd parameter is also mentioned, even though it is not actually used.


Solution 3: Recursively calculating the sum

Pseudo code

1) Return the formatted sum if the recursive base case is reached.
2) Otherwise return the recursive function and sum calculation.
Enter fullscreen mode Exit fullscreen mode

Solution

function SeriesSum(n, sum = 0) {
   return n === 0 
     ? sum.toFixed(2) 
     : SeriesSum(n - 1, sum += 1 / (3 * n - 2));
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) A conditional ternary operator is an alternative to an if else statement. It executes the code after the ? if the condition specified is met and the code after the : it's not met.

2) A recursive function is used to calculate the sum. Recursion can be a rather hard concept to grasp. Essentially, a recursive function is a function that calls itself inside of itself. Since this basically creates a loop, a recursive function always needs a base case that specifies when the function should stop calling itself. The recursive function in this example first calls itself with the n value. Each subsequent iteration, it subtracts 1 from n until the base case is reached, in this case until n reaches 0. It then stops calling itself, exiting the loop and returns a value, the formatted sum value.


Kata 3: Remove the minimum

Instructions

The museum of incredible dull things wants to get rid of some exhibitions. Miriam, the interior architect, comes up with a plan to remove the most boring exhibitions. She gives them a rating, and then removes the one with the lowest rating.

However, just as she finished rating all exhibitions, she's off to an important fair, so she asks you to write a program that tells her the ratings of the items after one removed the lowest one. Fair enough.

Task
Given an array of integers, remove the smallest value. Do not mutate the original array/list. If there are multiple elements with the same value, remove the one with a lower index. If you get an empty array/list, return an empty array/list.

Don't change the order of the elements that are left.

Examples

* Input: [1,2,3,4,5], output= [2,3,4,5]
* Input: [5,3,2,1,4], output = [5,3,2,4]
* Input: [2,2,1,2,1], output = [2,2,2,1]
Enter fullscreen mode Exit fullscreen mode

Breaking down the problem with P.R.E.P.

Parameters
The function expects one parameter: an array of integers.

Returns
The function should return one value: a new array of integers that does not contain (the first instance of) the lowest value in the original array.

Examples
The test cases provided by CodeWars are the same ones mentioned in the examples above in the instructions.

Pseudo code
See pseudo code section for each solution


Solution 1: Pushing numbers except smallest into a new array

Pseudo code

1) Find the index of the smallest number.
2) Create a new variable holding an empty array.
3) Loop over the array of numbers provided as an argument.
4) Push the number to the new array if its index isn't the index 
   of the smallest number.
5) Return the new array.
Enter fullscreen mode Exit fullscreen mode

Solution

function removeSmallest(numbers) {
  const smallestIndex = numbers.indexOf(Math.min(...numbers));
  const newArray = [];
  numbers.forEach((number, i) => {
    if (i !== smallestIndex) newArray.push(number);
  });
  return newArray;
}
Enter fullscreen mode Exit fullscreen mode

Notes

1) The .indexOf() method returns the first index at which the element specified within the method can be found within the array. It returns -1 if the element is not found.

2) The .forEach array method loops over a given array and executes a function on each of its elements.

3) The .push() array method adds an element to the end of the given array. It is used inside the .forEach() loop to add the number of the current iteration inside the loop to the new array if its index does not match the index of the (first) lowest number in the original array.


Solution 2: Filtering out the smallest number by index

Pseudo code

1) Find the index of the smallest number.
2) Return a new array containing all elements except the (first) 
   smallest number.
Enter fullscreen mode Exit fullscreen mode

Solution

function removeSmallest(numbers) {
  const smallestIndex = numbers.indexOf(Math.min(...numbers));
  return numbers.filter((num, i) => i !== smallestIndex);
}
Enter fullscreen mode Exit fullscreen mode

Notes

The .filter() array method returns a new array containing all elements that fulfill the condition specified within its callback function.


Solution 3: Slicing out the smallest number by index

Pseudo code

1) Find the index of the smallest number.
2) Return a new array containing all elements before and after the 
   (first) smallest number.
Enter fullscreen mode Exit fullscreen mode

Solution

function removeSmallest(numbers) {
  const smallestIndex = numbers.indexOf(Math.min(...numbers));
  return [...numbers.slice(0, smallestIndex), 
         ...numbers.slice(smallestIndex + 1)]
}
Enter fullscreen mode Exit fullscreen mode

Notes

The .slice() array method returns a new array containing a part - or slice - of the original array without modifying the original array. It receives two parameters: the index at which it should start copying and the first index that should be excluded from the copy.


What solution did you implement?
What solution did you find the most elegant?
What solution did you have trouble understanding?

Let me know, I'd love to hear from you!

I hope you found this article helpful.


Connect with me on ...
Twitter
GitHub

💖 💪 🙅 🚩
nats_tech_notes
Nat's Tech Notes

Posted on June 16, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related