Modified base36 to base 10 algorithm

668 Views Asked by At

I posted a question some time ago about an algorithm that generates 6 character base36 strings from integer numbers. It has the restriction that the first and last character must always be a letter and that the whole string is upper case.

Here is the algorithm:

String getId(int id)
{
    String s = "";
    for(int i = 0; i < 6; i++)
    {
        int digit;
        if((i == 0) || (i == 5))
        {
            digit = (id % 26) + 10;         
            id /= 26;
        }
        else
        {
            digit = id % 36;
            id /= 36;
        }

        // add the digit to the string:
        if(digit < 10)
            s = (char)('0' + digit) + s;
        else
            s = (char)('A' + (digit - 10)) + s;
    }
    return s;
}

I am trying to create a method that reverses this. I.e. given a String such as A0000K it would return 10. Here is what I have so far:

static int getNumber(String id) {
    int base = 36;
    int result = 0;
    int n = id.length();
    for (int i = 0; i < id.length(); i++)
    {
        n-=1;
        int digit = Character.digit(id.charAt(i), base);        

        if(i == 0 || i == 5) {
            result += digit * (Math.pow(base-10, n));
        }
        else {
            result += digit * (Math.pow(base, n));
        }

    }

    return result;
}

I think the issue is around the if statement for calculating result but i'm not too sure how to calculate it. I am basing it of standard algorithms for converting from other bases to base 10.

Can anyone help? Thanks

2

There are 2 best solutions below

0
E.D. On

I'd do something like this, using the assumption that the string is 6 characters long to simplify:

static int getNumber(String id) {
    int sum = 0, val;
    char current;
    for(int i = 0; i < 6; i++) {
        current = id.charAt(i);
        val = ((int) current) - (int) 'A';
        if(val > 0){
            sum += (val + 10) * Math.pow(36,5-i);
        } else {
            sum += ((int) id.charAt(i)) * Math.pow(36,5-i);
        }
    }
    return sum;
}

I haven't tested it, but it should work, or at least be pretty close. If you continue having difficulties, try stepping through it in a debugger.

0
samgak On

It will be easier if you iterate from the least significant to the most significant place, keeping track of the place value of each digit/letter.

Check whether each character is a digit or letter and then convert to a face value. Digits are 0-9, letters are 10-35 except in the 1st and 6th place where they are worth 10 less.

Multiply the face value by place value and add to the result. Increase the place value by multiplying by either 26 or 36 depending on the position.

static int getNumber(String id) {
    int placevalue = 1;
    int result = 0;
    for (int i = id.length()-1; i >= 0; i--)
    {
        int facevalue;
        if(Character.isDigit(id.charAt(i)))
            facevalue = (int)id.charAt(i) - '0';
        else
            facevalue = ((int)id.charAt(i) - 'A') + 10;

        if(i == 0 || i == 5) {
            result += (facevalue - 10) * placevalue;
            placevalue *= 26;
        }
        else {
            result += facevalue * placevalue;
            placevalue *= 36;
        }
    }

    return result;
}

The above doesn't do any input validation. At the very least you should check that id.length is 6.