| 1 | import string |
|---|
| 2 | |
|---|
| 3 | def rebase(i, frombase=None, tobase=None, fromalphabet=None, toalphabet=None, resize=1, too_big=40000, debug=False): |
|---|
| 4 | # ''' if frombase is not specified, it is guessed from the type and/or char in i with highest ord. |
|---|
| 5 | # tobase defaults to [10, 2][frombase == 10]. |
|---|
| 6 | # the alphabets are map(chr, range(256)) if its base is between 62 and 255; |
|---|
| 7 | # otherwise, string.digits+string.letters. |
|---|
| 8 | # always returns a string which is also valid input. |
|---|
| 9 | # valid bases are ints in range(-256, 257). |
|---|
| 10 | # alphabets must be subscriptable, and can only contain str's. |
|---|
| 11 | # invalid tobases are replied with 'why?'; rebase('why?') == '217648673'. |
|---|
| 12 | # returned string is zfilled to the next largest multiple of resize |
|---|
| 13 | # ''' |
|---|
| 14 | if frombase == None: |
|---|
| 15 | if isinstance(i, (int, long)): |
|---|
| 16 | frombase = 10 |
|---|
| 17 | elif isinstance(i, str): |
|---|
| 18 | a = str(i) |
|---|
| 19 | if any([(chr(x) in a) for x in range(ord('0')) + range(58, 65) + range(91, 97) + range(123, 256)]): |
|---|
| 20 | frombase = max(map(ord, a)) + 1 |
|---|
| 21 | else: |
|---|
| 22 | frombase = max(map((string.digits + string.letters).index, a)) + 1 |
|---|
| 23 | if tobase == None: |
|---|
| 24 | tobase = [10, 2][frombase == 10] |
|---|
| 25 | # got bases, ensuring that everything is an int |
|---|
| 26 | tobase = int(tobase) |
|---|
| 27 | frombase = int(frombase) |
|---|
| 28 | abstobase = abs(tobase) |
|---|
| 29 | absfrombase = abs(frombase) |
|---|
| 30 | if absfrombase in [0, 1]: |
|---|
| 31 | i = len(str(i)) |
|---|
| 32 | elif 2 <= frombase <= 36: |
|---|
| 33 | # may be difficult to translate to C |
|---|
| 34 | i = int(str(i), frombase) |
|---|
| 35 | else: |
|---|
| 36 | i = str(i) |
|---|
| 37 | n = 0 |
|---|
| 38 | if fromalphabet == None: |
|---|
| 39 | if 62 <= absfrombase <= 256: |
|---|
| 40 | fromalphabet = map(chr, range(256)) |
|---|
| 41 | else: |
|---|
| 42 | fromalphabet = string.digits + string.letters |
|---|
| 43 | fromalphabet = fromalphabet[:absfrombase] |
|---|
| 44 | for j in range(len(i)): |
|---|
| 45 | n += (frombase ** j) * fromalphabet.index(i[-1-j]) |
|---|
| 46 | i = n |
|---|
| 47 | # got ints, converting to tobase |
|---|
| 48 | if debug: print 'converting %d from base %d to %d' % (i, frombase, tobase) |
|---|
| 49 | if abstobase in [0, 1]: |
|---|
| 50 | return '0' * ((i > 0) and int(i) or 0) |
|---|
| 51 | elif abstobase > 256: |
|---|
| 52 | return 'why?' |
|---|
| 53 | # if execution gets here, we might want the result to be zfilled to a multiple of resize |
|---|
| 54 | r = '' |
|---|
| 55 | if tobase == 10: |
|---|
| 56 | r = str(i) |
|---|
| 57 | else: |
|---|
| 58 | if i < 0: |
|---|
| 59 | print 'negative', |
|---|
| 60 | i = -i |
|---|
| 61 | if toalphabet is None: |
|---|
| 62 | if 62 <= abstobase <= 256: |
|---|
| 63 | toalphabet = map(chr, range(abstobase)) |
|---|
| 64 | else: |
|---|
| 65 | toalphabet = (string.digits + string.letters)[:abstobase] |
|---|
| 66 | if tobase < 0: |
|---|
| 67 | i = -i |
|---|
| 68 | j = 0 |
|---|
| 69 | while i != 0: |
|---|
| 70 | r = toalphabet[i % tobase] + r |
|---|
| 71 | i /= tobase |
|---|
| 72 | j += 1 |
|---|
| 73 | if j >= too_big: raise "call again; set too_big bigger" |
|---|
| 74 | if resize > 1: |
|---|
| 75 | if 62 <= abstobase <= 256: |
|---|
| 76 | r = toalphabet[0] * (resize - (len(r) % resize)) + r |
|---|
| 77 | else: |
|---|
| 78 | r = r.zfill(len(r) + resize - (len(r) % resize)) |
|---|
| 79 | return r |
|---|
| 80 | |
|---|
| 81 | # 123456789 |
|---|
| 82 | # abcdefghjkmnpqrstuvwxyz |
|---|
| 83 | |
|---|
| 84 | oascii = r""" !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ """ |
|---|
| 85 | ascii = r""" !"#$%&'()*+,-./9abcdefghj:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`kmnpqrstuvwxyz12345678wxyz{|}~ """ |
|---|
| 86 | iascii = r""" !"#$%&'()*+,-./jopqrstuv0:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`12345678 9a bc defghijklmn{|}~ """ |
|---|
| 87 | def tinyid(id): |
|---|
| 88 | return rebase(id, 10, 32).translate(ascii) |
|---|
| 89 | |
|---|
| 90 | def reverseTinyid(tinyid): |
|---|
| 91 | return int(rebase(str(tinyid).translate(iascii), 32, 10)) |
|---|