简体   繁体   中英

Why does "col" variable return a wrong value

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 formula for spreadsheets's alphabetical column labels

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 .

The parts of this formula in Java

Given following inputs:

  • column-label String columnLabel
  • base int radix = 26
  • ASCII-code offset int asciiOffset = 65 - 1 ( A has the decimal ASCII code 65 )

We need to calculate the following working variables:

  • backwards-index 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 !)
  • the running column-number long columnNumber , where a column-letters numerical-character-representation will be added during each iteration

The formula in Java

    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 .

Issues in your code

What I did to show them:

  • split some statements of yours into meaningful and testable parts
  • commented the issues (actual values and expected)
  • added an assert below some lines (to verify expected values)
  • added a fixing statement below (with some explanation)
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM