Class: MTK::Patterns::Choice

Inherits:
Pattern
  • Object
show all
Defined in:
lib/mtk/patterns/choice.rb

Overview

Randomly choose from a list of elements.

Supports giving different weights to different choices. Default is to weight all choices equally.

Instance Attribute Summary

Attributes inherited from Pattern

#cycle_count, #element_count, #elements, #max_cycles, #max_elements, #min_elements, #options

Instance Method Summary collapse

Methods inherited from Pattern

#empty?, from_a, #max_cycles_exceeded?, #max_elements_exceeded?, #min_elements_unmet?, #next, #rewind, #rewind_or_cycle

Methods included from Groups::Collection

#==, #[], #clone, #concat, #each, #empty?, #enumerable_map, #first, #last, #map, #partition, #permute, #repeat, #reverse, #rotate, #size, #to_a

Constructor Details

#initialize(elements, options = {}) ⇒ Choice

Returns a new instance of Choice.

Examples:

choose the second element twice as often as the first or third:

MTK::Pattern::Choice.new [:first,:second,:third], :weights => [1,2,1]

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

  • elements (Enumerable)

    the list of elements in the pattern

  • options (Hash) (defaults to: {})

    the pattern options

Options Hash (options):

  • :weights (Array)

    a list of chances that each corresponding element will be selected (normalized against the total weight)

  • :max_elements (Fixnum)

    the Pattern#max_elements (default is nil, which means unlimited)

  • :max_cycles (Fixnum)

    the Pattern#max_cycles (default is 1)



16
17
18
19
20
# File 'lib/mtk/patterns/choice.rb', line 16

def initialize(elements, options={})
  super
  @weights = options.fetch :weights, Array.new(@elements.length, 1)
  @total_weight = @weights.inject(:+).to_f
end

Instance Method Details

#advanceObject (protected)

Raises:

  • (StopIteration)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/mtk/patterns/choice.rb', line 25

def advance
  @index += 1
  raise StopIteration if @index > 0

  target = rand * @total_weight
  @weights.each_with_index do |weight,index|
    if target < weight
      @current = @elements[index]
      break
    else
      target -= weight
    end
  end
end