2
\$\begingroup\$

I want to generate a four digit code based on the code generated before it, starting at 0000 and going to zzzz.

These are the available characters to be inside the code:

private static final char[] _availableChar = "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();

The first thing I do is the get the newest code or the code with the highest auto_incremented Id.

I then pass that to this function to generate the next cod:

private String getNewCodeFromOldCode(String oldCode) {
        char[] newCodeChars = oldCode.toCharArray();

        if (oldCode == null || oldCode.isEmpty()) {
            return "0000";
        } else {
            char[] oldCodeChars = oldCode.toCharArray();

            if (oldCodeChars[3] != 'z') {
                newCodeChars[3] = _availableChar[String.valueOf(_availableChar).indexOf(oldCodeChars[3]) + 1];
            } else {

                if (oldCodeChars[2] != 'z') {
                    newCodeChars[3] = '0';
                    newCodeChars[2] = _availableChar[String.valueOf(_availableChar).indexOf(oldCodeChars[2]) + 1];
                } else {

                    if (oldCodeChars[1] != 'z') {
                        newCodeChars[2] = '0';
                        newCodeChars[1] = _availableChar[String.valueOf(_availableChar).indexOf(oldCodeChars[1]) + 1];
                    } else {

                        if (oldCodeChars[0] != 'z') {
                            newCodeChars[1] = '0';
                            newCodeChars[0] = _availableChar[String.valueOf(_availableChar).indexOf(oldCodeChars[0]) + 1];
                        } else {
                            JsfUtil.addErrorMessage("Unable To Generate A Code");
                        }

                    }

                }

            }
        }

        return String.valueOf(newCodeChars);
    }

I'm not exactly sure how to calculate the permutations but I think I have upwards of million different perm. available.

\$\endgroup\$
5
\$\begingroup\$

By my count, 0-9 + a-z gives 36 characters rather than 35.

For four digits like that, the number of combinations is \$36^4\$, which works out to 1,679,616.

As for the code itself, I think I'd do things just a little differently. What you really have is a 4-digit number in base 36. It's probably easiest to just use a normal number, and then use toString to generate the base-36 representation when you need it:

Integer counter;
String result = toString(counter, 36);

This does differ in one minor detail: it won't fill in leading zeros, so if it's shorter than 4 characters, you'll have to fill in the leading zeros yourself (still a pretty trivial operation though).

For the sake of security, I don't install Java on my machines, but there's a rough imitation of the basic idea, but in C++:

#include <iostream>
#include <string>
#include <deque>
#include <cassert>

// This should be approximately equivalent to what you'd get from 
// Java's `toString`, at least for non-negative numbers:
std::string toString(unsigned value, unsigned base) {
    static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";

    assert(base <= 36);

    std::deque<char> ret;

    while (value) {
        unsigned digit = value % base;
        value /= base;
        ret.push_front(digits[digit]);
    }
    return std::string(ret.begin(), ret.end());
}

// This calls toString, then pads the result out to 4 digits.
std::string paddedToString(unsigned value, unsigned base, unsigned num_digits) {
    std::string s = toString(value, base);

    // Add enough 0's to get to the desired width:
    return std::string(num_digits - s.size(), '0') + s;
}

// A quick test of the code.    
int main() { 
    // First we'll write the first few values:
    for (unsigned value = 0; value < 256; value++) 
        std::cout << paddedToString(value, 36, 4) << "\t";

    std::cout << "\n\n";

    // Then some values from around the middle of the range:
    unsigned base = 512 * 1024;

    for (unsigned i = 0; i < 256; i++)
        std::cout << paddedToString(i + base, 36, 4) << "\t";
}
\$\endgroup\$
  • \$\begingroup\$ what's the implementation of the toString(counter, 36)? \$\endgroup\$ – lxcky Aug 12 '16 at 1:15
  • \$\begingroup\$ @lxcky: It's in the standard library. At a guess, it probably uses modulus and division to separate out one digit at a time, and uses that to index into an array of char to pick what to display for each digit. \$\endgroup\$ – Jerry Coffin Aug 12 '16 at 4:05
  • \$\begingroup\$ I'm a little confused what you mean by 4-digit number in base 36. In the real world application Users are going to have to paint this 4 letter code onto a finished product. This will still be less than four characters? \$\endgroup\$ – Sam Orozco Aug 12 '16 at 15:19
  • \$\begingroup\$ @SamOrozco: As I said: "if it's shorter than 4 characters, you'll have to fill in the leading zeros yourself". One easy way to do this would be to start with "000", and concatenate the result from toString to the end, then take the last four characters of that resulting string. \$\endgroup\$ – Jerry Coffin Aug 12 '16 at 15:23
  • \$\begingroup\$ I understand that. Excuse me if this is simple but I don't understand the whole base 36 number and how that gets converted to a string like this. \$\endgroup\$ – Sam Orozco Aug 12 '16 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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