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
…just needed a solution for PHP. This is what I came up with:
/**
* Calculates the column number for a given column name.
*
* @param string $columnName the column name: "A", "B", …, "Y", "Z", "AA", "AB" … "AZ", "BA", … "ZZ", "AAA", …
*
* @return int the column number for the given column name: 1 for "A", 2 for "B", …, 25 for "Y", 26 for "Z", 27 for "AA", … 52 for "AZ", 53 for "BA", … 703 for "AAA", …
*/
function getColumnNumber($columnName){
// the function's result
$columnNumber = 0;
// at first we need to lower-case the string because we calculate with the ASCII value of (lower-case) "a"
$columnName = strtolower($columnName);
// ASCII value of letter "a"
$aAsciiValue = ord('a') - 1;
// iterate all characters by splitting the column name
foreach (str_split($columnName) as $character) {
// determine ASCII value of current character and substract with that one from letter "a"
$characterNumberValue = ord($character) - $aAsciiValue;
// through iteration and multiplying we finally get the previous letters' values on base 26
// then we just add the current character's number value
$columnNumber = $columnNumber * 26 + $characterNumberValue;
}
// return the result
return $columnNumber;
}
Of course the script can be shortened a little by just combining some stuff into one line of code within the foreach loop:
// …
$columnNumber = $columnNumber * 26 + ord($character) - ord('a') + 1;
// …
This version is purely functional and permits alternative 'code' sequences, for example if you wanted to only uses the letters 'A' to 'C'. In Scala, with a suggestion from dcsobral.
def columnNumber(name: String) = {
val code = 'A' to 'Z'
name.foldLeft(0) { (sum, letter) =>
(sum * code.length) + (code.indexOf(letter) + 1)
}
}
Using Mr. Wizard's awesome Mathematica code, but getting rid of the cryptic pure function!
columnNumber[name_String] := FromDigits[ToCharacterCode[name] - 64, 26]
another [more cryptic] erlang example:
col2int(String) -> col2int(0,String).
col2int(X,[A|L]) when A >= 65, A =< 90 ->
col2int(26 * X + A - 65 + 1, L);
col2int(X,[]) -> X.
and inverse function:
int2col(Y) when Y > 0 -> int2col(Y,[]).
int2col(0,L) -> L;
int2col(Y,L) when Y rem 26 == 0 ->
int2col(Y div 26 - 1,[(26+65-1)|L]);
int2col(Y,L) ->
P = Y rem 26,
int2col((Y - P) div 26,[P + 65-1|L]).