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
Here's a CFML one:
<cffunction name="ColToNum" returntype="Numeric">
<cfargument name="Input" type="String" />
<cfset var Total = 0 />
<cfset var Pos = 0 />
<cfloop index="Pos" from="1" to="#Len(Arguments.Input)#">
<cfset Total += 26^(Pos-1) * ( Asc( UCase( Mid(Arguments.Input,Pos,1) ) ) - 64 ) />
</cfloop>
<cfreturn Total />
</cffunction>
<cfoutput>
#ColToNum('AABCCE')#
</cfoutput>
And because I'm in an odd mood, here's a CFScript version:
function ColToNum ( Input )
{
var Total = 0;
for ( var Pos = 1 ; Pos <= Len(Arguments.Input) ; Pos++ )
{
Total += 26^(Pos-1) * ( Asc( UCase( Mid(Arguments.Input,Pos,1) ) ) - 64 );
}
return Total;
}
WriteOutput( ColToNum('AABCCE') );
Sounds like a standard reduce to me:
Python:
def excel2num(x):
return reduce(lambda s,a:s*26+ord(a)-ord('A')+1, x, 0)
C#:
int ExcelToNumber(string x) {
return x.Aggregate(0, (s, c) => s * 26 + c - 'A' + 1 );
}
Hah - written it already in our code base - about 3 different times :(
%% @doc Convert an string to a decimal integer
%% @spec b26_to_i(string()) -> integer()
b26_to_i(List) when is_list(List) ->
b26_to_i(string:to_lower(lists:reverse(List)),0,0).
%% private functions
b26_to_i([], _Power, Value) ->
Value;
b26_to_i([H|T],Power,Value)->
NewValue = case (H > 96) andalso (H < 123) of
true ->
round((H - 96) * math:pow(26, Power));
_ ->
exit([H | T] ++ " is not a valid base 26 number")
end,
b26_to_i(T, Power + 1, NewValue + Value).
The riddle is that it isn't actually a Base26 representation of a number (we are lying to ourselves in our function name here) because there is no 0 in it.
The sequence is: A, B, C ... Z, AA, AB, AC
and not: A, B, C ...Z, BA, BB, BC
(the language is Erlang, mais oui).
Easy Java solution -->
public class ColumnName {
public static int colIndex(String col)
{ int index=0;
int mul=0;
for(int i=col.length()-1;i>=0;i--)
{
index += (col.charAt(i)-64) * Math.pow(26, mul);
mul++;
}
return index;
}
public static void main(String[] args) {
System.out.println(colIndex("AAA"));
}
Get a column name from an int in Java(read more here):
public String getColName (int colNum) {
String res = "";
int quot = colNum;
int rem;
/*1. Subtract one from number.
*2. Save the mod 26 value.
*3. Divide the number by 26, save result.
*4. Convert the remainder to a letter.
*5. Repeat until the number is zero.
*6. Return that bitch...
*/
while(quot > 0)
{
quot = quot - 1;
rem = quot % 26;
quot = quot / 26;
//cast to a char and add to the beginning of the string
//add 97 to convert to the correct ascii number
res = (char)(rem+97) + res;
}
return res;
}
This is basically a number in base 26, with the difference that the number doesn't use 0-9 and then letters but only letters.