HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavaModerate

Generate 16-digit unique code (like product serial)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
uniquelikeproductserialgeneratecodedigit

Problem

I am not sure what to call this type of code (16-digit alphanumeric code).

Conditions are like this:

  • Digits (or characters) are limited 16



  • Numeric, alphabet mixed



  • No duplication allowed (not yet implemented)



One class with the main method:

public class QuadraDigitCipherGenerator {
    // Step 1. Generate 16 digit wich is not duplicated
    // Step 2. divide by 4 digit

    private static List pickRandomIndex (String original, int count) {
        List randIndices = new ArrayList();
        Set noDuplicateIndices = new HashSet();
        System.out.println(noDuplicateIndices.size() + "    " + count);
        while (noDuplicateIndices.size()  convertIndices = pickRandomIndex(util.toString(), charCnt);
        System.out.println("Below indices will be casting to Alphabet " + convertIndices);

        for(Integer i : convertIndices){
            char target = util.charAt(i);
            util.setCharAt(i, convertDigit2Char(target));
        }
        return util.toString();
    }

    private static String beautifyDigits(String original, int term){
        System.out.println("original " + original);
        return original.substring(0, term) + "-" + original.substring(term, 2*term)
                + "-" + original.substring(2*term, 3*term) + "-" + original.substring(3*term, 4*term);
    }

    public static void main(String argv[]) throws Exception {
        int digit = 16;
        System.out.println(digit + " digits random code > " + beautifyDigits(generateCode(16, 4), 4));
    }
}


The output looks like D33J-H872-3545-71A1, a product serial key.

Anyway, I think this code is not satisfied with the third condition (no duplication). Do you have any advice with regards to that aspect of the requirements?

Solution

Okay first off, let's make your random character choosing better.

The simplest way to get random symbols is to simply define the alphabet and then index into it.

So here's how you'd typically do it:

static final private String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
final private Random rng = new SecureRandom();    

char randomChar(){
    return ALPHABET.charAt(rng.nextInt(ALPHABET.length()));
}

String randomUUID(int length, int spacing, char spacerChar){
    StringBuilder sb = new StringBuilder();
    int spacer = 0;
    while(length > 0){
        if(spacer == spacing){
            sb.append(spacerChar);
            spacer = 0;
        }
        length--;
        spacer++;
        sb.append(randomChar());
    }
    return sb.toString();
}


The likelihood of generating two keys that are duplicates is \$\frac{1}{36^{16}} \approx 8\cdot 10^{-24}\$. So if you generate 10000 (ten thousand) bulk keys, the likelyhood of not having any duplicates is: $$(1-\frac{1}{36^{16}})^{10000}=99.99999999999999999987\%$$.

In other words, you are not very likely to get duplicates as long as your random function is good (hence the use of SecureRandom instead of Math.random(). To be certain you have to always check against your database anyway as a last step so I would just not bother with duplicate checking on the client side as the likelihood of finding duplicates is so very low.

Code Snippets

static final private String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
final private Random rng = new SecureRandom();    

char randomChar(){
    return ALPHABET.charAt(rng.nextInt(ALPHABET.length()));
}

String randomUUID(int length, int spacing, char spacerChar){
    StringBuilder sb = new StringBuilder();
    int spacer = 0;
    while(length > 0){
        if(spacer == spacing){
            sb.append(spacerChar);
            spacer = 0;
        }
        length--;
        spacer++;
        sb.append(randomChar());
    }
    return sb.toString();
}

Context

StackExchange Code Review Q#159421, answer score: 11

Revisions (0)

No revisions yet.