Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated Python 3 function

...

Code Block
languagegroovy
titleThe modified mod10 algorithm implemented in Groovy
linenumberstrue
def checkdigit(idWithoutCheckDigit) {
	idWithoutCheckDigit = idWithoutCheckDigit.trim().toUpperCase()
	sum = 0
	(0..<idWithoutCheckDigit.length()).each { i ->
    	char ch = idWithoutCheckDigit[-(i+1)]
    	if (!'0123456789ABCDEFGHIJKLMNOPQRSTUVYWXZ_'.contains(ch.toString()))
        	throw new Exception("$ch is an invalid character")
    	digit = (int)ch - 48;
    	sum += i % 2 == 0 ? 2*digit - (int)(digit/5)*9 : digit
  	}
	(10 - ((Math.abs(sum)+10) % 10)) % 10
}

// Validate our algorithm
assert checkdigit('12') == 5
assert checkdigit('123') == 0
assert checkdigit('1245496594') == 3
assert checkdigit('TEST') == 4
assert checkdigit('Test123') == 7
assert checkdigit('00012') == 5
assert checkdigit('9') == 1
assert checkdigit('999') == 3
assert checkdigit('999999') == 6
assert checkdigit('CHECKDIGIT') == 7
assert checkdigit('EK8XO5V9T8') == 2
assert checkdigit('Y9IDV90NVK') == 1
assert checkdigit('RWRGBM8C5S') == 5
assert checkdigit('OBYY3LXR79') == 5
assert checkdigit('Z2N9Z3F0K3') == 2
assert checkdigit('ROBL3MPLSE') == 9
assert checkdigit('VQWEWFNY8U') == 9
assert checkdigit('45TPECUWKJ') == 1
assert checkdigit('6KWKDFD79A') == 8
assert checkdigit('HXNPKGY4EX') == 3
assert checkdigit('91BT') == 2
try {
checkdigit ("12/3")
assert false
} catch(e) { }

Python

Code Block
languagepython
titleImplemented in Python, by Daniel Watsonfor Python 3
linenumberstrue
import math# Works for Python 3 from here: https://gist.github.com/alastairmccormack/e115140ddb1b522059d677f6dbf38f34

def returnget_checkdigit(self, id_without_check):

  

    # allowable characters within identifier

       valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVYWXZ_"
 

      
        # remove leading or trailing whitespace, convert to uppercase
        id_without_checkdigit = id_without_check.strip().upper()

    # this will be a running total
     # this will be a running total
        sum sum = 0;
         
 

     # loop through digits from right to left
        for n, char in enumerate(reversed(id_without_checkdigit)):
            
 

         if not valid_chars.count(char):
                raise Exception('InvalidIDException')
    

                   # our "digit" is calculated using ASCII value - 48
        digit =   digit = ord(char) - 48
             


          # weight will be the current digit's contribution to
  
         # the running total
   
        weight = None
   
        if (n % 2 == 0):


              
                # for alternating digits starting with the rightmost, we

               # use our formula this is the same as multiplying x 2 and
                # adding digits together for values 0 to 9.  Using the
  
             # following formula allows us to gracefully calculate a a
            # weight for non-numeric "digits" as well (from their
            # ASCII value - 48).
            ## Use_sparingly: In Python 3, '/' makes floats. '//' fixes it for Python 3.
            ## For cross compatibility, simply int() the result
# weight for non-numeric "digits" as well (from their    ##             # ASCII value - 48).    VVVVVVVVVVVVV
            weight = (2 * digit) - int(digit / 5) * 9
            else:
                # even-positioned digits just contribute their ascii
                # value minus 48
        contribute their ascii
        weight = digit  # value minus 48
            weight = digit

        # keep a running total of weights
        ## Use_sparingly: removed maths.fabs()
  sum += weight    ## abs() is sufficient
        sum += weight

    # avoid sum less than 10 (if characters below "0" allowed,

       # this could happen)
 
      sum = math.fabsabs(sum) + 10

        
        # check digit is amount needed to reach next number
        # divisible by ten. Return an integer 
   
    return int((10 - (sum % 10)) % 10) 

...