diff --git a/bloom_filters/src/bloom_filters/Main.java b/bloom_filters/src/bloom_filters/Main.java index 4caeac6..5a96fed 100644 --- a/bloom_filters/src/bloom_filters/Main.java +++ b/bloom_filters/src/bloom_filters/Main.java @@ -36,9 +36,66 @@ class Hash { } } -class Examples { - void testTheThing(Tester t) { - t.checkExpect(true, true); - t.checkExpect(false, false); +class Bloom { + int n; // Number of things added. + int m; // The length of the buffer. + int k; // The number of hash functions to apply. + boolean[] v; // The bit vector. + + Bloom(int k, int m) { + if (k < 1 || m < 1) + throw new IllegalArgumentException("Need bigger arguments."); + + this.m = m; + this.k = k; + this.v = new boolean[m]; // Initialize the bit vector. + } + + void add(Object o) { // Apply the hash functions. + // Get the array of hashes for an object. + int[] hashes = Hash.hash(o, this.k, this.m); + // Set those elements in the vector to true. + for (int h : hashes) this.v[h] = true; + this.n++; + } + + // Returns true if it might contain the object, false if it definitely does + // not. + boolean has(Object o) { + // Get the array of hashes for an object. + int[] hashes = Hash.hash(o, this.k, this.m); + // Check that all of those are true. + for (int h : hashes) + if (!this.v[h]) return false; + return true; + } + + // Predict the false positive rate. + double probT2() { + return Math.pow( + 1 - Math.pow(Math.E, ((-this.k * this.n) / this.m)), this.k + ); + } + + // Return the number of elements added. + int added() { return this.n; } + + void clear() { + this.v = new boolean[this.m]; + this.n = 0; + } +} + +class Examples { + void testBloomAddAndHas(Tester t) { + Bloom b = new Bloom(2, 8); + t.checkExpect(b.has(7), false); + b.add(1); + t.checkExpect(b.has(1), true); + b.add(2); + b.add(3); + t.checkExpect(b.has(2) && b.has(3), true); + t.checkExpect(b.has(0), false); + t.checkExpect(b.added(), 3); } }