class WeightedTable

This class contains objects and associate weights to them. So that you can sample the object according to their weights.

@author Cédric ZUGER

Constants

BASE_WEIGHT

Public Class Methods

from_file( filename ) click to toggle source

Read the table from a file @param filename [String] the filename from which to read the table

# File lib/weighted_table.rb, line 94
def self.from_file( filename )
  YAML.load_file( filename )
end
from_flat_table( table ) click to toggle source

Load a WeightedTable with data Data format must be : [ data, data, data ] Example : [ :foo, :foo, :bar ]

@return [WeightedTable] the current WeightedTable

# File lib/weighted_table.rb, line 59
def self.from_flat_table( table )
  from_weighted_table( table.group_by{ |e| e }.map{ |k, v| [ v.count, k ] } )
end
from_weighted_table( table ) click to toggle source

Load a WeightedTable with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]

@return [WeightedTable] the current WeightedTable

# File lib/weighted_table.rb, line 23
def self.from_weighted_table( table )
  WeightedTable.new.from_weighted_table( table )
end
new( floating_points: false ) click to toggle source

Initialize a WeightedTable setting floating_points to true indicate that you will work with floating points rather than integers.

# File lib/weighted_table.rb, line 12
def initialize( floating_points: false )
  @weights = []
  @max_weight = BASE_WEIGHT
  @floating_points = floating_points
end

Public Instance Methods

from_weighted_table( table ) click to toggle source

Load a WeightedTable with data Data format must be : [ [ weight, data ], [ weight, data ], … ] Example : [ [ 2, :foo ], [ 1, :bar ] ]

@return [WeightedTable] the current WeightedTable

# File lib/weighted_table.rb, line 32
def from_weighted_table( table )
  raise 'Table must contain at least one element' if table.empty?

  # We may call this method many time for an existing object, so we must clear it
  @weights.clear

  base = BASE_WEIGHT
  w = nil

  table.each do |weight, data|
    w = base + weight
    @weights << [base, w, data]
    base = w
  end

  @max_weight = w

  # p @weights, @max_weight

  self
end
sample() click to toggle source

Return a random item from a WeightedTable

@return [Object] a random object given at the building of the table.

# File lib/weighted_table.rb, line 66
def sample

  # ... means that @max_weight is excluded
  if @floating_points
    r = Kernel.rand( 0.0...@max_weight.to_f )
  else
    r = Kernel.rand( 0...@max_weight )
  end

  # p r

  @weights.each do |base_weight, max_weight, data|
    return data if r >= base_weight && r < max_weight
  end

  raise 'Rand not in key range'
end
to_file( filename ) click to toggle source

Save the table to a file @param filename [String] the filename where to save the table

# File lib/weighted_table.rb, line 86
def to_file( filename )
  File.open( filename, 'w' ) do |f|
    f.write( to_yaml )
  end
end