Basic Python (JC) Recap Quiz - NRIC Check Digit

The structure of the Singapore NRIC/FIN number is one initial letter (S,T,F,G) followed by seven digits and one letter behind. E.g. S1234567D


The last letter is obtained from the 7 digits using the modulus eleven method. The steps to obtain the last letter are as below:

  1. Multiply each digit in the NRIC/FIN number by its weight (refer to table below).
  2. Add together the above products.
  3. If the first digit is G or T, add 4 to the sum obtained.
  4. Obtain the number to add to this sum such that the total will be divisible by 11. This is done by:
    • Divide the resulting sum by 11 to obtain the remainder.
    • If the remainder is 0, that is the check digit
    • If the remainder is not 0, subtract remainder from 11 to obtain the check digit.
  5. Check the check digit against the tables below to obtain the last letter.

The following table shows the weight for each digit:

2765432

The following tables are used to check the check digit corresponding letter.

If the first digit is S or T:

Check Digit012345678910
Last LetterJABCDEFGHIZ

If the first digit is G or F:

Check Digit012345678910
Last LetterXKLMNPQRTUW

source: https://userapps.support.sap.com/sap/support/knowledge/en/2572734

Task 1.1

Fill in the following function to calculate the check digit given the initial letter and 7 numerical digits (provided as a string)

# nric will be provided as a string, containing initial letter + 7 digits, e.g. 'S1234567'
def calculate_check_digit(nric):
    # TODO: if the length of the nric string is NOT 8 characters, return the string 'Error'
    if len(nric) != 8:
        return 'Error'
 
    # TODO: if the first digit (i.e. index 0) is NOT either 'S', T', 'F' or 'G', return the string 'Error'
    if nric[0] not in ['S', 'T', 'F', 'G']:
        return 'Error'
 
    # TODO: if the subsequent 7 digits (2nd to 8th digits, i.e. index 1 to index 7) are NOT numerical, return the string 'Error'
    # hint: use <str>.isdigit()
    if not nric[1:8].isdigit():
        return 'Error'
 
    # TODO: fill in this weight table according to info given above
    weight = [2, 7, 6, 5, 4, 3, 2]
 
    # TODO: fill in these check digits tables (stored as strings) according to info given above
    digits_S_T = 'JABCDEFGHIZ' # this is done for you, all digits according to the sequence given above, in a single string
    digits_G_F = 'XKLMNPQRTUW' # fill this in, all digits according to the sequence given above, in a single string
 
    # TODO: write a loop to calculated the weighted sum of the nric digits, saving it into variable total
    # based on steps 1 & 2 above
    total = 0
 
    for i in range(1,8):
        total += int(nric[i])*weight[i-1]
 
    # TODO: handle if NRIC starts with G or T
    # based on step 3 above
 
 
    if nric[0] in ['G', 'T']:
        total += 4
 
 
    # TODO: calculate and return the check digit
    # based on steps 4 & 5 above
 
    remainder = total % 11
 
    if remainder == 0:
        check_digit = remainder
    else:
        check_digit = 11-remainder
 
    if nric[0] in ['S', 'T']:
        last_digit = digits_S_T[check_digit]
        return last_digit # i asked chatgpt for this idk why we need to return here
    if nric[0] in ['G', 'F']:
        last_digit = digits_G_F[check_digit]
        return last_digit
 
 
 
 
 
 

Task 1.2

Test your code from Task 1.1 with the following test cases.

  • S1234567 (should return ‘D’)
  • T1122334 (should return ‘B’)
  • G7654321 (should return ‘L’)
  • A1111111 (should return ‘Error’)

The first one has been written for you.

print(calculate_check_digit('S1234567') == 'D')# should print True
print(calculate_check_digit('T1122334'))
print(calculate_check_digit('G7654321'))
print(calculate_check_digit('A1111111'))

Task 1.3

Fill in the following function to check if a given full nric string is valid or not

# nric will be provided as a string, containing initial letter + 7 digits + check digit, e.g. 'S1234567D'
def check_valid(nric):
    # TODO: if the length of the nric string is NOT 9 characters, return boolean value False
    if len(nric) != 9:
        return False
 
    # TODO: if the first digit (i.e. index 0) is NOT either 'S', T', 'F' or 'G', return boolean value False
    if nric[0] not in ['S', 'T', 'F', 'G']:
        return False
 
    # TODO: if the subsequent 7 digits (2nd to 8th digits, i.e. index 1 to index 7) are NOT numerical, return boolean value False
    # hint: use <str>.isdigit()
    if not nric[1:8].isdigit():
        return False
 
    # TODO: if the last digit (9th digit, i.e. index 8) is NOT a letter, return boolean value False
    # hint: use <str>.isalpha()
    if not nric[8].isalpha():
        return False
 
 
    # TODO: fill in the code to obtain the check digit from the function written in Task 1.1
    # hint: extract the first 8 digits from nric (excluding the check digit) and pass it into the function from Task 1.1
    calculated_check_digit = calculate_check_digit(nric[0:8])
 
    # TODO: fill in the code to check if the calculated check digit matches the last digit from the provided nric string
    if calculated_check_digit == nric[8]:
        return True
    else:
        return False
 

Task 1.4

Test your code from Task 1.3 with the following test cases.

  • S1234567D (should return True)
  • T1122334C (should return False)
  • G7654321L (should return True)
  • F1111111 (should return False)

The first one has been written for you.

print(check_valid('S1234567D') == True) # should print True
print(check_valid('T1122334C') == True)
print(check_valid('G7654321L') == True)
print(check_valid('F1111111') == True)

Task 1.5

Fill in the following procedure to print out n number of randomly generated NRIC numbers

import random
 
def generate_nric(n): # n is given as an integer; represents how many to generate
 
    # TODO: write a loop to repeat for n times
    for i in range(n):
 
        nric = '' # empty string that will be filled in later with the generated NRIC
 
        alphabets = ['S', 'T', 'F', 'G']
 
        # TODO: add a random alphabet from the above list into the nric string
        nric += random.choice(alphabets)
 
        # TODO: write a loop to repeat for 7 times
        for i in range(7):
 
            # TODO: generate a random number between 0 to 9
            random_num = random.choice('1234567890')
 
            # TODO: add the string version of this random number to the nric string
            nric += random_num
 
        # TODO: use the function written in Task 1.1 to generate the check digit
        check_digit = calculate_check_digit(nric)
 
        # add the generated check digit to the nric string
        nric  += check_digit
 
        # TODO: print the final nric string
 
        print(nric)
 

Task 1.6

Test your code from Task 1.5 by printing 10 randomly generated NRIC numbers.

generate_nric(10)