I was recently asked in a job interview to resolve a programming puzzle that I thought it would be interesting to share. It\'s about translating Excel column letters to actu
Wikipedia has good explanations and algos
http://en.wikipedia.org/wiki/Hexavigesimal
public static String toBase26(int value){
// Note: This is a slightly modified version of the Alphabet-only conversion algorithm
value = Math.abs(value);
String converted = "";
boolean iteration = false;
// Repeatedly divide the number by 26 and convert the
// remainder into the appropriate letter.
do {
int remainder = value % 26;
// Compensate for the last letter of the series being corrected on 2 or more iterations.
if (iteration && value < 25) {
remainder--;
}
converted = (char)(remainder + 'A') + converted;
value = (value - remainder) / 26;
iteration = true;
} while (value > 0);
return converted;
}
Caveat: both of these versions assume only uppercase letters A to Z. Anything else causes a miscalculation. It wouldn't be hard to add a bit of error checking and/or uppercasing to improve them.
Scala
def excel2Number(excel : String) : Int =
(0 /: excel) ((accum, ch) => accum * 26 + ch - 'A' + 1)
Haskell
excel2Number :: String -> Int
excel2Number = flip foldl 0 $ \accum ch -> accum * 26 + fromEnum ch - fromEnum 'A' + 1
Slightly related, the better challenge is the other way around: given the column number, find the column label as string.
Qt version as what I implemented for KOffice:
QString columnLabel( unsigned column )
{
QString str;
unsigned digits = 1;
unsigned offset = 0;
column--;
for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
offset += limit;
for( unsigned c = column - offset; digits; --digits, c/=26 )
str.prepend( QChar( 'A' + (c%26) ) );
return str;
}
Another Java:
public static int convertNameToIndex(String columnName) {
int index = 0;
char[] name = columnName.toUpperCase().toCharArray();
for(int i = 0; i < name.length; i++) {
index *= 26;
index += name[i] - 'A' + 1;
}
return index;
}
Get the column number from its name
Java:
public int getColNum (String colName) {
//remove any whitespace
colName = colName.trim();
StringBuffer buff = new StringBuffer(colName);
//string to lower case, reverse then place in char array
char chars[] = buff.reverse().toString().toLowerCase().toCharArray();
int retVal=0, multiplier=0;
for(int i = 0; i < chars.length;i++){
//retrieve ascii value of character, subtract 96 so number corresponds to place in alphabet. ascii 'a' = 97
multiplier = (int)chars[i]-96;
//mult the number by 26^(position in array)
retVal += multiplier * Math.pow(26, i);
}
return retVal;
}
Does it help to think of the string as the reverse of the column number in base 26 with digits represented by A, B, ... Z?