class Ranran::Bucket

Attributes

weight[R]

Public Class Methods

new() click to toggle source
# File lib/ranran/bucket.rb, line 5
def initialize
  @items = {}
  @weight = 0
end

Public Instance Methods

==(o) click to toggle source
# File lib/ranran/bucket.rb, line 86
def == o
  o.class == self.class && o.items == self.items
end
Also aliased as: eql?
[](item) click to toggle source
# File lib/ranran/bucket.rb, line 22
def [] item
  @items[item]
end
[]=(item, weight) click to toggle source
# File lib/ranran/bucket.rb, line 26
def []= item, weight
  raise TypeError, "#{weight} is not numeric" unless weight.is_a? Numeric
  @weight -= @items[item] if @items.key? item
  @items[item] = weight
  @weight += weight
  [item, weight]
end
add(item, weight) click to toggle source
# File lib/ranran/bucket.rb, line 34
def add item, weight
  raise TypeError, "#{weight} is not numeric" unless weight.is_a? Numeric
  if @items.key? item
    @items[item] += weight
  else
    @items[item] = weight
  end
  @weight += weight
  self
end
choose(n = nil) click to toggle source
# File lib/ranran/bucket.rb, line 51
def choose n = nil
  if n
    n.times.map { weighted_random }
  else
    weighted_random
  end
end
delete(item) click to toggle source
# File lib/ranran/bucket.rb, line 45
def delete item
  weight = @items.delete item
  @weight -= weight
  [item, weight]
end
dup() click to toggle source
# File lib/ranran/bucket.rb, line 78
def dup
  new_bucket = self.class.new
  @items.each_pair do |item, weight|
    new_bucket.add item, weight
  end
  new_bucket
end
empty?() click to toggle source
# File lib/ranran/bucket.rb, line 10
def empty?
  @items.empty?
end
eql?(o)
Alias for: ==
hash() click to toggle source
# File lib/ranran/bucket.rb, line 92
def hash
  @items.hash
end
items() click to toggle source
# File lib/ranran/bucket.rb, line 18
def items
  @items.to_a
end
length() click to toggle source
# File lib/ranran/bucket.rb, line 14
def length
  @items.length
end
take(n = nil) click to toggle source
# File lib/ranran/bucket.rb, line 59
def take n = nil
  if n
    dup.take! n
  else
    weighted_random
  end
end
take!(n = nil) click to toggle source
# File lib/ranran/bucket.rb, line 67
def take! n = nil
  if n
    n.times.map { take! }
  else
    return nil if empty?
    taken = weighted_random
    delete taken
    taken
  end
end
zipf(s) click to toggle source
# File lib/ranran/zipf.rb, line 3
def zipf s
  dup.zipf! s
end
zipf!(s) click to toggle source
# File lib/ranran/zipf.rb, line 7
def zipf! s
  sum = 1.upto(length).inject(0) do |acc, n|
    acc + 1.0 / n ** s
  end
  @items.to_a.each_with_index do |(item, weight), i|
    @items[item] = (1.0 / (i + 1) ** s) / sum
  end
  @weight = 1.0
  self
end

Private Instance Methods

weighted_random() click to toggle source
# File lib/ranran/bucket.rb, line 97
def weighted_random
  return nil if empty?
  goal = rand * @weight
  # current = 0
  # @items.each_pair do |item, weight|
  #   current += weight
  #   return item if goal < current
  # end
  @items.inject(0) do |acc, (item, weight)|
    return item if goal < acc + weight
    acc + weight
  end
end