Add all the A tasks

This commit is contained in:
Ingy döt Net 2013-04-10 14:58:50 -07:00
parent 2dd7375f96
commit 051504d65b
1608 changed files with 18584 additions and 0 deletions

View file

@ -0,0 +1,33 @@
Computing the [[wp:Moving_average#Simple_moving_average|simple moving average]] of a series of numbers.
The task is to:
:''Create a [[wp:Stateful|stateful]] function/class/instance that takes a period and returns a routine that takes a number as argument and returns a simple moving average of its arguments so far.''
'''Description'''<br>
A simple moving average is a method for computing an average of a stream of numbers by only averaging the last P numbers from the stream, where P is known as the period. It can be implemented by calling an initialing routine with P as its argument, I(P), which should then return a routine that when called with individual, successive members of a stream of numbers, computes the mean of (up to), the last P of them, lets call this SMA().
The word stateful in the task description refers to the need for SMA() to remember certain information between calls to it:
* The period, P
* An ordered container of at least the last P numbers from each of its individual calls.
Stateful also means that successive calls to I(), the initializer, should return separate routines that do ''not'' share saved state so they could be used on two independent streams of data.
Pseudocode for an implementation of SMA is:
<pre>
function SMA(number: N):
stateful integer: P
stateful list: stream
number: average
stream.append_last(N)
if stream.length() > P:
# Only average the last P elements of the stream
stream.delete_first()
if stream.length() == 0:
average = 0
else:
average = sum( stream.values() ) / stream.length()
return average
</pre>
See also: [[Standard Deviation]]

View file

@ -0,0 +1,2 @@
---
note: Probability and statistics

View file

@ -0,0 +1,88 @@
MODE SMAOBJ = STRUCT(
LONG REAL sma,
LONG REAL sum,
INT period,
REF[]LONG REAL values,
INT lv
);
MODE SMARESULT = UNION (
REF SMAOBJ # handle #,
LONG REAL # sma #,
REF[]LONG REAL # values #
);
MODE SMANEW = INT,
SMAFREE = STRUCT(REF SMAOBJ free obj),
SMAVALUES = STRUCT(REF SMAOBJ values obj),
SMAADD = STRUCT(REF SMAOBJ add obj, LONG REAL v),
SMAMEAN = STRUCT(REF SMAOBJ mean obj, REF[]LONG REAL v);
MODE ACTION = UNION ( SMANEW, SMAFREE, SMAVALUES, SMAADD, SMAMEAN );
PROC sma = ([]ACTION action)SMARESULT:
(
SMARESULT result;
REF SMAOBJ obj;
LONG REAL v;
FOR i FROM LWB action TO UPB action DO
CASE action[i] IN
(SMANEW period):( # args: INT period #
HEAP SMAOBJ handle;
sma OF handle := 0.0;
period OF handle := period;
values OF handle := HEAP [period OF handle]LONG REAL;
lv OF handle := 0;
sum OF handle := 0.0;
result := handle
),
(SMAFREE args):( # args: REF SMAOBJ free obj #
free obj OF args := REF SMAOBJ(NIL) # let the garbage collector do it's job #
),
(SMAVALUES args):( # args: REF SMAOBJ values obj #
result := values OF values obj OF args
),
(SMAMEAN args):( # args: REF SMAOBJ mean obj #
result := sma OF mean obj OF args
),
(SMAADD args):( # args: REF SMAOBJ add obj, LONG REAL v #
obj := add obj OF args;
v := v OF args;
IF lv OF obj < period OF obj THEN
(values OF obj)[lv OF obj+:=1] := v;
sum OF obj +:= v;
sma OF obj := sum OF obj / lv OF obj
ELSE
sum OF obj -:= (values OF obj)[ 1+ lv OF obj MOD period OF obj];
sum OF obj +:= v;
sma OF obj := sum OF obj / period OF obj;
(values OF obj)[ 1+ lv OF obj MOD period OF obj ] := v; lv OF obj+:=1
FI;
result := sma OF obj
)
OUT
SKIP
ESAC
OD;
result
);
[]LONG REAL v = ( 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 );
main: (
INT i;
REF SMAOBJ h3 := ( sma(SMANEW(3)) | (REF SMAOBJ obj):obj );
REF SMAOBJ h5 := ( sma(SMANEW(5)) | (REF SMAOBJ obj):obj );
FOR i FROM LWB v TO UPB v DO
printf(($"next number "g(0,6)", SMA_3 = "g(0,6)", SMA_5 = "g(0,6)l$,
v[i], (sma(SMAADD(h3, v[i]))|(LONG REAL r):r), ( sma(SMAADD(h5, v[i])) | (LONG REAL r):r )
))
OD#;
sma(SMAFREE(h3));
sma(SMAFREE(h5))
#
)

View file

@ -0,0 +1,13 @@
#!/usr/bin/awk -f
# Moving average over the first column of a data file
BEGIN {
P = 5;
}
{
x = $1;
i = NR % P;
MA += (x - Z[i]) / P;
Z[i] = x;
print MA;
}

View file

@ -0,0 +1,8 @@
generic
Max_Elements : Positive;
type Number is digits <>;
package Moving is
procedure Add_Number (N : Number);
function Moving_Average (N : Number) return Number;
function Get_Average return Number;
end Moving;

View file

@ -0,0 +1,40 @@
with Ada.Containers.Vectors;
package body Moving is
use Ada.Containers;
package Number_Vectors is new Ada.Containers.Vectors
(Element_Type => Number,
Index_Type => Natural);
Current_List : Number_Vectors.Vector := Number_Vectors.Empty_Vector;
procedure Add_Number (N : Number) is
begin
if Natural (Current_List.Length) >= Max_Elements then
Current_List.Delete_First;
end if;
Current_List.Append (N);
end Add_Number;
function Get_Average return Number is
Average : Number := 0.0;
procedure Sum (Position : Number_Vectors.Cursor) is
begin
Average := Average + Number_Vectors.Element (Position);
end Sum;
begin
Current_List.Iterate (Sum'Access);
if Current_List.Length > 1 then
Average := Average / Number (Current_List.Length);
end if;
return Average;
end Get_Average;
function Moving_Average (N : Number) return Number is
begin
Add_Number (N);
return Get_Average;
end Moving_Average;
end Moving;

View file

@ -0,0 +1,19 @@
with Ada.Text_IO;
with Moving;
procedure Main is
package Three_Average is new Moving (Max_Elements => 3, Number => Float);
package Five_Average is new Moving (Max_Elements => 5, Number => Float);
begin
for I in 1 .. 5 loop
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
" into max-3: " & Float'Image (Three_Average.Moving_Average (Float (I))));
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
" into max-5: " & Float'Image (Five_Average.Moving_Average (Float (I))));
end loop;
for I in reverse 1 .. 5 loop
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
" into max-3: " & Float'Image (Three_Average.Moving_Average (Float (I))));
Ada.Text_IO.Put_Line ("Inserting" & Integer'Image (I) &
" into max-5: " & Float'Image (Five_Average.Moving_Average (Float (I))));
end loop;
end Main;

View file

@ -0,0 +1,18 @@
MsgBox % MovingAverage(5,3) ; 5, averaging length <- 3
MsgBox % MovingAverage(1) ; 3
MsgBox % MovingAverage(-3) ; 1
MsgBox % MovingAverage(8) ; 2
MsgBox % MovingAverage(7) ; 4
MovingAverage(x,len="") { ; for integers (faster)
Static
Static sum:=0, n:=0, m:=10 ; default averaging length = 10
If (len>"") ; non-blank 2nd parameter: set length, reset
sum := n := i := 0, m := len
If (n < m) ; until the buffer is not full
sum += x, n++ ; keep summing data
Else ; when buffer is full
sum += x-v%i% ; add new, subtract oldest
v%i% := x, i := mod(i+1,m) ; remember last m inputs, cycle insertion point
Return sum/n
}

View file

@ -0,0 +1,11 @@
MovingAverage(x,len="") { ; for floating point numbers
Static
Static n:=0, m:=10 ; default averaging length = 10
If (len>"") ; non-blank 2nd parameter: set length, reset
n := i := 0, m := len
n += n < m, sum := 0
v%i% := x, i := mod(i+1,m) ; remember last m inputs, cycle insertion point
Loop %n% ; recompute sum to avoid error accumulation
j := A_Index-1, sum += v%j%
Return sum/n
}

View file

@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef struct sma_obj {
double sma;
double sum;
int period;
double *values;
int lv;
} sma_obj_t;
typedef union sma_result {
sma_obj_t *handle;
double sma;
double *values;
} sma_result_t;
enum Action { SMA_NEW, SMA_FREE, SMA_VALUES, SMA_ADD, SMA_MEAN };
sma_result_t sma(enum Action action, ...)
{
va_list vl;
sma_result_t r;
sma_obj_t *o;
double v;
va_start(vl, action);
switch(action) {
case SMA_NEW: // args: int period
r.handle = malloc(sizeof(sma_obj_t));
r.handle->sma = 0.0;
r.handle->period = va_arg(vl, int);
r.handle->values = malloc(r.handle->period * sizeof(double));
r.handle->lv = 0;
r.handle->sum = 0.0;
break;
case SMA_FREE: // args: sma_obj_t *handle
r.handle = va_arg(vl, sma_obj_t *);
free(r.handle->values);
free(r.handle);
r.handle = NULL;
break;
case SMA_VALUES: // args: sma_obj_t *handle
o = va_arg(vl, sma_obj_t *);
r.values = o->values;
break;
case SMA_MEAN: // args: sma_obj_t *handle
o = va_arg(vl, sma_obj_t *);
r.sma = o->sma;
break;
case SMA_ADD: // args: sma_obj_t *handle, double value
o = va_arg(vl, sma_obj_t *);
v = va_arg(vl, double);
if ( o->lv < o->period ) {
o->values[o->lv++] = v;
o->sum += v;
o->sma = o->sum / o->lv;
} else {
o->sum -= o->values[ o->lv % o->period];
o->sum += v;
o->sma = o->sum / o->period;
o->values[ o->lv % o->period ] = v; o->lv++;
}
r.sma = o->sma;
break;
}
va_end(vl);
return r;
}

View file

@ -0,0 +1,18 @@
double v[] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
int main()
{
int i;
sma_obj_t *h3 = sma(SMA_NEW, 3).handle;
sma_obj_t *h5 = sma(SMA_NEW, 5).handle;
for(i=0; i < sizeof(v)/sizeof(double) ; i++) {
printf("next number %lf, SMA_3 = %lf, SMA_5 = %lf\n",
v[i], sma(SMA_ADD, h3, v[i]).sma, sma(SMA_ADD, h5, v[i]).sma);
}
sma(SMA_FREE, h3);
sma(SMA_FREE, h5);
return 0;
}

View file

@ -0,0 +1,12 @@
(import '[clojure.lang PersistentQueue])
(defn enqueue-max [q p n]
(let [q (conj q n)]
(if (<= (count q) p) q (pop q))))
(defn avg [coll] (/ (reduce + coll) (count coll)))
(defn init-moving-avg [p]
(let [state (atom PersistentQueue/EMPTY)]
(fn [n]
(avg (swap! state enqueue-max p n)))))

View file

@ -0,0 +1,44 @@
I = (P) ->
# The cryptic name "I" follows the problem description;
# it returns a function that computes a moving average
# of successive values over the period P, using closure
# variables to maintain state.
cq = circular_queue(P)
num_elems = 0
sum = 0
SMA = (n) ->
sum += n
if num_elems < P
cq.add(n)
num_elems += 1
sum / num_elems
else
old = cq.replace(n)
sum -= old
sum / P
circular_queue = (n) ->
# queue that only ever stores up to n values;
# Caller shouldn't call replace until n values
# have been added.
i = 0
arr = []
add: (elem) ->
arr.push elem
replace: (elem) ->
# return value whose age is "n"
old_val = arr[i]
arr[i] = elem
i = (i + 1) % n
old_val
# The output of the code below should convince you that
# calling I multiple times returns functions with independent
# state.
sma3 = I(3)
sma7 = I(7)
sma11 = I(11)
for i in [1..10]
console.log i, sma3(i), sma7(i), sma11(i)

View file

@ -0,0 +1,11 @@
> coffee moving_average.coffee
1 1 1 1
2 1.5 1.5 1.5
3 2 2 2
4 3 2.5 2.5
5 4 3 3
6 5 3.5 3.5
7 6 4 4
8 7 5 4.5
9 8 6 5
10 9 7 5.5

View file

@ -0,0 +1,41 @@
main() ->
SMA3 = sma(3),
SMA5 = sma(5),
Ns = [1, 2, 3, 4, 5, 5, 4, 3, 2, 1],
lists:foreach(
fun (N) ->
io:format("Added ~b, sma(3) -> ~f, sma(5) -> ~f~n",[N,next(SMA3,N),next(SMA5,N)])
end, Ns),
stop(SMA3),
stop(SMA5).
sma(W) ->
{sma,spawn(?MODULE,loop,[W,[]])}.
loop(Window, Numbers) ->
receive
{_Pid, stop} ->
ok;
{Pid, N} when is_number(N) ->
case length(Numbers) < Window of
true ->
Next = Numbers++[N];
false ->
Next = tl(Numbers)++[N]
end,
Pid ! {average, lists:sum(Next)/length(Next)},
loop(Window,Next);
_ ->
ok
end.
stop({sma,Pid}) ->
Pid ! {self(),stop},
ok.
next({sma,Pid},N) ->
Pid ! {self(), N},
receive
{average, Ave} ->
Ave
end.

View file

@ -0,0 +1,12 @@
9> sma:main().
Added 1, sma(3) -> 1.000000, sma(5) -> 1.000000
Added 2, sma(3) -> 1.500000, sma(5) -> 1.500000
Added 3, sma(3) -> 2.000000, sma(5) -> 2.000000
Added 4, sma(3) -> 3.000000, sma(5) -> 2.500000
Added 5, sma(3) -> 4.000000, sma(5) -> 3.000000
Added 5, sma(3) -> 4.666667, sma(5) -> 3.800000
Added 4, sma(3) -> 4.666667, sma(5) -> 4.200000
Added 3, sma(3) -> 4.000000, sma(5) -> 4.200000
Added 2, sma(3) -> 3.000000, sma(5) -> 3.800000
Added 1, sma(3) -> 2.000000, sma(5) -> 3.000000
ok

View file

@ -0,0 +1,27 @@
: f+! ( f addr -- ) dup f@ f+ f! ;
: ,f0s ( n -- ) falign 0 do 0e f, loop ;
: period @ ;
: used cell+ ;
: head 2 cells + ;
: sum 3 cells + faligned ;
: ring ( addr -- faddr )
dup sum float+ swap head @ floats + ;
: update ( fvalue addr -- addr )
dup ring f@ fnegate dup sum f+!
fdup dup ring f! dup sum f+!
dup head @ 1+ over period mod over head ! ;
: moving-average
create ( period -- ) dup , 0 , 0 , 1+ ,f0s
does> ( fvalue -- avg )
update
dup used @ over period < if 1 over used +! then
dup sum f@ used @ 0 d>f f/ ;
3 moving-average sma
1e sma f. \ 1.
2e sma f. \ 1.5
3e sma f. \ 2.
4e sma f. \ 3.

View file

@ -0,0 +1,33 @@
program Movavg
implicit none
integer :: i
write (*, "(a)") "SIMPLE MOVING AVERAGE: PERIOD = 3"
do i = 1, 5
write (*, "(a, i2, a, f8.6)") "Next number:", i, " sma = ", sma(real(i))
end do
do i = 5, 1, -1
write (*, "(a, i2, a, f8.6)") "Next number:", i, " sma = ", sma(real(i))
end do
contains
function sma(n)
real :: sma
real, intent(in) :: n
real, save :: a(3) = 0
integer, save :: count = 0
if (count < 3) then
count = count + 1
a(count) = n
else
a = eoshift(a, 1, n)
end if
sma = sum(a(1:count)) / real(count)
end function
end program Movavg

View file

@ -0,0 +1,34 @@
package main
import "fmt"
func sma(n int) func(float64) float64 {
s := make([]float64, 0, n)
i, sum, rn := 0, 0., 1/float64(n)
return func(x float64) float64 {
if len(s) < n {
sum += x
s = append(s, x)
return sum / float64(len(s))
}
s[i] = x
i++
if i == n {
i = 0
}
sum = 0
for _, x = range s {
sum += x
}
return sum * rn
}
}
func main() {
sma3 := sma(3)
sma5 := sma(5)
fmt.Println("x sma3 sma5")
for _, x := range []float64{1, 2, 3, 4, 5, 5, 4, 3, 2, 1} {
fmt.Printf("%5.3f %5.3f %5.3f\n", x, sma3(x), sma5(x))
}
}

View file

@ -0,0 +1,10 @@
import Data.List
import Control.Arrow
import Control.Monad
sMA p = map (head *** head ).tail.
scanl (\(y,_) -> (id &&& return. av) . (: if length y == p then init y else y)) ([],[])
where av = liftM2 (/) sum (fromIntegral.length)
printSMA n p = mapM_ (\(n,a) -> putStrLn $ "Next number: " ++ show n ++ " Average: " ++ show a)
. take n . sMA p $ [1..5]++[5,4..1]++[3..]

View file

@ -0,0 +1,38 @@
import java.util.LinkedList;
import java.util.Queue;
public class MovingAverage {
private final Queue<Double> window = new LinkedList<Double>();
private final int period;
private double sum;
public MovingAverage(int period) {
assert period > 0 : "Period must be a positive integer";
this.period = period;
}
public void newNum(double num) {
sum += num;
window.add(num);
if (window.size() > period) {
sum -= window.remove();
}
}
public double getAvg() {
if (window.isEmpty()) return 0; // technically the average is undefined
return sum / window.size();
}
public static void main(String[] args) {
double[] testData = {1,2,3,4,5,5,4,3,2,1};
int[] windowSizes = {3,5};
for (int windSize : windowSizes) {
MovingAverage ma = new MovingAverage(windSize);
for (double x : testData) {
ma.newNum(x);
System.out.println("Next number = " + x + ", SMA = " + ma.getAvg());
}
System.out.println();
}
}
}

View file

@ -0,0 +1,24 @@
function simple_moving_averager(period) {
var nums = [];
return function(num) {
nums.push(num);
if (nums.length > period)
nums.splice(0,1); // remove the first element of the array
var sum = 0;
for (var i in nums)
sum += nums[i];
var n = period;
if (nums.length < period)
n = nums.length;
return(sum/n);
}
}
var sma3 = simple_moving_averager(3);
var sma5 = simple_moving_averager(5);
var data = [1,2,3,4,5,5,4,3,2,1];
for (var i in data) {
var n = data[i];
// using WSH
WScript.Echo("Next number = " + n + ", SMA_3 = " + sma3(n) + ", SMA_5 = " + sma5(n));
}

View file

@ -0,0 +1,10 @@
do
local t = {}
function f(a, b, ...) if b then return f(a+b, ...) else return a end end
function average(n)
if #t == 10 then table.remove(t, 1) end
t[#t + 1] = n
return f(unpack(t)) / #t
end
end
for v=1,30 do print(average(v)) end

View file

@ -0,0 +1,7 @@
sub sma ($)
{my ($period, $sum, @a) = shift, 0;
return sub
{unshift @a, shift;
$sum += $a[0];
@a > $period and $sum -= pop @a;
return $sum / @a;}}

View file

@ -0,0 +1,5 @@
(de sma (@Len)
(curry (@Len (Data)) (N)
(push 'Data N)
(and (nth Data @Len) (con @)) # Truncate
(*/ (apply + Data) (length Data)) ) )

View file

@ -0,0 +1,11 @@
(def 'sma3 (sma 3))
(def 'sma5 (sma 5))
(scl 2)
(for N (1.0 2.0 3.0 4.0 5.0 5.0 4.0 3.0 2.0 1.0)
(prinl
(format N *Scl)
" (sma3) "
(format (sma3 N) *Scl)
" (sma5) "
(format (sma5 N) *Scl) ) )

View file

@ -0,0 +1,17 @@
from collections import deque
def simplemovingaverage(period):
assert period == int(period) and period > 0, "Period must be an integer >0"
summ = n = 0.0
values = deque([0.0] * period) # old value queue
def sma(x):
nonlocal summ, n
values.append(x)
summ += x - values.popleft()
n = min(n+1, period)
return summ / n
return sma

View file

@ -0,0 +1,21 @@
from collections import deque
class Simplemovingaverage():
def __init__(self, period):
assert period == int(period) and period > 0, "Period must be an integer >0"
self.period = period
self.stream = deque()
def __call__(self, n):
stream = self.stream
stream.append(n) # appends on the right
streamlength = len(stream)
if streamlength > self.period:
stream.popleft()
streamlength -= 1
if streamlength == 0:
average = 0
else:
average = sum( stream ) / streamlength
return average

View file

@ -0,0 +1,15 @@
if __name__ == '__main__':
for period in [3, 5]:
print ("\nSIMPLE MOVING AVERAGE (procedural): PERIOD =", period)
sma = simplemovingaverage(period)
for i in range(1,6):
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
for i in range(5, 0, -1):
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
for period in [3, 5]:
print ("\nSIMPLE MOVING AVERAGE (class based): PERIOD =", period)
sma = Simplemovingaverage(period)
for i in range(1,6):
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))
for i in range(5, 0, -1):
print (" Next number = %-2g, SMA = %g " % (i, sma(i)))

View file

@ -0,0 +1,31 @@
#concat concatenates the new values to the existing vector of values, then discards any values that are too old.
lastvalues <- local(
{
values <- c();
function(x, len)
{
values <<- c(values, x);
lenv <- length(values);
if(lenv > len) values <<- values[(len-lenv):-1]
values
}
})
#moving.average accepts a numeric scalars input (and optionally a length, i.e. the number of values to retain) and calculates the stateful moving average.
moving.average <- function(latestvalue, len=3)
{
#Check that all inputs are numeric scalars
is.numeric.scalar <- function(x) is.numeric(x) && length(x)==1L
if(!is.numeric.scalar(latestvalue) || !is.numeric.scalar(len))
{
stop("all arguments must be numeric scalars")
}
#Calculate mean of variables so far
mean(lastvalues(latestvalue, len))
}
moving.average(5) # 5
moving.average(1) # 3
moving.average(-3) # 1
moving.average(8) # 2
moving.average(7) # 4

View file

@ -0,0 +1,35 @@
/*REXX program is illustrate simple moving average. */
arg p q n . /*get some arguments (maybe). */
if p=='' then p=3 /*the 1st period (default: 3).*/
if q=='' then q=5 /* " 2nd " " 5 */
if n=='' then n=10 /*number of items in the list.*/
a.=0
do j=1 for n%2 /*build beginning of the list,*/
a.j=j /* ... increasing values. */
end /*j*/
do k=n%2 to 1 by -1 /* ... decreasing values. */
a.j=k
j=j+1
end /*k*/
do i=1 for n /*show an indented item list. */
say left('',60) 'item' right(i,3)'='right(a.i,3)
end /*i*/
do m=1 for n /*OK the, let's start the SMA.*/
smaP=sma(p,m) /*simple moving average for P.*/
smaQ=sma(q,m) /* " " " " Q.*/
/*show 2 nicely formated SMAs.*/
say 'm='right(m,3), /*show where we're at in list.*/
" sma("p')='left(sma(p,m),11), /*show nicely aligned sma P. */
" sma("q')='left(sma(q,m),11) /* " " " " Q. */
end /*m*/
exit
/*────────────────────────────────────────SMA subroutine────────────────*/
sma: procedure expose A.; arg p,j; s=0; i=0
do k=max(1,j-p+1) to j+p for p while k<=j
i=i+1
s=s+a.k
end
return s/i

View file

@ -0,0 +1,18 @@
def simple_moving_average(size)
nums = []
sum = 0.0
lambda do |hello|
nums << hello
goodbye = nums.length > size ? nums.shift : 0
sum += hello - goodbye
sum / nums.length
end
end
ma3 = simple_moving_average(3)
ma5 = simple_moving_average(5)
(1.upto(5).to_a + 5.downto(1).to_a).each do |num|
printf "Next number = %d, SMA_3 = %.3f, SMA_5 = %.1f\n",
num, ma3.call(num), ma5.call(num)
end

View file

@ -0,0 +1,28 @@
class MovingAverager
def initialize(size)
@size = size
@nums = []
@sum = 0.0
end
def <<(hello)
@nums << hello
goodbye = @nums.length > @size ? @nums.shift : 0
@sum += hello - goodbye
self
end
def average
@sum / @nums.length
end
alias to_f average
def to_s
average.to_s
end
end
ma3 = MovingAverager.new(3)
ma5 = MovingAverager.new(5)
(1.upto(5).to_a + 5.downto(1).to_a).each do |num|
printf "Next number = %d, SMA_3 = %.3f, SMA_5 = %.1f\n",
num, ma3 << num, ma5 <<num
end

View file

@ -0,0 +1,11 @@
class MovingAverage(period: Int) {
private var queue = new scala.collection.mutable.Queue[Double]()
def apply(n: Double) = {
queue.enqueue(n)
if (queue.size > period)
queue.dequeue
queue.sum / queue.size
}
override def toString = queue.mkString("(", ", ", ")")+", period "+period+", average "+(queue.sum / queue.size)
def clear = queue.clear
}

View file

@ -0,0 +1,6 @@
(define ((simple-moving-averager size . nums) num)
(set! nums (cons num (if (= (length nums) size) (reverse (cdr (reverse nums))) nums)))
(/ (apply + nums) (length nums)))
(define av (simple-moving-averager 3))
(map av '(1 2 3 4 5 5 4 3 2 1))

View file

@ -0,0 +1,31 @@
Object subclass: MovingAverage [
|valueCollection period collectedNumber sum|
MovingAverage class >> newWithPeriod: thePeriod [
|r|
r := super basicNew.
^ r initWithPeriod: thePeriod
]
initWithPeriod: thePeriod [
valueCollection := OrderedCollection new: thePeriod.
period := thePeriod.
collectedNumber := 0.
sum := 0
]
sma [ collectedNumber < period
ifTrue: [ ^ sum / collectedNumber ]
ifFalse: [ ^ sum / period ] ]
add: value [
collectedNumber < period
ifTrue: [
sum := sum + value.
valueCollection add: value.
collectedNumber := collectedNumber + 1.
]
ifFalse: [
sum := sum - (valueCollection removeFirst).
sum := sum + value.
valueCollection add: value
].
^ self sma
]
].

View file

@ -0,0 +1,10 @@
|sma3 sma5|
sma3 := MovingAverage newWithPeriod: 3.
sma5 := MovingAverage newWithPeriod: 5.
#( 1 2 3 4 5 5 4 3 2 1 ) do: [ :v |
('Next number %1, SMA_3 = %2, SMA_5 = %3' % {
v . (sma3 add: v) asFloat . (sma5 add: v) asFloat
}) displayNl
]

View file

@ -0,0 +1,11 @@
oo::class create SimpleMovingAverage {
variable vals idx
constructor {{period 3}} {
set idx end-[expr {$period-1}]
set vals {}
}
method val x {
set vals [lrange [list {*}$vals $x] $idx end]
expr {[tcl::mathop::+ {*}$vals]/double([llength $vals])}
}
}

View file

@ -0,0 +1,5 @@
SimpleMovingAverage create averager3
SimpleMovingAverage create averager5 5
foreach n {1 2 3 4 5 5 4 3 2 1} {
puts "Next number = $n, SMA_3 = [averager3 val $n], SMA_5 = [averager5 val $n]"
}