4
\$\begingroup\$

I have a working code (below) to convert a number to Excel-like (A...Z AA...AZ BA...BZ ...ZA-ZZ) column codes (headers).

For simplicity I limited it to 1 or 2 character codes.

Can the algorithm be streamlined by using a bit more of elementary math or using it differently?

Please note that I just happened to need it in JavaScript (so I wrote it in JS) and am not looking for pure code improvements.

function numberToLetters(nNum) {
    var result;
    if (nNum <= 26) {
        result = letter(nNum);
    } else {
        var modulo = nNum % 26;
        var quotient = Math.floor(nNum / 26);
        if (modulo === 0) {
            result = letter(quotient - 1) + letter(26);
        } else {
            result = letter(quotient) + letter(modulo);
        }
    }

    return result;
}

function letter(nNum) {
    var a = "A".charCodeAt(0);
    return String.fromCharCode(a + nNum - 1);
}
\$\endgroup\$
3

2 Answers 2

3
\$\begingroup\$

It depends what do you mean by "streamlined"? There is not much you can do to, for example, reduce the complexity of your algorithm. What you can do is to increase the clarity of your algorithm, which falls into the domain of code review or improvement.

Maybe there is some math trick that can do the job faster, or with fewer lines of code. However there is also a good chance that such a trick will not make your algorithm look more "streamlined". It might even go the opposite direction and make it harder for the code to reveal its intention.

That being said, the problem you solved can be generalized to the problem of converting number to an arbitrary base, and then encode the number-in-new-base using a set of arbitrary symbols. In your case, the base is 26. The symbols are ["A", "B", ..., "Z"]. How a number is encoded or represented in a new base is independent of the base-convertion itself.

Looking at it this way, the only improvement I can think of is "do not limit the convertion to only one or two characters". Such a constraint does not bring much simplicity. But this probably is still implementation level improvement.

Your algorithm (or api) could eventually look like: number.convertToBase(26).encodeIn (["A", "B", ... , "Z"]). Is this more "streamlined"?

\$\endgroup\$
1
  • \$\begingroup\$ I already pointed (linked) to the answer I liked (both in my comments and in the closing reason). Look at Linked section on the right. You are wrong about the math part. It's base 27 that needs to be used and then properly shifted. Edge cases are "Z", "AA", "AZ". \$\endgroup\$
    – PM 77-1
    Commented Dec 20, 2014 at 0:58
2
\$\begingroup\$

I don't really see, where you could apply major improvements. You certainly could remove the magic number 26 from your code and rename you letter-function. Furthermore, it is not neccessary to compute the character code of the letter A of every call to letter. Your calculation can be marginally simplified as well.

var charCodeOfA = "A".charCodeAt(0),
    alphabetLength = "Z".charCodeAt(0) - charCodeOfA + 1;

function numberToLetters(nNum) {
    if (nNum <= alphabetLength) {
        return convertNumberToLetter(nNum);
    } else {
        var firstNumber = Math.floor((nNum - 1) / alphabetLength);
        var firstLetter = convertNumberToLetter(firstNumber);

        var secondNumber = (nNum % alphabetLength) || alphabetLength;
        var secondLetter = convertNumberToLetter(secondNumber);

        return firstLetter + secondLetter;
    }
}

function convertNumberToLetter(nNum) {
    var charCode = charCodeOfA + nNum - 1;
    return String.fromCharCode(charCode);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.