The National Register of Belgium1 is a database containing information about all residents of Belgium. The database is managed by the Federal Public Service Interior2, but the data is supplied by the Population Service of the individual municipalities. Shortly after birth, each resident receives a unique national register number3 that can be used to find administrative information in the National Register (domicile, civil status, nationality). This number is indicated on the ID card and can be personally requested at the counter of the Population Service.
The national register number consists of 11 digits:
A first group of six digits corresponds to the date of birth in the order year, month and day. Only the last two digits of the year of birth are used. The month and day are represented with two digits by adding leading zeros if necessary.
A second group of three digits serves to distinguish residents born on the same day. It is a daily serial number of births, with even serial numbers (002–998) for women and odd serial numbers (001–997) for men.
A third group of two digits is a check number that is calculated from the number $$n$$ formed by the nine preceding digits. For residents born from the year 2000 onward, an extra digit 2 must be prepended to the nine digits (+ 2000000000) to obtain the number $$n$$. The calculation of the check number then consists of dividing $$n$$ by 97 (integer division) and subtracting the remainder of that division (modulo) from 97. That difference is the check number. The check number is represented with two digits by adding a leading zero if necessary.
This information tells us for example that the national register number 93051822361 was assigned to a male resident (odd daily serial number) who was born on May 18, 1993 (first group). We can infer that the year of birth is 1993 and not 2093 (if we would already have reached that year) because the remainder after integer division of 930518223 by 97 is 36. We then get that 97 - 36 is equal to the check number 61. If the resident was born in 2093, we would compute the check number as the division of 2930518223 by 97 to get 7 as a remainder. In that case the check number should have been 97 - 7 = 90.
Define a class NationalRegisterNumber that can be used to check the validty of Belgian national register numbers. A string must be passed when creating objects of the class NationalRegisterNumber. If the given argument is not a string, an AssertionError must be raised with the message invalid type. In addition, the given string must contain exactly 11 digits (all characters that are no digits are ignored). If this is not the case, an AssertionError must be raised with the message invalid format (n digits), with $$n$$ being the number of digits in the given string. The message must use the singular form (1 digit) if $$n = 1$$.
Make sure that the built-in function repr returns a string representation for national register numbers (objects of the class NationalRegisterNumber) in the format
NationalRegisterNumber('number')
where number corresponds to the digits in the string that was passed when creating the object. All characters that are not digits must therefore be deleted.
Also make sure that the built-in function str returns a string representation for national register numbers (objects of the class NationalRegisterNumber) in the format
yy.mm.dd-xxx.cc
where the digits yy, mm and dd corrrespond to the date of birth (respectively year, month and day), xxx with the daily serial number and cc with the check number.
The class NationalRegisterNumber must support at least the following methods:
A method gender that takes no arguments. The method must return a string that corresponds to the gender of the national register number: male for male residents and female for female residents.
A method checksum with an optional parameter y2k that takes a Boolean value (default value: False). The method must return the check number that is computed from the first nine digits of the national register number (so not just the last two digits of the national register number). If the value False is passed to the parameter y2k, the computation must be done for residents born from the year 2000 onwards. Otherwise the computation must be done for residents born before the year 2000.
A method birthday that takes no arguments. The method must return a datetime.date object that corresponds to the date of birth of the national register number. The function must assume that national register numbers whose last two digits are equal to the computed check number for residents born from 2000 onward correspond to residents born in the 21st century (20xx) and all other national register numbers to residents born in the 20th century (19xx). If the national register number does not contain a valid date of birth, an AssertionError must be raised with the message invalid birthday.
A method valid that takes no arguments. The method must return a Boolean value that indicates whether the national register number is valid. In addition to the checks that were done at the time the object was created, national register numbers must also have a valid date of birth and the number formed by the last two digits must be equal to one of the two check numbers that are computed from the first nine digits.
# born before the year 2000
>>> nrn = NationalRegisterNumber('75.12.05-137.14')
>>> nrn
NationalRegisterNumber('75120513714')
>>> print(nrn)
75.12.05-137.14
>>> nrn.checksum()
14
>>> nrn.checksum(y2k=True)
43
>>> nrn.birthday()
datetime.date(1975, 12, 5)
>>> nrn.gender()
'male'
>>> nrn.valid()
True
# born since the year 2000
>>> nrn = NationalRegisterNumber('>>>09082428248<<<LENA<NADINE<INGRID')
>>> nrn
NationalRegisterNumber('09082428248')
>>> print(nrn)
09.08.24-282.48
>>> nrn.checksum(y2k=False)
19
>>> nrn.checksum(y2k=True)
48
>>> nrn.birthday()
datetime.date(2009, 8, 24)
>>> nrn.gender()
'female'
>>> nrn.valid()
True
# invalid identification numbers
>>> NationalRegisterNumber(1234567890)
Traceback (most recent call last):
AssertionError: invalid type
>>> NationalRegisterNumber('xxx3xxx')
Traceback (most recent call last):
AssertionError: invalid format (1 digit)
>>> NationalRegisterNumber('1234567890')
Traceback (most recent call last):
AssertionError: invalid format (10 digits)
>>> NationalRegisterNumber('12.34.56-789.10').birthday()
Traceback (most recent call last):
AssertionError: invalid birthday
>>> NationalRegisterNumber('12.34.56-789.10').valid()
False
>>> NationalRegisterNumber('85.02.01-002.00').birthday()
datetime.date(1985, 2, 1)
>>> NationalRegisterNumber('85.02.01-002.00').valid()
False
Because the national register number of Belgium only uses the last two digits of the year of birth, there was a chance that national register numbers would no longer be unique after the year 2000. In order to cope with this manifestation of the Millenium bug4 (aka Y2K), it was established on November 1997 by royal decree that in the computation of the check number an additional digit 2 must be prepended to the sequence of the first nine digits of the date of birth and the daily serial number for residents born from the year 2000 onward.
In a few decades a similar crisis threatens the Social Security Number5 that the United States uses to identify its residents. These numbers are also unique and are never recycled when somebody dies. About a billion numbers are possible. The United States started to assign these numbers in 1936 and already about a third of the possibilities have been used up since. According to some estimates they could run out by 2075.
What happens then? Who knows? But if the American government collapses, its residents could head to South Korea: their social security numbers give access to online video games.