Driver's License numbers in New Jersey aren't random. They follow the format: Affff lllii mmyye
, where A
is the first letter of the person's last name, ffff
is some mapping of the remaining letters of the last name to a four digit numeric, lll
is a mapping of the full first name to a three digit numeric and ii
is a code representing the middle initial (according to the below table:
| | 6 | 7 | 8 |
|---|---|---|---|
| 1 | a | j | |
| 2 | b | k | s |
| 3 | c | l | t |
| 4 | d | m | u |
| 5 | e | n | v |
| 6 | f | o | w |
| 7 | g | p | x |
| 8 | h | q | y |
| 9 | i | r | z |
Where the number corresponding to the initial is 10*column number + row number. mm corresponds to the month born, and yy
to the year born. e
is the eye color (a value 1-8 corresponding to BRO
, BLU
, GRY
, GRN
, BLK
, etc.)
The only thing I don't understand is how the names are mapped to the integer values. I only have 5 examples for the last name mappings: (ignoring the first letter because it doesn't play into the mapping
aab -> 0001
ackson -> 0062
eals -> 2024
eimel -> 2278
ounds -> 6810
For first names, I only have four:
Alexander -> 019
Richard -> 655
John -> 407
Matthew -> 529
Does anyone have any ideas how the implementation is done, or even a general mapping function that will hash a max 25 length string to a four digit or three digit number while maintaining lexicographical order (<=, not <).
Things I've Tried
Convert each letter to a number 1-26. Then, taking only the first four numbers, create the number by the rule 26^3 * first number + 26^2 * second number + 26 * third + fourth. Then, divide this number by 26^4 + 26^3 + 26^2 + 26, and multiply by 10000 to map the decimal into 0-9999. This produces the following mappings:
aab -> 0000
ackson -> 0035
eals -> 1547
emiel -> 1722
ounds -> 5695
Get a list of the top 10,000 most common surnames. Order by the second letter, and then check the index. This produces the following mappings:
aab -> 0005
ackson -> 0128
eals -> 2813
emiel -> 3235
ounds -> 7588
Each letter subdivides the 10,000. The first number (according to 1-26) cuts it into one of 26 pieces. The second cuts the piece into one of 26, and so on and so forth. This produces the following mappings:
aab -> 0000
ackson -> 0028
eals -> 1536
emiel -> 1648
ounds -> 5656
Convert each of the first four letters to 1-26. Concatenate all of them, multiply the resulting number by 10,000, and divide by 26262626. This produces the following mappings:
aab -> 0003
ackson -> 0392
eals -> 1908
emiel -> 1953
ounds -> 5792
Do the above with 0-25, divide by 25252525. This produces the following mappings:
aab -> 0000
ackson -> 0008
eals -> 1584
emiel -> 1631
ounds -> 5623
Additional Samples
While I believe all of the above samples are correct, I tried to track down more authentic sample data points. Ones that I can guarantee are below:
Last Names
avis -> 0921
eals -> 2024
olff -> 6247
orello -> 6581
First Names
Alexander -> 019
Andrew -> 042
Gabriel -> 270
Lena -> 456