How "full" the filter is drives its accuracy, the more bits set, the more likely a random lookup collides into a false positive. Expose two metrics:
count_set_bits(): how many bits are 1fill_ratio(): the fraction of bits set (count_set_bits / size)Adding the same item twice must not change either number. The bits were already 1.
import hashlib
def _default_hash(item, i, size):
return int(hashlib.md5(f"{i}:{item}".encode()).hexdigest(), 16) % size
class BloomFilter:
def __init__(self, size, num_hashes, hash_fn=None):
self.size = size
self.num_hashes = num_hashes
self.hash_fn = hash_fn
self._bits = bytearray(size)
def _indices(self, item):
if self.hash_fn is not None:
return [self.hash_fn(item, i) for i in range(self.num_hashes)]
return [_default_hash(item, i, self.size) for i in range(self.num_hashes)]
def add(self, item):
for idx in self._indices(item):
self._bits[idx] = 1
def contains(self, item):
return all(self._bits[idx] for idx in self._indices(item))
def count_set_bits(self):
"""Number of bits currently set to 1."""
# TODO
pass
def fill_ratio(self):
"""Fraction of the bit array that is set (0.0 to 1.0)."""
# TODO
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
How "full" the filter is drives its accuracy, the more bits set, the more likely a random lookup collides into a false positive. Expose two metrics:
count_set_bits(): how many bits are 1fill_ratio(): the fraction of bits set (count_set_bits / size)Adding the same item twice must not change either number. The bits were already 1.
Press Run Tests or ββ© to check your solution.