Skip to content

Instantly share code, notes, and snippets.

@joshpeterson
Created September 23, 2010 18:33
Show Gist options
  • Save joshpeterson/594106 to your computer and use it in GitHub Desktop.
Save joshpeterson/594106 to your computer and use it in GitHub Desktop.
Use a class hierarchy to create some simple statistics operations as an example in the first chapter of The D Programming Language does.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace StatisticsMethods
{
interface StatisticsMethod
{
void Accumulate(double value);
void PostProcess();
double GetResult();
}
public abstract class IncrementalStatisticsMethod : StatisticsMethod
{
protected double result = 0.0;
public virtual void Accumulate(double value) { }
public virtual void PostProcess() { }
public virtual double GetResult() { return this.result; }
}
public sealed class Min : IncrementalStatisticsMethod
{
public Min()
{
this.result = double.MaxValue;
}
public override void Accumulate(double value)
{
if (value < this.result)
{
this.result = value;
}
}
}
public sealed class Max : IncrementalStatisticsMethod
{
public Max()
{
this.result = double.MinValue;
}
public override void Accumulate(double value)
{
if (value > this.result)
{
this.result = value;
}
}
}
public sealed class Average : IncrementalStatisticsMethod
{
private int numberOfValues = 0;
public override void Accumulate(double value)
{
numberOfValues++;
this.result += value;
}
public override void PostProcess()
{
if (numberOfValues != 0)
{
this.result = this.result / numberOfValues;
}
}
}
class SimpleStatisticsMethods
{
static void Main(string[] args)
{
if (args[0] == "Test")
{
TestStatisticsMethods();
return;
}
Dictionary<string, StatisticsMethod> statsMethods = GetStatisticsMethods(args);
List<double> values = GetValuesFromStandardInput();
ProcessAllStatisticsMethods(values, statsMethods);
}
private static Dictionary<string, StatisticsMethod> GetStatisticsMethods(string[] args)
{
Dictionary<string, StatisticsMethod> statsMethods = new Dictionary<string, StatisticsMethod>();
for (int i = 0; i < args.Length; ++i)
{
StatisticsMethod method = (StatisticsMethod)Activator.CreateInstance(Assembly.GetExecutingAssembly().FullName, string.Format("StatisticsMethods.{0}", args[i])).Unwrap();
if (method != null)
{
statsMethods.Add(args[i], method);
}
else
{
Console.WriteLine("Unknown statistics method: {0}", args[i]);
}
}
return statsMethods;
}
private static List<double> GetValuesFromStandardInput()
{
List<double> values = new List<double>();
string line;
while ((line = Console.ReadLine()) != null)
{
foreach (string input in line.Split(' '))
{
string trimmedInput = input.Trim();
if (!string.IsNullOrEmpty(trimmedInput))
{
double value;
if (double.TryParse(trimmedInput, out value))
{
values.Add(value);
}
else
{
Console.WriteLine("It doesn't look like {0} is a number, I'm skipping it.", input);
}
}
}
}
return values;
}
private static void ProcessAllStatisticsMethods(IEnumerable<double> values, IDictionary<string, StatisticsMethod> statsMethods)
{
foreach (string statsMethodName in statsMethods.Keys)
{
Console.WriteLine("{0}: {1}", statsMethodName,ProcessStatisticsMethod(values, statsMethods[statsMethodName]));
}
}
private static double ProcessStatisticsMethod(IEnumerable<double> values, StatisticsMethod statsMethod)
{
foreach (double value in values)
{
statsMethod.Accumulate(value);
}
statsMethod.PostProcess();
return statsMethod.GetResult();
}
private static void TestStatisticsMethods()
{
double[] testValues = { 1.2, 2, 3.4, 4, 5.1, 6.8, 0.5, 1 };
Console.WriteLine("Statistics method {0} test {1}", "Min", ProcessStatisticsMethod(testValues, new Min()) == 0.5 ? "passed" : "failed");
Console.WriteLine("Statistics method {0} test {1}", "Max", ProcessStatisticsMethod(testValues, new Max()) == 6.8 ? "passed" : "failed");
Console.WriteLine("Statistics method {0} test {1}", "Average", ProcessStatisticsMethod(testValues, new Average()) == 3.0 ? "passed" : "failed");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment