Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Brian Donovan http://brian.maybeyoureinsane.net/

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

Weighted random methods for Array

   1  
   2  class Array
   3    # Chooses a random array element from the receiver based on the weights
   4    # provided. If _weights_ is nil, then each element is weighed equally.
   5    # 
   6    #   [1,2,3].random          #=> 2
   7    #   [1,2,3].random          #=> 1
   8    #   [1,2,3].random          #=> 3
   9    #
  10    # If _weights_ is an array, then each element of the receiver gets its
  11    # weight from the corresponding element of _weights_. Notice that it
  12    # favors the element with the highest weight.
  13    #
  14    #   [1,2,3].random([1,4,1]) #=> 2
  15    #   [1,2,3].random([1,4,1]) #=> 1
  16    #   [1,2,3].random([1,4,1]) #=> 2
  17    #   [1,2,3].random([1,4,1]) #=> 2
  18    #   [1,2,3].random([1,4,1]) #=> 3
  19    #
  20    # If _weights_ is a symbol, the weight array is constructed by calling
  21    # the appropriate method on each array element in turn. Notice that
  22    # it favors the longer word when using :length.
  23    #
  24    #   ['dog', 'cat', 'hippopotamus'].random(:length) #=> "hippopotamus"
  25    #   ['dog', 'cat', 'hippopotamus'].random(:length) #=> "dog"
  26    #   ['dog', 'cat', 'hippopotamus'].random(:length) #=> "hippopotamus"
  27    #   ['dog', 'cat', 'hippopotamus'].random(:length) #=> "hippopotamus"
  28    #   ['dog', 'cat', 'hippopotamus'].random(:length) #=> "cat"
  29    def random(weights=nil)
  30      return random(map {|n| n.send(weights)}) if weights.is_a? Symbol
  31      
  32      weights ||= Array.new(length, 1.0)
  33      total = weights.inject(0.0) {|t,w| t+w}
  34      point = rand * total
  35      
  36      zip(weights).each do |n,w|
  37        return n if w >= point
  38        point -= w
  39      end
  40    end
  41    
  42    # Generates a permutation of the receiver based on _weights_ as in
  43    # Array#random. Notice that it favors the element with the highest
  44    # weight.
  45    #
  46    #   [1,2,3].randomize           #=> [2,1,3]
  47    #   [1,2,3].randomize           #=> [1,3,2]
  48    #   [1,2,3].randomize([1,4,1])  #=> [2,1,3]
  49    #   [1,2,3].randomize([1,4,1])  #=> [2,3,1]
  50    #   [1,2,3].randomize([1,4,1])  #=> [1,2,3]
  51    #   [1,2,3].randomize([1,4,1])  #=> [2,3,1]
  52    #   [1,2,3].randomize([1,4,1])  #=> [3,2,1]
  53    #   [1,2,3].randomize([1,4,1])  #=> [2,1,3]
  54    def randomize(weights=nil)
  55      return randomize(map {|n| n.send(weights)}) if weights.is_a? Symbol
  56      
  57      weights = weights.nil? ? Array.new(length, 1.0) : weights.dup
  58      
  59      # pick out elements until there are none left
  60      list, result = self.dup, []
  61      until list.empty?
  62        # pick an element
  63        result << list.random(weights)
  64        # remove the element from the temporary list and its weight
  65        weights.delete_at(list.index(result.last))
  66        list.delete result.last
  67      end
  68      
  69      result
  70    end
  71  end


Intended for use in selecting random elements from an array based on weight. Not optimized!
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS