Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this questionFor example I have this data:
headings = {
:heading1 => { :weight => 60, :show_count => 0}
:heading2 => { :weight => 10, :show_count => 0}
:heading3 => { :weight => 20, :show_count => 0}
:heading4 => { :weight => 10, :show_count => 0}
}
t开发者_如何学Pythonotal_views = 0
Now I want to serve each heading based on their weightages. For instance, for first 10 requests/iterations, heading1
, heading3
, heading2
and heading4
would be served 6, 2, 1, and 1 times respectively in order (by weight).
For every iteration show_count of served heading will increment by one and total_views will also increment globally.
Could you please suggest an algorithm or some ruby code to handle this.
You can use pickup gem
It accepts hash like this:
require 'pickup'
headings = {
heading1: 60,
heading2: 10,
heading3: 20,
heading4: 10
}
pickup = Pickup.new(headings)
pickup.pick
#=> heading1
pickup.pick
#=> heading1
pickup.pick
#=> heading3
pickup.pick
#=> heading1
pickup.pick
#=> heading4
So you can do something like this:
require 'pickup'
headings = {
heading1: { :weight => 60, :show_count => 0},
heading2: { :weight => 10, :show_count => 0},
heading3: { :weight => 20, :show_count => 0},
heading4: { :weight => 10, :show_count => 0}
}
pickup_headings = headings.inject({}){ |h, (k,v)| h[k] = v[:weight]; h}
pickup = Pickup.new(pickup_headings)
# let's fire it 1000 times
1000.times do
server = pickup.pick
headings[server][:show_count] += 1
end
puts headings
#=> {
#=> :heading1=>{:weight=>60, :show_count=>601},
#=> :heading2=>{:weight=>10, :show_count=>116},
#=> :heading3=>{:weight=>20, :show_count=>176},
#=> :heading4=>{:weight=>10, :show_count=>107}
#=> }
This should work for your basic case and can be modified according to the details of what you need:
class Heading
attr_reader :heading, :weight, :show_count
def initialize(heading,weight=1)
@heading=heading
@weight=weight
@show_count=0
end
def serve
puts "Served #{@heading}! "
@show_count += 1
end
end
class HeadingServer
attr_reader :headings
def initialize(headings_hash)
@headings=headings_hash.map {|h, data| Heading.new(h,data[:weight])}
@total_weight=@headings.inject(0) {|s,h| s+= h.weight}
end
def serve(num_to_serve=@total_weight)
@headings.sort {|a,b| b.weight <=> a.weight}.each do |h|
n = (h.weight * num_to_serve) / @total_weight #possibility of rounding errors
n.times { h.serve }
end
end
def total_views
@headings.inject(0) {|s,h| s += h.show_count}
end
end
headings = {
:heading1 => { :weight => 60, :show_count => 0},
:heading2 => { :weight => 10, :show_count => 0},
:heading3 => { :weight => 20, :show_count => 0},
:heading4 => { :weight => 10, :show_count => 0}
}
# Example Usage:
hs = HeadingServer.new(headings)
hs.serve(10)
hs.headings.each {|h| puts "#{h.heading} : served #{h.show_count} times"}
puts "Total Views: #{hs.total_views}"
精彩评论