code: def sample_following_dist(handle_iter, n, totalf):
      
      multiplier = 1.0
      if totalf == 1.0:
          multiplier = 1e8
          # print "WARNING!! I don't except probabilities"
  
      totalf = totalf * multiplier
      print("# Population Size", totalf)
      A = np.sort(np.unique(np.random.randint(0, totalf, size=n*2))[:n])
      A = A[::-1]
      # Uniqueness check, non necessarily required, but not very
      # computationally intensive
      assert len(A) == n, "Not enough randomnumbers generated"\
          "Requried {}, generated only {}".format(n, len(A))
      j = 0
      sampled = 0
      val = A.pop()
      # print handle_iter
      for _,w,f in handle_iter:
          j += f*multiplier
          if not A: break
          while val<j:
              sampled += 1
              if sampled %5000 == 0:
                  print ("Sampled:",sampled)
              yield (val, w)
              if A:
                  val = A.pop()
              else:
                  break
  
      print ("# Stopped at:", w, f, j, '\n')
      while A and val<j:
          yield (val, w)
          if A:
              i, val = A.pop()
          else:
              break
docs: Samples n passwords following the distribution from the handle
      @handle_iter is an iterator that gives (pw,f) @n is the total
      number of samle asked for @totalf is the total number of users,
      which is euqal to sum(f for pw,f in handle_iter)
      As, handle_iterator is an iterator and can only traverse once, @totalf
      needs to be supplied to the funciton.
  
      Returns, an array of @n tuples (id, pw) sampled from @handle_iter.