4

I'm trying to write a function that takes a revision number (int) and turns it into a revision name (string). The formula should produce outputs similar to this:

Number  Name
1       A
2       B
3       C
...     ...
25      Y
26      Z
27      AA
28      AB
29      AC
...     ...
51      AY
52      AZ
53      BA
54      BB
55      BC
...     ...

This seems simple, but I think it might involve recursion and I'm terrible at that. Any suggestions?

Matthew Jones
  • 25,644
  • 17
  • 102
  • 155
  • 1
    It looks like you want the same formula as Excel uses to take row numbers to row names. Have a search here for that - I remember not so long ago there was a question that sparked something of a heated debate... – AakashM Dec 14 '09 at 21:23
  • `string x=abc[num%26]; x+=this(num-num%26)` or something like that.. (also note `abc=char [a...z]`) unless you want a non-elegant way :) – Earlz Dec 14 '09 at 21:25
  • Yes I know, but just a start.. you'd need to subtract and divide and of course actually return something rather than making a recursive loop – Earlz Dec 14 '09 at 21:30
  • 1
    See also: http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa – Graham Dec 14 '09 at 21:52

5 Answers5

6

I think this is the same as working out the Excel column name from a column number:

private string GetExcelColumnName(int columnNumber)
{
    int dividend = columnNumber;
    string columnName = String.Empty;
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
        dividend = (int)((dividend - modulo) / 26);
    } 

    return columnName;
}
Graham
  • 14,885
  • 4
  • 36
  • 42
5

I think you basically need a transformation of a number in 10x numerical system to a number in 26x numerical system.

For example:

53 = 5*10^1 + 3*10^0 = [5][3]

53 = B*26^1 + A*26^0 = [B][A]


int value10 = 53;
int base10 = 10;

string value26 = "";
int base26 = 26;

int input = value10;
while (true)
{
    int mod = input / base26;
    if (mod > 0)
        value26 += Map26SymbolByValue10 (mod); // Will map 2 to 'B'
    else
        value26 += Map26SymbolByValue10 (input); // Will map 1 to 'A'

    int rest = input - mod * base26;
    if (input < base26) break;
    input = rest;
}
2

I really hope this isn't homework... (untested solution):

if(value == 1)
  return "A";
StringBuilder result = new StringBuilder();
value--;
while(value > 0)
{
  result.Insert(0, 'A' + (value % 26));
  value /= 26;
}

Recursive version based on tanascius' original answer (also untested):

string ConvertToChar(int value)
{
  char low = 'A' + (value - 1) % 26;
  if(value > 26)
    return ConvertToChar((value - 1) / 26 + 1) + low.ToString();
  else
    return low.ToString();
}
Aaron
  • 9,123
  • 5
  • 40
  • 38
  • @tanascius - I had already realized (and edited) that it was reversed -- but you still want to use modulo either way. – Aaron Dec 14 '09 at 21:35
2

Tested solution:

private static string VersionName(int versionNum)
{
    StringBuilder sb = new StringBuilder();
    while (versionNum > 0)
    {
        versionNum--;
        sb.Insert(0, (char)('A' + (versionNum % 26)));
        versionNum /= 26;
    }
    return sb.ToString();
}

I wouldn't bother using recursion for this. Looping with a StringBuilder is more efficient than concatenating strings with each recursion, although you'd probably need a crazy number of revisions to notice the difference (4 letters is enough for over 400,000 revisions).

Tara McGrew
  • 1,987
  • 19
  • 28
1

You can use the modulo operator and division to get your code.
Like 55 / 26 == 2 (that is B) and 55 % 26 = 3 (that is C). It works for two characters. When you have an unknown count of characters, you have to start looping:

[look at Aaron's solution, mine was wrong]

tanascius
  • 53,078
  • 22
  • 114
  • 136
  • What is GetChar() -- is that the function itself? If so, why bother with the loop at all? Better to just use the recursion... – Aaron Dec 14 '09 at 21:37