2009/6/25 David Newton <info / freesportsarbitrage.com>:
> Robert Klemme wrote:
>> 2009/6/23 David Newton <info / freesportsarbitrage.com>:

> I think I would find some comments on the code very helpful.

Ok, here we go.  The basic idea is to have a single definition of the
weight handling and separate the algorithm from that.  That way we can
use the algorithm for whatever weighting schemes we want to apply.  I
have "repackaged" the code into a method of module Enumerable which
seems appropriate considering the genericity of the approach.

Basically we have two inputs for the algorithm:
- enum of data
- weighting scheme

module Enumerable

  def weighting(weights)
    if block_given?
      # input: weights
      weights = weights.to_a

      # derive the divisor once from the weights because
      # it depends on the weights and does not change
      # otherwise
      div = weights.inject(0){|s,x| s + x}.to_f

      # Now iterate through self using a sliding window
      # of weights.size elements (this is done by each_cons)
      # for each window we calculate the weighted average
      # and yield it to the block passed to this method
      # Array#zip is used to iterate the weights and the
      # sliding window in lock step.
      each_cons weights.size do |elements|
       sum = 0
       elements.zip(weights) {|n,w| sum += n * w}
       yield sum / div
      end

      self
    else
      # create an Enumerator to allow for chaining.
      enum_for(:weighting, weights)
    end
  end

end

# input to the calculation, weighting scheme:
weights = 1..5

# second input, our data
data = [
 25.0000,
 24.8750,
 24.7813,
 24.5938,
 24.5000,
 24.6250,
 25.2188,
 27.2500,
 26.2500,
 26.5938,
]

data.weighting(weights).each_with_index do |avg, i|
  printf "period %2d: %8.3f\n", i, avg
end

Kind regards

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/