forked from kodecocodes/swift-algorithm-club
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add examples to description Add playground Add test project
- Loading branch information
Showing
8 changed files
with
488 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
//: Playground - noun: a place where people can play | ||
|
||
public class BloomFilter<T> { | ||
private var array: [Bool] | ||
private var hashFunctions: [T -> Int] | ||
|
||
public init(size: Int = 1024, hashFunctions: [T -> Int]) { | ||
self.array = .init(count: size, repeatedValue: false) | ||
self.hashFunctions = hashFunctions | ||
} | ||
|
||
private func computeHashes(value: T) -> [Int] { | ||
return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } | ||
} | ||
|
||
public func insert(element: T) { | ||
for hashValue in computeHashes(element) { | ||
array[hashValue] = true | ||
} | ||
} | ||
|
||
public func insert(values: [T]) { | ||
for value in values { | ||
insert(value) | ||
} | ||
} | ||
|
||
public func query(value: T) -> Bool { | ||
let hashValues = computeHashes(value) | ||
|
||
// Map hashes to indices in the Bloom Filter | ||
let results = hashValues.map() { hashValue in array[hashValue] } | ||
|
||
// All values must be 'true' for the query to return true | ||
|
||
// This does NOT imply that the value is in the Bloom filter, | ||
// only that it may be. If the query returns false, however, | ||
// you can be certain that the value was not added. | ||
|
||
let exists = results.reduce(true, combine: { $0 && $1 }) | ||
return exists | ||
} | ||
|
||
public func isEmpty() -> Bool { | ||
// As soon as the reduction hits a 'true' value, the && condition will fail. | ||
return array.reduce(true) { prev, next in prev && !next } | ||
} | ||
} | ||
|
||
|
||
|
||
/* Two hash functions, adapted from http://www.cse.yorku.ca/~oz/hash.html */ | ||
|
||
func djb2(x: String) -> Int { | ||
var hash = 5381 | ||
for char in x.characters { | ||
hash = ((hash << 5) &+ hash) &+ char.hashValue | ||
} | ||
return Int(hash) | ||
} | ||
|
||
func sdbm(x: String) -> Int { | ||
var hash = 0 | ||
for char in x.characters { | ||
hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash | ||
} | ||
return Int(hash) | ||
} | ||
|
||
|
||
|
||
/* A simple test */ | ||
|
||
let bloom = BloomFilter<String>(size: 17, hashFunctions: [djb2, sdbm]) | ||
|
||
bloom.insert("Hello world!") | ||
print(bloom.array) | ||
|
||
bloom.query("Hello world!") // true | ||
bloom.query("Hello WORLD") // false | ||
|
||
bloom.insert("Bloom Filterz") | ||
print(bloom.array) | ||
|
||
bloom.query("Bloom Filterz") // true | ||
bloom.query("Hello WORLD") // true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='5.0' target-platform='osx'> | ||
<timeline fileName='timeline.xctimeline'/> | ||
</playground> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Timeline | ||
version = "3.0"> | ||
<TimelineItems> | ||
</TimelineItems> | ||
</Timeline> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,46 @@ | ||
import Foundation | ||
|
||
public class BloomFilter<T> { | ||
private(set) private var arr: [Bool] | ||
private(set) private var hashFunctions: [T -> Int] | ||
|
||
public init(size: Int = 1024, hashFunctions: [T -> Int]) { | ||
self.arr = Array<Bool>(count: size, repeatedValue: false) | ||
self.hashFunctions = hashFunctions | ||
private var array: [Bool] | ||
private var hashFunctions: [T -> Int] | ||
|
||
public init(size: Int = 1024, hashFunctions: [T -> Int]) { | ||
self.array = .init(count: size, repeatedValue: false) | ||
self.hashFunctions = hashFunctions | ||
} | ||
|
||
private func computeHashes(value: T) -> [Int] { | ||
return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } | ||
} | ||
|
||
public func insert(element: T) { | ||
for hashValue in computeHashes(element) { | ||
array[hashValue] = true | ||
} | ||
private func computeHashes(value: T) -> [Int] { | ||
return hashFunctions.map() { hashFunc in | ||
abs(hashFunc(value) % self.arr.count) | ||
} | ||
} | ||
|
||
public func insert(values: [T]) { | ||
for value in values { | ||
insert(value) | ||
} | ||
} | ||
|
||
public func query(value: T) -> Bool { | ||
let hashValues = computeHashes(value) | ||
|
||
public func insert(toInsert: T) { | ||
let hashValues: [Int] = self.computeHashes(toInsert) | ||
|
||
for hashValue in hashValues { | ||
self.arr[hashValue] = true | ||
} | ||
} | ||
// Map hashes to indices in the Bloom Filter | ||
let results = hashValues.map() { hashValue in array[hashValue] } | ||
|
||
public func insert(values: [T]) { | ||
for value in values { | ||
self.insert(value) | ||
} | ||
} | ||
// All values must be 'true' for the query to return true | ||
|
||
public func query(value: T) -> Bool { | ||
let hashValues = self.computeHashes(value) | ||
|
||
// Map hashes to indices in the Bloom filter | ||
let results = hashValues.map() { hashValue in | ||
self.arr[hashValue] | ||
} | ||
|
||
// All values must be 'true' for the query to return true | ||
|
||
// This does NOT imply that the value is in the Bloom filter, | ||
// only that it may be. If the query returns false, however, | ||
// you can be certain that the value was not added. | ||
|
||
let exists = results.reduce(true, combine: { $0 && $1 }) | ||
|
||
return exists | ||
} | ||
|
||
public func isEmpty() -> Bool { | ||
// Reduce list; as soon as the reduction hits a 'true' value, the && condition will fail | ||
return arr.reduce(true) { prev, next in | ||
prev && !next | ||
} | ||
} | ||
// This does NOT imply that the value is in the Bloom filter, | ||
// only that it may be. If the query returns false, however, | ||
// you can be certain that the value was not added. | ||
|
||
} | ||
let exists = results.reduce(true, combine: { $0 && $1 }) | ||
return exists | ||
} | ||
|
||
public func isEmpty() -> Bool { | ||
// As soon as the reduction hits a 'true' value, the && condition will fail. | ||
return array.reduce(true) { prev, next in prev && !next } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
...r/BloomFilterTests/BloomFilterTests.swift → Bloom Filter/Tests/BloomFilterTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>en</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>BNDL</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0</string> | ||
<key>CFBundleSignature</key> | ||
<string>????</string> | ||
<key>CFBundleVersion</key> | ||
<string>1</string> | ||
</dict> | ||
</plist> |
Oops, something went wrong.