A couple of days ago I received and email from HackerRank. They invited me to solve one of their challenges soā¦ Thatās what weāre going to do now!
You are in charge of the cake for your nieceās birthday and have decided the cake will have one candle for each year of her total age. When she blows out the candles, sheāll only be able to blow out the tallest ones. Your task is to find out how many candles she can successfully blow out.
For example, if your niece is turning 4 years old, and the cake will have 4 candles of height 3, 3, 1, 2, she will be able to blow out 2 candles successfully, since the tallest candles are of height 3 and there are such candles.
Function description
Create a function:
birthdayCakeCandles
. It must return an integer representing the number of candles she can blow out.
birthdayCakeCandles
has the following parameter:arr
- an array of integers representing candle heights.
As you can see itās pretty simple, but if they challenged meā¦ I have to solve it! :smiley:
You can find the challenge on HackerRank.
Note: Before reading forward, Iād recommend that you solve the challenge on your own first. Than you can take a peak š on my solutions.
First solution - the cleaner way
For this one weāre going to do a couple of steps:
- create a variable which will store the highest candle height. Letās call this variable:
max
- (a) loop over the array and (b) increase a
counter
everytime the currentitem
is equal tomax
- if the
item
is higher thanmax
, reset thecounter
and also setmax
to be equal to theitem
- at the end, return the
counter
(item
is the current candle height from the given arr
)
function birthdayCakeCandles(arr) {
// Step 1
let max = 0;
let counter = 0;
// Step 2 (a)
arr.forEach(item => {
// Step 3
if (item > max) {
// Step 4
max = item;
counter = 1;
// Step 2 (b)
} else if (item === max) {
counter++;
}
});
return counter;
}
Second solution - the clever but not optimal way
We could also use some ātricksā to make it easier to understand the code, without having to use both if
and else if
statements.
This time letās do the following:
- use
Math.max
+ thearray spread
operator to get the maximum value from the array - use the arrayās
filter
method to return an array with only themax
values - return the length of this
filter
ed array
function birthdayCakeCandles(arr) {
let max = Math.max(...arr);
return arr.filter(item => item === max).length;
}
Itās not the optimal way because are looping twice over the array (int the Max.max
and the filter
methods).
Third solution - the one-liner
(Or the worst but most satisfying way ā¤ļø)
You might know (or if you donāt, ask my friend: jenovs) that I like the reduce
function so everytime I can, I love using it, including this time. š
Soā¦ for this one, weāre going to use a ternary
operator twice because one ternary
operator can only handle 2 cases at a time. Plug another one in and you can have 3 cases: š
item
>max
item
=max
item
<max
Also, the default value of the acc
(accumulator) would be an object
where weāre going to save the two values we need: max
and counter
.
Other than that we just have to use the ālogicā from the First solution - sort ofā¦ :wink:
- If the
max
is less than theitem
we save it and reset thecounter
. - Else if the
item
is equal to themax
we increase the counter and we spread the rest of the object (although we only have one prop and we donāt have to use thespread
operator. We could just re set themax
again, butā¦ itās nice to see the three dots syntax š ). - Else, just return the
object
And at the end, we return the counter
prop of the returning object
.
const birthdayCakeCandles = arr =>
arr.reduce(
(acc, item) =>
acc.max < item
? { max: item, counter: 1 }
: acc.max === item
? { ...acc, counter: ++acc.counter }
: acc,
{ max: 0, counter: 0 }
).counter;
Conclusion
Thatās all we have for nowā¦ a simple problem with a simple solution. š
As always, I had fun coming up with all these solutions. Which one did you like the most?
Maybe you found another solutionā¦ Iād like to see it so let me know. You can brag about it! š