Advertisement
Guest User

Untitled

a guest
Jan 16th, 2018
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 3.07 KB | None | 0 0
  1. package net.verdagon.vcompiler.carpenter
  2.  
  3. case class LeveledTable[K, V](
  4.     hasher: K => Int,
  5.     table: Array[Array[Option[(K, V)]]]) {
  6.   def get(key: K): Option[V] = {
  7.     val hash = hasher(key);
  8.     val indexInTopLevel = hash % table.size;
  9.     val bucket = table(indexInTopLevel);
  10.     val indexInBucket = hash % bucket.length;
  11.     bucket(indexInBucket) match {
  12.       case None => None
  13.       case Some((foundKey, foundValue)) => {
  14.         if (foundKey == key) Some(foundValue) else None
  15.       }
  16.     }
  17.   }
  18. }
  19.  
  20. class LeveledTableGenerator[K, V] {
  21.   def generateTetrisTable(map: Map[K, V], hasher: K => Int): LeveledTable[K, V] = {
  22.     if (map.isEmpty) {
  23.       LeveledTable[K, V](hasher, Array(Array()))
  24.     }
  25.     val hashes = map.keys.zip(map.keys).toMap.mapValues(hasher);
  26.  
  27.     val initialTopLevelSize = Math.ceil(map.size / 4.0).toInt;
  28.     val listBuckets = bucketize(hashes, initialTopLevelSize);
  29.     val hashBuckets = listBuckets.map(listBucket => hashifyBucket(hashes, listBucket))
  30.     val hashBucketsWithValues = hashBuckets.map(hashBucket => {
  31.       hashBucket.map(maybeKey => {
  32.         maybeKey.map(key => {
  33.           (key -> map(key))
  34.         })
  35.       })
  36.     })
  37.     LeveledTable[K, V](hasher, hashBucketsWithValues)
  38.   }
  39.  
  40.   private def bucketize(hashes: Map[K, Int], topLevelSize: Int): Array[List[K]] = {
  41.     val initialBuckets = (0 until topLevelSize).map(_ => List[K]()).toVector
  42.     val filledBuckets =
  43.       hashes.foldLeft(initialBuckets)({
  44.         case (buckets, (key, hash)) => {
  45.           val index = hash % topLevelSize;
  46.           buckets.updated(index, key :: buckets(index))
  47.         }
  48.       })
  49.     // It's *extremely* unlikely, but if any of the buckets are too large (contain more than a
  50.     // fourth of all the values) then we need to pick a different topLevelSize.
  51.     if (filledBuckets.forall(_.size <= topLevelSize / 4)) {
  52.       // It's fine, return it.
  53.       filledBuckets.toArray
  54.     } else {
  55.       // Try again with a slightly larger top level size.
  56.       bucketize(hashes, topLevelSize + 1)
  57.     }
  58.   }
  59.  
  60.   private def hashifyBucket(hashes: Map[K, Int], listBucket: List[K]): Array[Option[K]] = {
  61.     hashifyBucketInner(hashes, listBucket, listBucket.size)
  62.   }
  63.  
  64.   private def hashifyBucketInner(hashes: Map[K, Int], listBucket: List[K], hashBucketSize: Int): Array[Option[K]] = {
  65.     val initialHashBucket: Array[Option[K]] = (0 until hashBucketSize).map(_ => None).toArray
  66.     val resultMaybeHashBucket =
  67.       listBucket.foldLeft[Option[Array[Option[K]]]](Some(initialHashBucket))((maybeHashBucket, key) => {
  68.         maybeHashBucket match {
  69.           case None => None
  70.           case Some(hashBucket) => {
  71.             val index = hashes(key) % hashBucketSize;
  72.             hashBucket(index) match {
  73.               case Some(_) => None
  74.               case None => Some(hashBucket.updated(index, Some(key)))
  75.             }
  76.           }
  77.         }
  78.       })
  79.     resultMaybeHashBucket match {
  80.       case Some(resultHashBucket) => resultHashBucket
  81.       case None => hashifyBucketInner(hashes, listBucket, hashBucketSize + 1)
  82.     }
  83.   }
  84. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement