Nat's Tech Notes

Posted on

# 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"
``````

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"
``````

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.
``````

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;
}
``````

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.
``````

Solution

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

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.
``````

Solution

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

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 +...
``````

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"
``````

### 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"
``````

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.
``````

Solution

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

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.
``````

Solution

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

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.
``````

Solution

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

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.

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]
``````

### 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.
``````

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;
}
``````

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.
``````

Solution

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

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.
``````

Solution

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

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!