 
 import Foundation
 
-struct HashTable <K : Hashable, V> : CustomStringConvertible {
-    
-    private(set) var table          : [[(key: K, value: V)]]
-    private(set) var hashFunction   : K -> Int
-    
-    init(_ f: K -> Int) {
+struct HashTableElement<K> : Hashable {
+    let key : Int
+    var elem : K?
+    var hashValue : Int { return key }
+}
+
+func ==<K>(lhs: HashTableElement<K>, rhs: HashTableElement<K>) -> Bool {
+    return lhs.key == rhs.key
+}
+
+protocol HashTableType : CustomStringConvertible {
+    associatedtype Element : Hashable
+    
+    // init(_ f: Element -> Int)
+    // init(_ array: [Element]) throws
+    // init()
+    // init(_ buckets : Int)
+    // init(_ buckets: Int, _ array: [Element]) throws
+    // init(_ buckets : Int, hashFunction: Element -> Int)
+    mutating func insert(elements: Element...) throws
+    mutating func insert(elements: [Element]) throws
+    mutating func insertNoCorrection(element new: Element) throws
+    mutating func overwriteOrAdd(element: Element) throws
+    mutating func executeForKey<T>(key: Element, f: (Int,Int?) throws -> T) throws -> T
+    mutating func executeForUniqueKey<T>(key: Element, f: (Int,Int?) throws -> T) throws -> T
+    mutating func overwrite(element: Element) throws
+    mutating func insert(element new: Element) throws
+    mutating func get(key key: Element) throws -> Element
+    mutating func remove(key key: Element) throws -> Element
+    mutating func correctBucketCount() throws
+    func hash(key: Element) throws -> Int
+    mutating func changeBucketCount(buckets: Int) throws
+    mutating func changeBucketCount(buckets: Int, f: Element -> Int) throws
+    mutating func hash(newHash: Element -> Int) throws
+    func sort()
+    var array : [Element] { get }
+    var buckets : Int { get }
+    var count : Int { get }
+    var description: String { get }
+}
+
+struct HashTable <Element : Hashable> : HashTableType {
+    
+    //P.ERFORMANCE: making table of type [[[(K,V)]]] with the second list being hashed, too?
+    private(set) var table          : [[Element]]
+    private(set) var hashFunction   : Element -> Int
+    
+    init(_ f: Element -> Int) {
         self.init()
         hashFunction = f
     }
     
-    init(_ array: [(K, V)]) throws {
+    init(_ array: [Element]) throws {
         self.init()
         for v in array {
             try insert(element: v)
         }
     }
     
-    init(_ array: [(K, V)], buckets: Int) throws {
+    init(_ array: [Element], buckets: Int) throws {
         self.init(buckets)
         for v in array {
             try insert(element: v)

        return array
    }
    
    var count : Int {
        var c = 0
        for arr in table {

            print("did end because tc * 2 < 5: " + table.count)
            return
        }
        if max > count / tc {
            print("increasing bucket count!")
            try changeBucketCount(tc)
        }
