XORing long strings opimization?

Peter Otten __peter__ at web.de
Tue Nov 4 19:09:49 EST 2003


Francis Avila wrote:

> "Noen" <not.available at na.no> wrote in message
> news:ieUpb.24457$BD3.4567875 at juliett.dax.net...
>> nope, thought the Argument check would do it, but I used and opeartor
>> instead of or. Well, here is XOR v.0.3b :P Any comments how to make it
>> faster?
> 
> How about using the struct module?
> Caveat: I don't know if struct limits the repeat count.
> 
> import struct
> def XOR(data, key):
>     if len(data) != len(key):
>         raise ValueError, "data and key not of equal length"
>     ldata = struct.unpack('=%sb' % len(data), data)
>     lkey = struct.unpack('=%sb' % len(key), key)
>     lxored = [d^k for d,k in zip(ldata, lkey)]
>     xored = struct.pack('=%sb' % len(lxored), *lxored)
>     return xored
> 
> Just an idea.
> --
> Francis Avila

Nope. Both your and my approach make it worse. Only Alex Martelli did it
right:

import itertools, array, struct

def xor_noen(s1,s2):
     """ XOR string s1 with s2 """
     output = ""
     for i in range(len(s1)):
         output += chr(ord(s1[i]) ^ ord(s2[i]))
     return output

def xor_po(s1, s2):
    return "".join([chr(ord(c1) ^ ord(c2)) for c1, c2 in itertools.izip(s1,
s2)])

def xor_am(s1, s2):
    x = array.array("b", s2)
    for i, v in enumerate(array.array("b", s1)):
        x[i] ^= v
    return x.tostring()

def xor_fa(data, key):
    ldata = struct.unpack('=%sb' % len(data), data)
    lkey = struct.unpack('=%sb' % len(key), key)
    lxored = [d^k for d,k in zip(ldata, lkey)]
    xored = struct.pack('=%sb' % len(lxored), *lxored)
    return xored

# 35 usec
def pro_noen():
    return xor_noen("sgnirts ni sreffid eziS", "Size differs in strings")

# 40 usec
def pro_po():
    return xor_po("sgnirts ni sreffid eziS", "Size differs in strings")

# 23 usec
def pro_am():
    return xor_am("sgnirts ni sreffid eziS", "Size differs in strings")

# 46 usec
def pro_fa():
    return xor_fa("sgnirts ni sreffid eziS", "Size differs in strings")

assert pro_po() == pro_am() == pro_fa() == pro_noen()

I was surprised how good pro_noen() does, but that might change for large
strings. By the way, results varied significantly (several usecs) in
various test runs.

Peter






More information about the Python-list mailing list