地图递增的整数范围六位数基地26最大,但未经predictably整数、六位、范围、地图

2023-09-10 23:13:52 作者:谢谢赠我空欢喜

我想设计一个URL缩短为一个特定用例的最终用户和类型,我已经针对性​​。我决定,我要的URL将被存储在内部根据自动递增的整数键。但是,它也需要一个键被重新psented用户在url作为六位基$ P $ 26(亚利桑那州* 6)与它不可能predict什么基座26网址密钥基于所述递增的整数键。换句话说,第一网址键不应该是AAAAAA那么下一次某人创建一个网址它不应该被aaaaab等,并没有循环产生一个随机和捞入数据库,看它是否已反复存在。

I want to design a URL shortener for a particular use case and type of end-user that I have targetted. I have decided that I want the URLs to be stored internally according to an auto-incrementing integer key. However, it is also required that a key be represented to users in the url as six-digit base 26 (a-z * 6) AND it's not possible to predict what the base 26 url key is based on the incrementing integer key. In other words, the first url key should not be aaaaaa then the next time someone creates a url it shouldn't be aaaaab, etc, and no loop generating a random one and fishing into the database to see if it already exists repeatedly.

的要求(网址在基地26难外人predict)的第二部分是更有趣的部分。理想情况下,我想某种算法1-1映射都在26 ^ 6范围内的数字来在同一范围内的另一个数字,我可以再打印在基地26,而且我可以撤消算法和不需要存储在单独的表时,我要查询的URL。我怎样才能做到这一点?

The second part of the requirements (urls in base 26 difficult for an outsider to predict) is the more interesting part. Ideally I would like some kind of algorithmic 1-1 mapping of all of the numbers in the 26^6 range to another number in the same range that I can just then print in base 26, and that I can undo algorithmically and don't need to store in a separate table when I want to look up the url. How can I accomplish this?

推荐答案

为什么不就在洗牌位以特定的顺序转换为基26前值?例如,第0位变成第5位,第1位变成第2位,等要取消code,只是做相反。

Why not just shuffle the bits around in a specific order before converting to the base 26 value? For example, bit 0 becomes bit 5, bit 1 becomes bit 2, etc. To decode, just do the reverse.

下面是用Python的例子。 (现在编辑,包括将碱太。)

Here's an example in Python. (Edited now to include converting the base too.)

import random

# generate a random bit order
# you'll need to save this mapping permanently, perhaps just hardcode it
# map how ever many bits you need to represent your integer space
mapping = range(28)
mapping.reverse()
#random.shuffle(mapping)

# alphabet for changing from base 10
chars = 'abcdefghijklmnopqrstuvwxyz'

# shuffle the bits
def encode(n):
    result = 0
    for i, b in enumerate(mapping):
        b1 = 1 << i
        b2 = 1 << mapping[i]
        if n & b1:
            result |= b2
    return result

# unshuffle the bits
def decode(n):
    result = 0
    for i, b in enumerate(mapping):
        b1 = 1 << i
        b2 = 1 << mapping[i]
        if n & b2:
            result |= b1
    return result

# change the base
def enbase(x):
    n = len(chars)
    if x < n:
        return chars[x]
    return enbase(x/n) + chars[x%n]

# go back to base 10
def debase(x):
    n = len(chars)
    result = 0
    for i, c in enumerate(reversed(x)):
        result += chars.index(c) * (n**i)
    return result

# test it out
for a in range(200):
    b = encode(a)
    c = enbase(b)
    d = debase(c)
    e = decode(d)
    while len(c) < 7:
        c = ' ' + c
    print '%6d %6d %s %6d %6d' % (a, b, c, d, e)

该脚本的输出,显示了编码和解码过程:

The output of this script, showing the encoding and decoding process:

   0            0       a            0    0
   1    134217728  lhskyi    134217728    1
   2     67108864  fqwfme     67108864    2
   3    201326592  qyoqkm    201326592    3
   4     33554432  cvlctc     33554432    4
   5    167772160  oddnrk    167772160    5
   6    100663296  imhifg    100663296    6
   7    234881024  ttztdo    234881024    7
   8     16777216  bksojo     16777216    8
   9    150994944  mskzhw    150994944    9
  10     83886080  hbotvs     83886080   10
  11    218103808  sjheua    218103808   11
  12     50331648  egdrcq     50331648   12
  13    184549376  pnwcay    184549376   13
  14    117440512  jwzwou    117440512   14
  15    251658240  veshnc    251658240   15
  16      8388608   sjheu      8388608   16
  17    142606336  mabsdc    142606336   17
  18     75497472  gjfmqy     75497472   18
  19    209715200  rqxxpg    209715200   19

需要注意的是零映射到零,但你可以跳过这个数字。

Note that zero maps to zero, but you can just skip that number.

这是简单,高效,应该是你的目的不够好。如果你真的需要一些安全的我显然不会推荐。这基本上是一个天真的分组密码。不会有任何冲突。

This is simple, efficient and should be good enough for your purposes. If you really needed something secure I obviously would not recommend this. It's basically a naive block cipher. There won't be any collisions.

可能是最好的,以确保该位N不以往任何时候都映射到N位(无变化),可能最好的,如果在输入一些低比特被映射到较高位输出,一般。换句话说,你可能要产生手工映射。事实上,一个体面的映射是简单地颠倒位顺序。 (这就是我为上面的示例输出。)

Probably best to make sure that bit N doesn't ever map to bit N (no change) and probably best if some low bits in the input get mapped to higher bits in the output, in general. In other words, you may want to generate the mapping by hand. In fact, a decent mapping would be simply reversing the bit order. (That's what I did for the sample output above.)