How could this Java CLABE control digit calculation be enhanced I recently wrote the following Java 1.8 snippet to generate a CLABE control digit based on the following subheading on the CLABE page on Wikipedia and I was curious on how it could be improved.

private void generateCLABEControlDigit() {
    final int[] expectedResults = {0,1,2,3,6,0,0,0,0,3,7,8,9,5,9,1,7};
    final String incompleteClabe = "03218000011835971";
    final String completeClabe = "032180000118359719";

    char[] clabeChars = incompleteClabe.toCharArray();
    int[] weightFactors = {3, 7, 1};
    int[] results = new int[clabeChars.length];
    int count = 0;

    for (int i = 0; i &lt; incompleteClabe.length(); i++) {
        int clabeInt = Integer.parseInt(String.valueOf(clabeChars[i]));
        int weightFactor = weightFactors[count];
        int result = clabeInt * weightFactor % 10;
        results[i] = result;
        if(count == 2) {
            count = 0;
        } else {
            count++;
        }
    }

    final int controlDigit =  (10 - Arrays.stream(results).sum() % 10) % 10;

    assert Boolean.TRUE.equals(Arrays.equals(expectedResults, results));
    assert completeClabe.equals(incompleteClabe + controlDigit);
}


I have included the incomplete CLABE and complete expected CLABE, these are also present within the Wiki article. 

This snippet normally takes a String value and would return an integer, this being the generated control digit. However, for purposes of the review I've simply refactored it so it can be simply lifted into a class and run along with the expected outcome (See the assert).

The CLABE comes into the system as a String, which resulted in the not so elegant one liner. 

int clabeInt = Integer.parseInt(String.valueOf(clabeChars[i]));
There are certainly a few things that can be improved.

Mainly the amount of intermediate (array) variables is just unnecessary. They use up memory, which means things get big and slow. The adding up can be performed within the loop.

Computers don't like branching (if statements), so if you can remove branches from a loop and replace them by a calculation (such as % 3) then that's always a boon, especially if the result is more readable as well.

The integer count is not well named. If it would be used in my code below, it would be named weightIndex or something similar.

I think the method is better named calculateCLABEControlDigit but I'm a bit lazy and won't rename it here. "Generate" is a bit much for such a calculation in my opinion.

public class CLABE {
    private static final String INCOMPLETE_CLABE = "03218000011835971";
    private static final String COMPLETE_CLABE = "032180000118359719";
    private static final int[] WEIGHT_FACTORS = {3, 7, 1};

    public static char generateCLABEControlDigit(final String incompleteClabe) {
        int sum = 0;
        for (int i = 0; i &lt; incompleteClabe.length(); i++) {            
            final int digitValue = Character.digit(incompleteClabe.charAt(i), 10);
            final int weightFactor = WEIGHT_FACTORS[i % 3];
            sum = (sum + (digitValue * weightFactor) % 10) % 10;
        }

        final int controlDigitValue =  (10 - (sum % 10) % 10);
        return Character.forDigit(controlDigitValue, 10);
    }

    public static void main(String[] args) {
        String clabe = INCOMPLETE_CLABE + generateCLABEControlDigitLessMod(INCOMPLETE_CLABE);
        if (clabe.equals(COMPLETE_CLABE)) {
            System.out.println("Yay!");
        }
    }
}




Now just to spook you a bit, some modular operations can be removed from the loop. For multiplication and addition, the final digit will remain correct after all. That is, as long as the sum is below Integer.MAX_VALUE. Of course you'd need a very long CLABE before you can add up to that (with 9 x 7 = 63 being the highest value that may be added per digit).

The double modulus is required for the final subtraction, as the sum can be 0 (an all zero incomplete CLABE) and because the Java mod operator is terrible when it comes to negative left-operand values. Actually, it's not a modulus operator at all. It is called the rest operator, as it may return negative values even if the modulus is positive. That's OK though because it is not in the loop.

    public static char generateCLABEControlDigitLessMod(final String incompleteClabe) {
        int sum = 0;
        for (int i = 0; i &lt; incompleteClabe.length(); i++) {            
            final int digitValue = Character.digit(incompleteClabe.charAt(i), 10);
            final int weightFactor = WEIGHT_FACTORS[i % 3];
            sum += digitValue * weightFactor;
        }

        final int controlDigitValue =  (10 - (sum % 10) % 10);
        return Character.forDigit(controlDigitValue, 10);
    }


Of course this speedup doesn't make any difference for this particular method. However, adding or removing modular operations is an interesting speedup trick to use in cases where it does matter, so I thought it was interesting enough to show you.



The testing with the vectors from Wikipedia (or preferably a banking standard) should be done by a Unit test.

Besides that, I'd probably make sure that the input is consisting just of digits before running any code on it by using a guard statement such as:

if (!incompleteClabe.matches("\\d*")) {
    throw new IllegalArgumentException("Not a valid CLABE sans control digit");
}


or even:

if (!incompleteClabe.matches("\\d{17}")) {
    throw new IllegalArgumentException("Not a valid CLABE sans control digit");
}


The CLABE class as specified should be made final and should not be instantiated as it only contains static methods. That is performed by adding a private, no argument constructor to it.

Finally, I might also create a validateCLABEControlDigit(final String fullClabe): boolean method that uses the other method. I'll leave the implementation up to you...