""" Generate constant hash tables. The `constant_hash` module can generate constant pre-populated hash tables. We don't attempt parfect hashing, but simply generate an open addressed quadratically probed hash table. """ def simple_hash(s): """ Compute a primitive hash of a string. Example: >>> hex(simple_hash("Hello")) '0x2fa70c01' >>> hex(simple_hash("world")) '0x5b0c31d5' """ h = 5381 for c in s: h = ((h ^ ord(c)) + ((h >> 6) + (h << 26))) & 0xffffffff return h def next_power_of_two(x): """ Compute the next power of two that is greater than `x`: >>> next_power_of_two(0) 1 >>> next_power_of_two(1) 2 >>> next_power_of_two(2) 4 >>> next_power_of_two(3) 4 >>> next_power_of_two(4) 8 """ s = 1 while x & (x + 1) != 0: x |= x >> s s *= 2 return x + 1 def compute_quadratic(items, hash_function): """ Compute an open addressed, quadratically probed hash table containing `items`. The returned table is a list containing the elements of the iterable `items` and `None` in unused slots. :param items: Iterable set of items to place in hash table. :param hash_function: Hash function which takes an item and returns a number. Simple example (see hash values above, they collide on slot 1): >>> compute_quadratic(['Hello', 'world'], simple_hash) [None, 'Hello', 'world', None] """ items = list(items) # Table size must be a power of two. Aim for >20% unused slots. size = next_power_of_two(int(1.20*len(items))) table = [None] * size for i in items: h = hash_function(i) % size s = 0 while table[h] is not None: s += 1 h = (h + s) % size table[h] = i return table if __name__ == "__main__": import doctest doctest.testmod()