Function to take a positive integer and return the next bigger number formed by the same digits I've written a solution to a Codewars challenge:


  You have to create a function that takes a positive integer number and returns the next bigger number formed by the same digits:
  
  12 ==> 21; 513 ==> 531; 2017 ==> 2071 


I am getting the following error on Codewars: "Execution Timed Out (12000 ms)". I am a rookie, and would appreciate if anyone could give me some suggestions on optimizing my code, as this is something I know very little about.

I've made some minor tweaks but nothing that really reconstructs the solution from the ground up.

//takes a num and finds the next biggest num composed of the same digits.

function nextBigger(num) {
  let newNum = 0;
  let otherNum = 0;
  let indicator = 0;
  while (num &gt; newNum) {
    if (indicator === 0) {
      otherNum = num;
      indicator++;
      continue;
    }

    if (
      String(num)
        .split("")
        .sort()
        .join("") ===
      String(otherNum)
        .split("")
        .sort()
        .join("")
    ) {
      if (otherNum &gt; num) {
        newNum = otherNum;
      }
    }

    otherNum++;
  }

  return newNum;
}
I know whatever program codewars uses does not care about readability (most computer programs don't), but in the real world readability is important.

The first step to refactoring should be creating tests. This way you can easily figure out if you've broken something:

let test1 = getNextNumberOfGreaterSize(12);
let test2 = getNextNumberOfGreaterSize(513);
let test3 = getNextNumberOfGreaterSize(2017);

assertEquals(21, test1);
assertEquals(531, test2);
assertEquals(2071, test3);

function assertEquals(expected, actual) {
  if (expected !== actual) {
    throw new Error("expected: " + expected + " but was: " + actual);
  }
}


While designing tests, you may discover other edge cases such as:


What if the number given is already the highest?
What if the number doesn't have any other combinations (such as 11)?
What if a single digit number is given (1)?


You didn't provide a function name but assuming it wasn't descriptive I suggest you change it. It's tricky coming up with a name for such a function (Functions like these probably wouldn't exist in the 'real world'), but something like getNextNumberOfGreaterSize(originalNumber) with a comment describing what it does.

Set otherNumber (Note I changed the name to be more readable. Cutting off 3 letters isn't saving you, or the interpreter any time) outside of the while loop and get rid of your if statement:

let otherNum = originalNumber;
while (originalNumber &gt; newNum) {
if (....


Whatever you are doing inside the if statement deserves a comment. Better yet, you should also put it inside a function (especially when you know you'll refactor it later!):

function numbersContainSameDigits(number1, number2) {
  return String(number1)
        .split("")
        .sort()
        .join("") ===
      String(number2)
        .split("")
        .sort()
        .join("");
}


Now that we got the important stuff out of the way, let's move onto what you're actually asking for. How can we shave a few milliseconds off each run / Why is coderank telling us the methods too slow?

Computers suck at computing Strings. However they rock at computing numbers. Let's see if we can cut down on the amount of String computing.

The way we check if the two numbers contain the same letters can be changed. First we get an array containing the characters, then compare the two arrays after sorting:

function numbersContainSameDigits(number1, number2) {
  return checkIfTwoArraysAreEqual(getArrayContainingDigits(number1), getArrayContainingDigits(number2));
}

function checkIfTwoArraysAreEqual(array1, array2) {
  return JSON.stringify(array1.sort()) === JSON.stringify(array2.sort());
}

function getArrayContainingDigits(number) {
    let arrayOfDigits = [];
    while (number &gt;= 1) {
        arrayOfDigits.push(Math.floor(number % 10));
      number /= 10;
    }

    return arrayOfDigits;
}


Edit:

You are going through a much wider range of numbers than needed. You could instead get all available combinations of a number, and select the permutation 1 index greater than the input.