Are one-liners always the best solutions?
Tags: javascript
Published: 2020-12-24 00:37:23

Whenever I solved an algorithm on leetcode or codesignal, I liked to look at others solutions. For Codesignal in particular, a lot of the top voted solutions were **one-liners**. I loved looking at these clever solutions which seemed to both simplify the problem while also introducing sometimes complex answers. 

This week, I encountered an opportunity to introduce my own one-liner solution. Unfortunately, it didn’t turn out how I wanted it to. 

## The Problem 

Given an array of integers such as [1, 2, 2, 4, 4, 4] return the number of occurrences of the largest value. Since four shows up three times in this array, the answer would be 3. 

## One liner solution 

After playing around with a few **for-loop** type solutions, it occurred to me that I could use Math.max to find the largest value. 

```js
Math.max(array)
```

However, this returned an error.  I soon remembered (aka Googled) that the array would need to be spread in order for the method to work. 

```js
Math.max(…array)
```

With Math.max(…array), I was able to return the largest value, 4!

With that in mind, I only needed to compare the amount of times 4 appeared. There were several ways of doing this, but I settled on the filter method, which returns a new array for all the elements that match a given condition (in this case, each value that is 4). 

```js
arr.filter(num => Math.max(...arr) === num)
```

This returns an array [4, 4, 4], and so all that’s needed is to return the length of it. 

```js
arr.filter(num => Math.max(...arr) === num).length

```

In a repl, the results worked as expected with my sample array ([1, 2, 2, 4, 4, 4]). However, when I tried to submit the problem to the site, I was hit with a timeout error. It appeared that the solution took too long for arrays that were thousands of elements long. 

Not only that, but this solution is creating another array that won’t really be used besides for the purposes of taking its length. Is there a more optimized way of doing things?

## For loop solution 

Not wanting to get hit by timeout errors again, I returned to my initial idea of using a for loop. I also decided on using a sorted array to grab the max value immediately. 

```js
let sort = arr.sort((a,b) => b - a); 
let count = 0;
```

There were a few things I needed to keep in mind for this sorted array and counter method to work. First, I needed to make sure to keep track of duplicate values. I decided a comparison would take care of this. 

```js
for(let i = 0; i < sort.length ; i++){
        if(sort[0] !== sort[i]){
            return count
        } 
        
        count++
    }
```
*sort[0] represents the max value here since the array has been sorted in decreasing order.*

Second, I needed to account for instances where the arrays were filled with the same value. 

In the end, the solution looked like this. 

```js
    let sort = arr.sort((a,b) => b - a)
    let count = 0;
    for(let i = 0; i < sort.length ; i++){
        if(sort[0] !== sort[i]){
            return count
        } 
        
        count++
    }
   return count
```
This solution did pass the tests. 

## One liner vs for loop 

Although the one liner was a lot less code, it ended up being significantly slower than the for loop solution. Using console.time, the execution time was **76.631ms** for a 100 element array. 

Compared to the for loop, which took **0.319ms**, that’s a LOT longer. 

## Summary

I’m sure there’s solutions out there that account for shorter execution times and less code. Knowing how the time complexity of each method in a one-liner can affect the overall performance of a function is something important to keep in mind. 

You can find this problem on [hackerrank](https://www.hackerrank.com/challenges/birthday-cake-candles/problem).