Python3 replace ord() and chr()

1.5k Views Asked by At
        for i in word:
            c = ord(i) - int(key)
            if c < 97:
                c = c + 26
            b = chr(c)
            text += b

Is there another way to replace this without ord() and chr()?

Thank you very much!

1

There are 1 best solutions below

7
On

Here is a code using numpy module plus UTF-32 encoding/decoding. This code will be very fast for large data, and needs no Python loops.

numpy module is easily installed using python -m pip install numpy. If you need solution without numpy, using plain Python, and running speed is not an issue, tell me and I'll rewrite, but in plain Python code will work much slower on big data.

You can also run this code online here.

# Needs: python -m pip install numpy
import numpy as np

word = 'Duck'
key = 1

a = np.frombuffer(word.encode('utf-32-le'), dtype = np.int32)
a = a - key
a[a < 97] += 26

text = a.tobytes().decode('utf-32-le')

print(text)

And similar slower next solution but without numpy, using just standard Python's built-in module struct. You can also run next code online.

import struct

word = 'Duck'
key = 1

text = ''

for i in word:
    c = struct.unpack('<I', i.encode('utf-32-le'))[0] - int(key)
    if c < 97:
        c = c + 26
    b = struct.pack('<I', c).decode('utf-32-le')
    text += b
    
print(text)

Another solution below without using any module. Run next code online.

word = 'Duck'
key = 1

text = ''

for i in word:
    c = int(i.encode('utf-32-be').hex(), 16) - int(key)
    if c < 97:
        c = c + 26
    b = bytes.fromhex(hex(c)[2:].zfill(8)).decode('utf-32-be')
    text += b
    
print(text)

If text symbols are only from ASCII set then code can be simplified even further (run this code online):

word = 'Duck'
key = 1

text = ''

for i in word:
    c = i.encode('ascii')[0] - int(key)
    if c < 97:
        c = c + 26
    b = bytes((c,)).decode('ascii')
    text += b
    
print(text)

One more solution for the case of ASCII chars, using two tables (run this code online)

word = 'Duck'
key = 1

tmp = [(c, i) for i, c in enumerate(bytes(range(128)).decode('ascii'))]
c2i = dict(tmp)
i2c = [e[0] for e in tmp]

text = ''

for i in word:
    c = c2i[i] - int(key)
    if c < 97:
        c = c + 26
    b = i2c[c]
    text += b
    
print(text)

Previous code can be extended from ASCII to wider char set (e.g. 16-bit) by replacing next line (run this code online):

tmp = [(bytes.fromhex(hex(i)[2:].zfill(8)).decode('utf-32-be', 'replace'), i) for i in range(1 << 16)]