In a recent job interview, I had to solve a programmatic question. The question was to convert a given excel alphabet column name to a column number. My solution worked for the most part until they (interviewer) gave me "AUHS" as a column name. The solution broke. The expected answer "31999" but I got "18999". I want to learn where I went wrong and what I could do to improve the solution.
PS: I am new to Java
My solution,
public class test {
public static void main(String[] args) {
String argChar = "AUHS";
char a = 'A';
int asciiA = (int) a;
int col = 0;
col += Math.pow(26, 0) + (int)argChar.charAt(argChar.length()-1) - asciiA;
for(int i=1; i<argChar.length(); i++) {
col += (int)(Math.pow(26, i) + ((int)argChar.charAt(argChar.length()-(i+1)) - asciiA) * 26);
}
System.out.println(col);
}
}
The sequence of AZ encoded (base-26) column-labels is:
A .. 1 (= 26^0*1)
B .. 2 (= 26^0*2)
H .. 2 (= 26^0*8)
S .. 2 (= 26^0*19)
U .. 2 (= 26^0*21)
Z .. 26 (= 26^0*26)
AA .. 27 (= 26^1*1 +1)
AZ .. 52 (= 26^1*1 +26)
BA .. 53 (= 26^1*2 +1)
ZZ .. 702 (= 26^1*26 +26)
AAA .. 703 (= 26^2*1 + 26^1*1 + 26^0*1)
UHS .. 14423 (= 26^2*21 + 26^1*8 + 26^0*19)
AUHS .. 31999 (= 26^3*1 + 26^2*21 + 26^1*8 + 26^0*19)
So we can deduct the formula (in pseudo-mathematical-notation) as:
sum-of ( 26^index * letterAsNumber ) over each letter
where index is the position of the letter from the end starting with 0
where letterAsNumber is the letter mapped to a number {1..26}
where letter must be in range {A..Z}
See also Positional notation .
Given following inputs:
String columnLabel
int radix = 26
int asciiOffset = 65 - 1
( A
has the decimal ASCII code 65
) We need to calculate the following working variables:
int backwardsIndex
, which is initially 0
and is incremented by 1 when iterating through each character; starting at the end of the column-label (hence: backwards !)long columnNumber
, where a column-letters numerical-character-representation will be added during each iteration final int asciiOffset = (int) 'A' - 1; // 64 = 65 - 1, so that (int) 'B' - asciiOffset == 2
long columnNumber = 0;
for (int backwardsIndex=0; backwardsIndex < columnLabel.length(); backwardsIndex++) {
char letter = columnLabel.charAt(columnLabel.length() - backwardsIndex -1);
int letterAsNumber = (int) letter - asciiOffset;
columnNumber += Math.pow(26, backwardsIndex) * letterAsNumber;
}
return columnNumber;
}
See working demo on IDEone .
What I did to show them:
assert
below some lines (to verify expected values)String argChar = "AUHS";
// int asciiA = (int) 'A'; // actual: 65; expected: 64
int asciiA = (int) 'A' - 1; // should be an offset to have: (int) `A` - offset == 1
assert asciiA == 64;
int col = 0;
char letter = argChar.charAt(argChar.length()-1); // actual == expected: 'S'
int letterAsNumber = (int) letter - asciiA; // actual: 83 - 65: expected: 83 - 64;
assert letterAsNumber == 19;
// col += Math.pow(26, 0) + letterAsNumber; // actual: 20 = 1 + 19; expected: 19 = 1 * 19
col = (int) Math.pow(26, 0) * letterAsNumber; // multiply instead add
assert col == 19;
for(int i=1; i<argChar.length(); i++) {
letter = argChar.charAt(argChar.length() - (i + 1));
// letterAsNumber = ((int) letter - asciiA) * 26;
letterAsNumber = ((int) letter - asciiA); // should not add 26 at the end
// col += Math.pow(26, i) + letterAsNumber;
col += Math.pow(26, i) * letterAsNumber; // multiply instead add
}
assert col == 31999;
As counting starts from 1, and columns are counted from A
, a correction argChar.charAt(i) - 'A' + 1
is needed to properly convert chars to digits:
String argChar = "AUHS";
int pow = 1;
int n = 0;
for (int i = argChar.length() - 1; i >= 0; i--) {
n += (argChar.charAt(i) - 'A' + 1) * pow;
pow *= 26;
}
System.out.println("n = " + n);
Output:
n = 31999
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.