Whenever you get a non-elegant method, first thing, try to break your logic into smaller logic
private static bool isMaxChar(this char ch) { return ch == '9' || ch == 'z' || ch == 'Z'; } public static char Increment(this char ch) { if (Char.IsDigit(ch)) return (char)((ch + 1 - '0') % 10 + '0'); if (Char.IsLower(ch)) return (char)((ch + 1 - 'a') % 26 + 'a'); if (Char.IsUpper(ch)) return (char)((ch + 1 - 'A') % 26 + 'A'); return ch; }
by using the above helper methods, your code will be clearer and elegant
public static string Increment(this String str) { var charArray = str.ToCharArray(); for (int i = charArray.Length - 1; i >= 0; i--) { char originalChar = charArray[i]; charArray[i] = charArray[i].Increment(); if (!originalChar.isMaxChar() && char.IsLetterOrDigit(originalChar)) break; // break when update the first alphanumeric char and it's not a max char } return new string(charArray); }
I have written unit tests and run against the above code, and it gives the same results as your code
[Theory] [InlineData("a", "b")] [InlineData("z", "a")] [InlineData("c", "d")] [InlineData("az", "ba")] [InlineData("a9", "b0")] [InlineData("a1a", "a1b")] [InlineData("AAA", "AAB")] [InlineData("abc", "abd")] [InlineData("H98", "H99")] [InlineData("H99", "I00")] [InlineData("a99", "b00")] [InlineData("I00", "I01")] [InlineData("azz", "baa")] [InlineData("bl9Zz", "bm0Aa")] [InlineData("zzz", "aaa")] [InlineData("ZZZ", "AAA")] [InlineData("999", "000")] [InlineData("z99", "a00")] [InlineData("__a__", "__b__")] [InlineData("__z__", "__a__")] public void stringIncremental(string input, string expected) { string result = input.Increment(); Assert.Equal(result, expected); } [Theory] [InlineData('a', 'b')] [InlineData('z', 'a')] [InlineData('c', 'd')] [InlineData('k', 'l')] [InlineData('A', 'B')] [InlineData('Z', 'A')] [InlineData('G', 'H')] [InlineData('K', 'L')] [InlineData('1', '2')] [InlineData('9', '0')] [InlineData('0', '1')] [InlineData('5', '6')] [InlineData('%', '%')] [InlineData('-', '-')] [InlineData('_', '_')] [InlineData('/', '/')] public void charIncremental(char input, char expected) { char result = input.Increment(); Assert.Equal(result, expected); } ```
999andZZZcorrectly. I would have expected1000andAAAA. but it shouldn't be too hard to fix =) \$\endgroup\$