Skip to content

Commit ec470dc

Browse files
authored
Merge pull request #162 from knaxus/bloom-filters
Bloom filters
2 parents d77dbb7 + b3ef051 commit ec470dc

File tree

4 files changed

+184
-6
lines changed

4 files changed

+184
-6
lines changed

TOC.md

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
- [K Largest Elements](src/_DataStructures_/Heaps/k-largest-in-array)
5151
- [K Smallest Elements](src/_DataStructures_/Heaps/k-smallest-in-array)
5252
- [Hash Table](src/_DataStructures_/HashTable)
53+
- [Set](src/_DataStructures_/Set)
54+
- [Bloom Filters](src/_DataStructures_/BloomFilters)
5355

5456
### Logical Problems
5557

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
class BloomFilters {
2+
constructor(size = 101) {
3+
this.size = size;
4+
this.data = this.getStorage(size);
5+
}
6+
7+
add(element) {
8+
const indices = this.getIndices(element);
9+
10+
for (let i = 0; i < indices.length; i += 1) {
11+
this.data.setBit(indices[i]);
12+
}
13+
}
14+
15+
contains(element) {
16+
const indices = this.getIndices(element);
17+
18+
for (let i = 0; i < indices.length; i += 1) {
19+
const index = indices[i];
20+
if (!this.data.getBit(index)) {
21+
return false; // item is definately not there
22+
}
23+
}
24+
return true; // item may be there
25+
}
26+
27+
getIndices(element) {
28+
return [this.hashOne(element), this.hashTwo(element), this.hashThree(element)];
29+
}
30+
31+
hashOne(value) {
32+
const stringValue = String(value);
33+
let hashVal = 0;
34+
35+
for (let i = 0; i < stringValue.length; i += 1) {
36+
hashVal += stringValue.charCodeAt(i) - 96;
37+
}
38+
39+
// eslint-disable-next-line no-bitwise
40+
hashVal &= hashVal;
41+
42+
return Math.abs(hashVal % this.size);
43+
}
44+
45+
hashTwo(value) {
46+
const stringValue = String(value);
47+
const PRIME_MULTIPLIER = 1801; // Random prime number
48+
let hashVal = 0;
49+
50+
for (let i = 0; i < stringValue.length; i += 1) {
51+
hashVal += stringValue.charCodeAt(i) - 96;
52+
hashVal *= PRIME_MULTIPLIER;
53+
}
54+
55+
return Math.abs(hashVal % this.size);
56+
}
57+
58+
hashThree(value) {
59+
const stringValue = String(value);
60+
const PRIME_MULTIPLIER = 1801; // Random prime number
61+
const PRIME_ADDER = 2029; // Random prime number
62+
let hashVal = 0;
63+
64+
for (let i = 0; i < stringValue.length; i += 1) {
65+
hashVal += stringValue.charCodeAt(i) - 96;
66+
hashVal *= PRIME_MULTIPLIER;
67+
hashVal += PRIME_ADDER;
68+
}
69+
// eslint-disable-next-line no-bitwise
70+
hashVal &= hashVal;
71+
return Math.abs(hashVal % this.size);
72+
}
73+
74+
// eslint-disable-next-line class-methods-use-this
75+
getStorage(size) {
76+
const data = new Array(size).fill(0);
77+
78+
return {
79+
setBit(index) {
80+
data[index] = 1;
81+
},
82+
getBit(index) {
83+
return data[index];
84+
},
85+
};
86+
}
87+
}
88+
89+
// const b = new BloomFilters();
90+
91+
// b.add('React.js');
92+
// b.add('Node.js');
93+
94+
// console.log(b.contains('JavaScript'));
95+
// console.log(b.contains('React.js'));
96+
97+
module.exports = BloomFilters;

src/_DataStructures_/HashTable/index.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ class HashTable {
1111
this.threshold = 0.7;
1212
// the main bucket
1313
this.bucket = new Array(this.slot);
14+
// fill the bucket with null
15+
// for (let i = 0; i < this.slot; i += 1) this.bucket[i] = null;
16+
this.bucket.fill(null);
1417
this.allowResize = allowResize;
1518
this.strongHash = strongHash;
1619
if (custonHash) {
1720
// eslint-disable-next-line no-underscore-dangle
1821
this._hash = custonHash;
1922
}
20-
21-
// fill the bucket with null
22-
for (let i = 0; i < this.slot; i += 1) this.bucket[i] = null;
2323
}
2424

2525
_hash(key) {
@@ -36,12 +36,14 @@ class HashTable {
3636
for (let i = 0; i < loopTill; i += 1) {
3737
const char = stringKey[i];
3838
const value = char.charCodeAt(0) - 96;
39-
index = (index * PRIME_MULTIPLIER + value) % this.bucket.length;
39+
// eslint-disable-next-line no-bitwise
40+
index &= index;
41+
index = index * PRIME_MULTIPLIER + value;
4042
if (this.strongHash) {
41-
index = (index + PRIME_ADDER) % this.bucket.length;
43+
index += PRIME_ADDER;
4244
}
4345
}
44-
return index;
46+
return Math.abs(index % this.bucket.length);
4547
}
4648

4749
_resize() {

src/_DataStructures_/Set/index.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// XSet because ES6 already has a Set class
2+
class XSet {
3+
constructor() {
4+
this.data = this.getStore();
5+
}
6+
7+
add(element) {
8+
this.data.push(element);
9+
}
10+
11+
remove(element) {
12+
this.data.pop(element);
13+
}
14+
15+
has(element) {
16+
return this.data.contains(element);
17+
}
18+
19+
values() {
20+
return this.data.val();
21+
}
22+
23+
union(givenSet) {
24+
const result = new Set();
25+
const firstSetValues = this.values();
26+
const givenSetValues = givenSet.values();
27+
28+
// eslint-disable-next-line no-restricted-syntax
29+
for (const e of firstSetValues) result.add(e);
30+
31+
// eslint-disable-next-line no-restricted-syntax
32+
for (const e of givenSetValues) result.add(e);
33+
34+
return result;
35+
}
36+
37+
// eslint-disable-next-line class-methods-use-this
38+
getStore() {
39+
const store = {};
40+
41+
return {
42+
push(el) {
43+
if (!store[el]) {
44+
store[el] = true;
45+
}
46+
},
47+
pop(el) {
48+
if (store[el]) {
49+
delete store[el];
50+
}
51+
},
52+
contains(el) {
53+
return !!store[el];
54+
},
55+
val() {
56+
return Object.keys(store);
57+
},
58+
};
59+
}
60+
}
61+
62+
// const s = new XSet();
63+
64+
// s.add(10);
65+
// s.add(20);
66+
// s.add(90);
67+
68+
// console.log(s.has(1));
69+
// console.log(s.has(10));
70+
// console.log(s.has(90));
71+
72+
// console.log(s.values());
73+
// s.remove(90);
74+
// console.log(s.has(90));
75+
// console.log(s.data);
76+
77+
module.exports = XSet;

0 commit comments

Comments
 (0)