【问题标题】:Generating unique non-similar codes with validation通过验证生成唯一的非相似代码
【发布时间】:2020-09-30 09:47:38
【问题描述】:

我知道有类似的问题,所以请多多包涵。

我希望生成大约 50,000 个代码供人们下订单 - 理想情况下不超过 10 个字符,并且可以包含字母和数字。它们不是折扣代码,所以我不担心人们试图猜测代码。我担心的是有人不小心输入了错误的数字(即 1 而不是 l 或 0 而不是 O),然后如果碰巧它也是一个有效的代码,系统就会失败。

由于代码不断生成,理想情况下我不想要一个表格查找验证,而是一个公式(例如,如果它包含一个 A,则数字元素应该可以被 13 整除)。

【问题讨论】:

  • 一种确保所有代码足够不同的方法是生成随机代码,然后然后添加一些对应于例如CRC的字符。 en.wikipedia.org/wiki/Cyclic_redundancy_check
  • 所以如果有人输入10 而不是IO,您希望系统不会失败?
  • 抱歉,不清楚。我不想要的是生成 2 个代码,例如 ABC123 和 ABCl23,其中输入 ABC123 的用户可能会意外输入 ABCl23 并且不会收到任何警告,因为两者都是有效的。
  • 确保您不会得到 2 个此类代码的最佳方法是在内部减少代码中的字母表,例如,只有“1”而不是“I”。这样,如果用户输入 ABCI23,您就知道他们的意思是 ABC123。你可以对 O 和 0 做同样的事情;甚至小写/大写。
  • 你听说过 Base58 吗?你可以用它来处理原始位。

标签: algorithm uniqueidentifier


【解决方案1】:

选择一些大小为 B 的字母(由数字和字母组成),以免容易混淆。为每个符号分配一个从 0 到 B-1 的值,最好以随机顺序。现在您可以使用 sequential 整数,将它们转换为基数 B 并相应地分配符号。

为了提高安全性,您可以附加一或两个校验和符号以进行错误检测。

如果 N=34(十位数字和二十四个字母 9ABHC0FVW3YGJKL1N2456XRTS78DMPQEUZ),50K 代码只需要长度为四的代码。

如果不希望生成的代码是连续的,可以在换基前打乱位。

【讨论】:

    【解决方案2】:

    在开始生成随机字符组合之前,您需要记住以下几点:


    1。脏话

    如果您的代码包含字母表中四个字母的所有可能组合,它们将不可避免地包含每个four-letter word。您需要绝对确保您永远不会要求客户输入任何违规或冒犯的内容。

    2。人为错误

    人们在输入代码时经常会出错。混淆O0 等类似字符只是问题的一部分。其他常见错误包括转置相邻字符(例如theteh)和敲错键盘上的键(例如andamd


    为避免这些问题,我建议您从不可能拼写出任何不幸的字母的受限字母中生成代码,并使用Luhn algorithm 或类似的东西来捕获意外的数据输入错误。

    例如,下面是一些 Python 代码,它使用 16 个不带元音的字母表生成十六进制代码。它使用linear congruential generator 步骤来避免输出序列号,并包含一个base-16 Luhn 校验和来检测输入错误。如果校验和不正确,code2int() 函数将返回 -1。否则它将返回一个整数。如果这个整数小于您的最大输入值(例如 50,000),那么您可以假设代码是正确的。

    def int2code(n):
        # Generates a 7-character code from an integer value (n > 0)
        alph = 'BCDFGHJKMNPRTWXZ'
        mod = 0xfffffd          # Highest 24-bit prime
        mul = 0xc36572          # Randomly selected multiplier
        add = 0x5d48ca          # Randomly selected addend
        # Convert the input number `n` into a non-sequential 6-digit
        # hexadecimal code by means of a linear congruential generator
        c = "%06x" % ((n * mul + add) % mod)
        # Replace each hex digit with the corresponding character from alph.
        # and generate a base-16 Luhn checksum at the same time
        luhn_sum = 0
        code = ''
        for i in range(6):
            d = int(c[i], 16)
            code += alph[d]
            if i % 2 == 1:
                t = d * 15
                luhn_sum += (t & 0x0f) + (t >> 4)
            else:
                luhn_sum += d
        # Append the checksum
        checksum = (16 - (luhn_sum % 16)) % 16
        code += alph[checksum]
        return code
    
    def code2int(code):
        # Converts a 7-character code back into an integer value
        # Returns -1 if the input is invalid
        alph = 'BCDFGHJKMNPRTWXZ'
        mod = 0xfffffd          # Highest 24-bit prime
        inv = 0x111548          # Modular multiplicative inverse of 0xc36572
        sub = 0xa2b733          # = 0xfffffd - 0x5d48ca
        if len(code) != 7:
            return -1
        # Treating each character as a hex digit, convert the code back into
        # an integer value. Also make sure the Luhn checksum is correct
        luhn_sum = 0
        c = 0
        for i in range(7):
            if code[i] not in alph:
                return -1
            d = alph.index(code[i])
            c = c * 16 + d
            if i % 2 == 1:
                t = d * 15
                luhn_sum += (t & 0x0f) + (t >> 4)
            else:
                luhn_sum += d
        if luhn_sum % 16 != 0:
            return -1
        # Discard the last digit (corresponding to the Luhn checksum), and undo
        # the LCG calculation to retrieve the original input value
        c = (((c >> 4) + sub) * inv) % mod
        return c
    
    # Test
    
    >>> print('\n'.join([int2code(i) for i in range(10)]))
    HWGMTPX
    DBPXFZF
    XGCFRCN
    PKKNDJB
    JPWXNRK
    DXGGCBR
    ZCPNMDD
    RHBXZKN
    KMKGJTZ
    FRWNXCH
    >>> print(all([code2int(int2code(i)) == i for i in range(50000)]))
    True
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      • 2013-05-04
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      相关资源
      最近更新 更多