using System;
using System.Linq;
using System.Collections.Generic;
public static class Utils {
    public static double GetStandardDeviation(this IEnumerable<int> values)
    {
        double standardDeviation = 0;
        int[] enumerable = values as int[] ?? values.ToArray();
        int count = enumerable.Count();
        if (count > 1)
        {
            double avg = enumerable.Average();
            double sum = enumerable.Sum(d => (d - avg) * (d - avg));
            standardDeviation = Math.Sqrt(sum / count);
        }
        return standardDeviation;
    }
    
    class Tuple3<X, Y, Z> {
      public Tuple3(X x, Y y, Z z) {
        this.Item1 = x;
        this.Item2 = y;
        this.Item3 = z;
      }
      public static Tuple3<X, Y, Z> Create(X x, Y y, Z z) {
        return new Tuple3<X, Y, Z>(x, y, z);
      }
      public X Item1;
      public Y Item2;
      public Z Item3;
    }
    
    public static Tuple<Double, Double, Double> FastStandardDeviation(this IEnumerable<int> values) {
        var res = values.Aggregate(Tuple3<Double, Double, Double>.Create(0d, 0d, 0d), (tup, a) => {
          var n = tup.Item1 + 1;
          var delta = a - tup.Item2;
          var mean = tup.Item2 + delta / n;
          var delta2 = a - mean;
          var m2 = tup.Item3 + delta * delta2;
          tup.Item1 = n;
          tup.Item2 = mean;
          tup.Item3 = m2;
          return tup;
        });
        return Tuple.Create(res.Item1, res.Item2, Math.Sqrt(res.Item3 / res.Item1));
    }
    
    public static Tuple<Double, Double, Double> FastStandardDeviationWithTupleCreate(this IEnumerable<int> values) {
        var res = values.Aggregate(Tuple.Create(0d, 0d, 0d), (tup, a) => {
          var n = tup.Item1 + 1;
          var delta = a - tup.Item2;
          var mean = tup.Item2 + delta / n;
          var delta2 = a - mean;
          var m2 = tup.Item3 + delta * delta2;
          return Tuple.Create(n, mean, m2);
        });
        return Tuple.Create(res.Item1, res.Item2, Math.Sqrt(res.Item3 / res.Item1));
    }
}
public static class UtilsT<T> {
    public static Tuple<long, T> Time(Func<T> act) {
      var watch = System.Diagnostics.Stopwatch.StartNew();
      var t = act();
      watch.Stop();
      return Tuple.Create(watch.ElapsedMilliseconds, t);
    }
}
class MainClass {
    static void Main() {
        var rand = new Random();
        var nums = Enumerable.Range(1, 10000000).Select(_ => rand.Next(1000));
        
        var slow = UtilsT<Double>.Time(nums.GetStandardDeviation);
        Console.WriteLine("Slow Method, Result = {0}, Time = {1}", slow.Item2, slow.Item1);
        
        var fast = UtilsT<Tuple<Double, Double, Double>>.Time(nums.FastStandardDeviation);
        Console.WriteLine("Fast Method, Result = {0}, Time = {1}", fast.Item2.Item3, fast.Item1);
    }
}