新泽西州的驾照号码不是随机的。它们遵循以下格式:Affff lllii mmyye
,其中A
是某人姓氏的第一个字母,ffff
是姓氏剩余字母到四位数数字lll
的某种映射,是全名到三位数数字的映射,ii
是代表中间名首字母的代码(根据下表:
| | 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 |
其中首字母对应的数字为10*列号+行号。mm对应出生月份,对应出生yy
年份。 e
是(对应于值1-8眼睛的颜色BRO
,BLU
,GRY
,GRN
,BLK
,等等)
我唯一不明白的是名称如何映射到整数值。对于姓氏映射,我只有 5 个示例:(忽略第一个字母,因为它不会影响映射
aab -> 0001
ackson -> 0062
eals -> 2024
eimel -> 2278
ounds -> 6810
对于名字,我只有四个:
Alexander -> 019
Richard -> 655
John -> 407
Matthew -> 529
有没有人知道如何完成实现,甚至是一个通用映射函数,它将最大 25 个长度的字符串散列到一个四位数或三位数,同时保持字典顺序(<=,而不是 <)。
我尝试过的事情
将每个字母转换为数字 1-26。 然后,仅取前四个数字,按照规则 26^3 * 第一个数字 + 26^2 * 第二个数字 + 26 * 第三个 + 第四个创建数字。然后,将这个数除以 26^4 + 26^3 + 26^2 + 26,再乘以 10000,将小数映射为 0-9999。这会产生以下映射:
aab -> 0000
ackson -> 0035
eals -> 1547
emiel -> 1722
ounds -> 5695
获取前 10,000 个最常见姓氏的列表。 按第二个字母排序,然后检查索引。这会产生以下映射:
aab -> 0005
ackson -> 0128
eals -> 2813
emiel -> 3235
ounds -> 7588
每个字母细分 10,000。第一个数字(根据 1-26)将其切成 26 块之一。第二个将一块切割成 26 个之一,依此类推。这会产生以下映射:
aab -> 0000
ackson -> 0028
eals -> 1536
emiel -> 1648
ounds -> 5656
将前四个字母中的每一个都转换为 1-26。 将所有这些连接起来,将结果乘以 10,000,再除以 26262626。这会产生以下映射:
aab -> 0003
ackson -> 0392
eals -> 1908
emiel -> 1953
ounds -> 5792
对 0-25 执行上述操作,除以 25252525。 这会产生以下映射:
aab -> 0000
ackson -> 0008
eals -> 1584
emiel -> 1631
ounds -> 5623
附加样品
虽然我相信上述所有样本都是正确的,但我试图追踪更真实的样本数据点。我可以保证的如下:
姓氏
avis -> 0921
eals -> 2024
olff -> 6247
orello -> 6581
名字
Alexander -> 019
Andrew -> 042
Gabriel -> 270
Lena -> 456