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.)
2 Answers 2
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
).
-
\$\begingroup\$ Hah! You couldn't resist opening an account just for this :) \$\endgroup\$Benjamin Gruenbaum– Benjamin Gruenbaum2013年02月23日 17:26:03 +00:00Commented 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– MaiaVictor2013年02月23日 17:42:11 +00:00Commented Feb 23, 2013 at 17:42 -
\$\begingroup\$ @Dokkat you shouldn't write your code so condensed. \$\endgroup\$copy– copy2013年02月23日 17:49:52 +00:00Commented 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– MaiaVictor2013年02月23日 18:12:33 +00:00Commented Feb 23, 2013 at 18:12
-
\$\begingroup\$ @Dokkat, so you wrote it with your eyes closed? \$\endgroup\$radarbob– radarbob2013年02月23日 19:14:57 +00:00Commented Feb 23, 2013 at 19:14
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'
-
\$\begingroup\$ Your code doesn't roll over.
inc_str('az')
outputs as "aa" but should be "ba" \$\endgroup\$Larry Battle– Larry Battle2013年07月02日 02:41:40 +00:00Commented Jul 2, 2013 at 2:41