Advertisement
phi2dao

bucket.rb

Apr 18th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 1.91 KB | None | 0 0
  1. module Ranran
  2.   class Bucket
  3.     attr_reader :weight
  4.  
  5.     def initialize
  6.       @items = {}
  7.       @weight = 0
  8.     end
  9.  
  10.     def empty?
  11.       @items.empty?
  12.     end
  13.  
  14.     def length
  15.       @items.length
  16.     end
  17.  
  18.     def items
  19.       @items.to_a
  20.     end
  21.  
  22.     def [] item
  23.       @items[item]
  24.     end
  25.  
  26.     def []= item, weight
  27.       raise TypeError, "#{weight} is not numeric" unless weight.is_a? Numeric
  28.       @weight -= @items[item] if @items.key? item
  29.       @items[item] = weight
  30.       @weight += weight
  31.       [item, weight]
  32.     end
  33.  
  34.     def add item, weight
  35.       raise TypeError, "#{weight} is not numeric" unless weight.is_a? Numeric
  36.       if @items.key? item
  37.         @items[item] += weight
  38.       else
  39.         @items[item] = weight
  40.       end
  41.       @weight += weight
  42.       self
  43.     end
  44.  
  45.     def delete item
  46.       weight = @items.delete item
  47.       @weight -= weight
  48.       [item, weight]
  49.     end
  50.  
  51.     def choose n = nil
  52.       if n
  53.         n.times.map { weighted_random }
  54.       else
  55.         weighted_random
  56.       end
  57.     end
  58.  
  59.     def take n = nil
  60.       if n
  61.         dup.take! n
  62.       else
  63.         weighted_random
  64.       end
  65.     end
  66.  
  67.     def take! n = nil
  68.       if n
  69.         n.times.map { take! }
  70.       else
  71.         return nil if empty?
  72.         taken = weighted_random
  73.         delete taken
  74.         taken
  75.       end
  76.     end
  77.  
  78.     def dup
  79.       new_bucket = self.class.new
  80.       @items.each_pair do |item, weight|
  81.         new_bucket.add item, weight
  82.       end
  83.       new_bucket
  84.     end
  85.  
  86.     def == o
  87.       o.class == self.class && o.items == self.items
  88.     end
  89.  
  90.     alias :eql? :==
  91.  
  92.     def hash
  93.       @items.hash
  94.     end
  95.  
  96.     private
  97.     def weighted_random
  98.       return nil if empty?
  99.       goal = rand * @weight
  100.       current = 0
  101.       @items.each_pair do |item, weight|
  102.         current += weight
  103.         return item if goal < current
  104.       end
  105.     end
  106.   end
  107. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement