1
\$\begingroup\$

I'm writing a function to increase a string so, for example, "aac" becomes "aad" and "aaz" becomes "aba". The result is horribly inelegant, I can't get it simple enough and I feel I'm missing something. How to improve that code?

function inc_str(str){
    var str = str.split("").map(function(a){ return a.charCodeAt(0); });
    var n = 1;
    while (n<str.length){
        str[str.length-n]++;
        if (str[str.length-n] > "z".charCodeAt(0))
            str[str.length-n] = "a".charCodeAt(0),
            ++n;
        else
            break;
    };
    return str.map(function(a){ return String.fromCharCode(a); }).join("");
};

Extra points for a brief functional style solution! (Even if it needs to implement other functional functions such as zip or whatever.)

\$\endgroup\$

2 Answers 2

8
\$\begingroup\$

A recursive approach is much more elegant in this case:

function inc_str(str) {
  var last = str[str.length - 1],
    head = str.substr(0, str.length - 1);
  if (last === "z") {
    return inc_str(head) + "a";
  } else {
    return head + String.fromCharCode(last.charCodeAt(0) + 1);
  }
}

Making it wrap around for inc_str('z') is left as an exercise for the reader (hint: last becomes undefined).

\$\endgroup\$
9
  • \$\begingroup\$ Hah! You couldn't resist opening an account just for this :) \$\endgroup\$ Commented Feb 23, 2013 at 17:26
  • 2
    \$\begingroup\$ Yay I'm glad I motivated someone to joining in. Great way to start, also. That was the obvious thing I was missing, recursion! Adapting from your answer, I got the one-liner: function inc_str(str){ return (last(str) == "z") ? inc_str(head(str)) + "a" : head(str) + inc_char(last(str)); }; So elegant! Thank you. \$\endgroup\$
    – MaiaVictor
    Commented Feb 23, 2013 at 17:42
  • \$\begingroup\$ @Dokkat you shouldn't write your code so condensed. \$\endgroup\$
    – copy
    Commented Feb 23, 2013 at 17:49
  • \$\begingroup\$ That's fine, this isn't meant to be human readable as it is the base of an AI programming system I'm developing. Less tokens = better and I must avoid varaibles. \$\endgroup\$
    – MaiaVictor
    Commented Feb 23, 2013 at 18:12
  • \$\begingroup\$ @Dokkat, so you wrote it with your eyes closed? \$\endgroup\$
    – radarbob
    Commented Feb 23, 2013 at 19:14
1
\$\begingroup\$

I suppose this could be written as:

 function inc_str(str){
 return !/^[a-z0-9]$/i.test(str[str.length-1]) ? str :
         str.substr(0,str.length-1) + 
          ( /z/i.test(str[str.length-1]) 
            ? String.fromCharCode(str.charCodeAt(str.length-1)-25) 
            : String.fromCharCode(str.charCodeAt(str.length-1)+1))
}
// usage
inc_str('aaa'); //=> 'aab'
inc_str('aaz'); //=> 'aaa'
inc_str('aaZ'); //=> 'aaA'
inc_str('aa2'); //=> 'aa3'
\$\endgroup\$
1
  • \$\begingroup\$ Your code doesn't roll over. inc_str('az') outputs as "aa" but should be "ba" \$\endgroup\$ Commented Jul 2, 2013 at 2:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.