I have this weird craving for writing super short code, like writing entire functions in a single line. I do not recommend doing it that way, code readability is many times more important than your code being small in size. But I do it sometimes as a fun activity, just to check if I can do something.
So a friend approached me with a problem called the “step number problem” where you take a number and return true if all the digits differ from the neighbour by 1, either positive or negative.
545678 -> True45654 -> True12345 -> True13573 -> False12145 -> False
Important note: In my score for shortness, I take into account the number of tokens used and not the actual number of characters. Therefore according to my standard, using a variable n instead of variable number doesn’t make it any shorter.
Step 1: Split digits
There are mathematical ways to do this, for example, by taking repeated %10, till the number is > 0. But I went for the convert to string and split approach. I don’t see big performance impacts.
Step 1.1: Convert number to string
There are few ways to do this…
1. number.toString()2. String(number)3. number + ""
The last one is unique. It uses the property that, + operator will convert one operand to string if the other one is string. Shorter, but an extreme blow to readability. I’m not sure, but there is a possibility that code minifiers use this to reduce the code size. Aaaaannnd, it looks a tad bit cooler, so let me use it.
Step 1.2: Split
Similarly, to split a string, the commonly used syntax is this
But there is an even cooler syntax, using the spread operator…
Read about the spread syntax here.
The spread operator can take a string and convert it into a comma separated list of characters. We again put it in an array. So in essence, this is equivalent to the split function.
Step 1.3: Convert to number
From the previous step we will have something like [‘1’, ‘2’, ‘3’], an array of single character Strings. We want them all to be numbers.
The map function comes in handy here. (Take a look at the link if you haven’t used it before). It is suitable for places where we want to apply some operation to each element of the array, and end up with a new array with the transformed values. Here the transformation is from string to number.
Again, there are some ways to do it.
1. parseInt()2. Number()3. Unary + operator
The last one is the cooler one again. (Not recommended for readability). Take a look at this example:
const str = '123';
const num = +str;
num would have the numeric value 123.
To convert each value of the array, we can do this:
arr.map(e => +e)
But I prefer this one:
Remember that Number is not only a type, but also a function. So it can be passed to the map function.
Summarizing step one, we have
This takes the input
[1, 2, 3, 4, 5]
Step 2: Core logic
We have an array of numbers, and want to check if each adjacent number differs exactly by plus or minus one.
For this, I use another tool in my arsenal, the reduce function. To be honest, I think reduce function is very underrated. Have a look at the reduce function here. You are provided with an accumulator, and a function is called for each element of the array. The value you return is used as the accumulator value for the next element.
To make it easy, let me first solve it in a procedural way before jumping on to using reduce:
Now moving on to using reduce:
Notice how we are accumulating the result. We are ANDing the previous result and returning it, so that, if anywhere the difference isn’t 1, the final result would be false.
Here is a walkthrough of how it works
Assume array = [3, 4, 5, 7, 8]
Now that you are clear, let me shorten the function:
We use the if condition to return true for the 0th element, because for the 0th element, there is no previous. If you think about it, the above too can be simplified to the following:
The return statement consists of two parts concatenated by ||. The first part checks if the current index is 0, and the other bulky part. If the first condition is true, the second part will not be even executed (think about it, it is an OR operation, if one is true, whether or not the second one is true, the result will be true). This is a type of optimization done by compilers, called “short circuit evaluation” which might come handy in these types of situations.
Since in our function we have only one line, we can convert it to an arrow function:
Let me wire step 1 and step 2 together:
So, there you have it! Some Ninja code. Use the tricks you learnt from this article to hide your logic from your sneaky colleagues!
Note: There might be some argument that there is a performance impact due to the fact that you can’t break out of the loop, like you do with the for loop. But, again there is the role of short circuit evaluation. Once the value of the result becomes false, the next bulky expression will not be evaluated, because they are && ed together. If the first one is false, the whole expression is always false.