Sha256: e33c27b4e437c99a0b06740f32c984bd34c389ff2b841c3f6a199c2e9c259017

Contents?: true

Size: 756 Bytes

Versions: 3

Compression:

Stored size: 756 Bytes

Contents

# frozen_string_literal: true

class WeightedList
  class Sampler
    def initialize(hash, random: Random)
      @hash = hash.clone
      @random = random
    end

    def call
      Result.new(chosen, remaining)
    end

    private

    attr_reader :hash, :random

    Result = Struct.new(:chosen, :remaining)

    def choose
      return if hash.empty?
      current_target = random.rand(total_weight)

      hash.each do |item, weight|
        return item if current_target <= weight
        current_target -= weight
      end
    end

    def chosen
      @chosen ||= choose
    end

    def remaining
      hash.reject { |item, _weight| chosen == item }
    end

    def total_weight
      @total_weight ||= hash.values.reduce(&:+)
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
weighted_list-0.3.0 lib/weighted_list/sampler.rb
weighted_list-0.2.0 lib/weighted_list/sampler.rb
weighted_list-0.1.0 lib/weighted_list/sampler.rb