Challenge: phone keypad to letters - return all possible strings The challenge: 

Given a mapping of digits to letters (as in a phone number), and a digit string, return all possible letters the number could represent. You can assume each valid number in the mapping is a single digit.

Example: 

If {"2": ["a", "b", "c"], 3: ["d", "e", "f"], …} 
then "23" should return ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

My iterative solution:

const digitMap = (digiStr) =&gt; {

  const digitMapping = {
    2: ['a', 'b', 'c'],
    3: ['d', 'e', 'f'],
    4: ['g', 'h', 'i'],
    5: ['j', 'k', 'l'],
    6: ['m', 'n', 'o'],
    7: ['p', 'q', 'r', 's'],
    8: ['t', 'u', 'v'],
    9: ['w', 'x', 'y', 'z']
  }
  const length = digiStr.length; 
  if (length === 1) return digitMapping[digiStr]; // in case of single digit strings
  const indexes = []; // index addresses of charsets, in order
  for (let i = 0; i &lt; length; i++) {
    indexes.push(0);
  }
  let nextI = length === 2 ? 0 : 1; // current spot of nextI in indexes
  const possibleStrs = []; // for final answer of possible permutations
  let str = ''; 
  let endCount = 0; // if all addresses in indexes are at their end, then break while loop
  while (true) {
    console.log(indexes);
    for (let i = 0; i &lt; length; i++) {
      str += digitMapping[digiStr[i]][indexes[i]];
      if (indexes[i] === digitMapping[digiStr[i]].length - 1) {
        endCount += 1;
      }
    }
    possibleStrs.push(str);
    str = '';
    if (endCount === length) {
      break;
    }
    endCount = 0;
    // increment last item in indexes as long as it &lt; length of corresponding inner char array
    if (indexes[indexes.length - 1] &lt; digitMapping[digiStr[digiStr.length - 1]].length - 1) {
      indexes[indexes.length - 1] += 1;
    }
    else {
      indexes[indexes.length - 1] = 0;
      // increment nextI as long as &lt; length of corresponding inner array
      if (indexes[nextI] &lt; digitMapping[digiStr[nextI]].length - 1) {
        indexes[nextI] += 1;
      }
      else {
      // otherwise shift position of nextI in indexes array
        // if next position of nextI not end of indexes array
          // shift nextI 1 spot forward in indexes
        if (nextI + 1 &lt; length - 1) {
          nextI += 1;
          indexes[nextI] += 1;
        }
        else {
          // else reset all indexes to 0, starting from position 1
          for (let i = 1; i &lt; indexes.length; i++) {
            indexes[i] = 0;
          }
          // increment first item in indexes
          indexes[0] += 1;
          nextI = 1; // place nextI at position 1
        }
      }
    }
  }
  return possibleStrs;
}

console.log(digitMap("2"));
console.log(digitMap("23"));
console.log(digitMap("234"));
console.log(digitMap("2345"));
console.log(digitMap("23456"));


Produces the correct output for all test cases. Any alternative approaches--recursive or iterative--to cleaning up the conditional logic would be greatly appreciated.
Too long for a comment...

The problem as presented seems to have much in common with the string permutations problem in terms of solution structure.

You should be able to do something similar to: https://stackoverflow.com/questions/4240080/generating-all-permutations-of-a-given-string with slight modification to get a compact recursive formulation.

Pseudo code below:

solution(string digits, string prefix="", array&lt;string&gt; outputs)
    if digits empty then
        add prefix to outputs
    else
        currentDigit := digits.get(0)
        remainingDigits := digits.remove(0);
        for each character in listOfCharsForDigit[currentDigit] do
            solution(remainingDigits, prefix+character, outputs)
        endfor
    endif


Hope that helps...