using System.Diagnostics;
using System.Collections.Generic;
using System.Collections;
using System.Threading.Tasks;
public interface IAggregate
Dictionary<string, double>[] DoAggregations(double[,] input);
public class Solution: IAggregate
public const string SUM="SUM";
public const string AVERAGE = "AVERAGE";
public const string COUNT_DISTINCT = "COUNT DISTINCT";
public Dictionary<string, double>[] DoAggregations(double[,] input)
Dictionary<string, double>[] result = new Dictionary<string, double>[input.GetLength(1)];
Dictionary<string, double> temp;
for (int i = 0; i < input.GetLength(0); i++)
for (int j = 0; j < input.GetLength(1); j++)
if (temp == null) temp = new Dictionary<string, double>();
if (temp.ContainsKey(SUM))
temp[SUM] += input[i, j];
temp.Add(SUM, input[i, j]);
for (int i = 0; i < result.Length; i++)
if (temp.ContainsKey(SUM))
temp[AVERAGE] = temp[SUM] / input.GetLength(0);
for (int i = 0; i < input.GetLength(1); i++)
Hashtable count = new Hashtable();
for (int j = 0; j < input.GetLength(0); j++)
double currentValue = input[j, i];
if (!count.ContainsKey(currentValue))
count.Add(currentValue, 1);
temp[COUNT_DISTINCT] = count.Count;
public class Generic : IAggregate
public const string SUM = "SUM";
public const string AVERAGE = "AVERAGE";
public const string COUNT_DISTINCT = "COUNT DISTINCT";
public static Dictionary<string, double>[] DoAggregations(Func<double[,], Dictionary<string, double>[]> Func, double[,] input)
public Dictionary<string, double>[] DoAggregations(double[,] input)
return Generic.DoAggregations((x) => {
Dictionary<string, double>[] result = new Dictionary<string, double>[input.GetLength(1)];
Dictionary<string, double> temp;
for (int i = 0; i < input.GetLength(0); i++)
for (int j = 0; j < input.GetLength(1); j++)
if (temp == null) temp = new Dictionary<string, double>();
if (temp.ContainsKey(SUM))
temp[SUM] += input[i, j];
temp.Add(SUM, input[i, j]);
for (int i = 0; i < result.Length; i++)
if (temp.ContainsKey(SUM))
temp[AVERAGE] = temp[SUM] / input.GetLength(0);
for (int i = 0; i < input.GetLength(1); i++)
Hashtable count = new Hashtable();
for (int j = 0; j < input.GetLength(0); j++)
double currentValue = input[j,i];
if (!count.ContainsKey(currentValue))
count.Add(currentValue,1);
temp[COUNT_DISTINCT] = count.Count;
public class Mock : IAggregate
public Dictionary<string, double>[] DoAggregations(double[,] input)
return new Dictionary<string, double>[]{
new Dictionary<string, double>{{"SUM", 9d}, {"AVERAGE", 2.25d}, {"COUNT DISTINCT", 3d}},
new Dictionary<string, double>{{"SUM", 14d}, {"AVERAGE", 3.5d}, {"COUNT DISTINCT", 2d}},
new Dictionary<string, double>{{"SUM", 16d}, {"AVERAGE", 4d}, {"COUNT DISTINCT", 4d}}};
public static void Main()
double[,] smallInput = new double[,] { { 1, 4, 3 }, { 2, 3, 4 }, { 1, 3, 7 }, { 5, 4, 2 } };
IAggregate aggregate = new Mock();
Console.WriteLine("=== Small Input - Mocked Execution ===");
var mockResult = aggregate.DoAggregations(smallInput);
IsResultCorrect(mockResult);
aggregate = new Generic();
Console.WriteLine("\n=== Small Input - Solution Execution ===");
var result = aggregate.DoAggregations( smallInput);
Console.WriteLine("\n=== Large Input - Solution Execution ===");
var largeInput = GenerateLargeInput();
aggregate = new Solution();
var sw = Stopwatch.StartNew();
aggregate.DoAggregations(largeInput);
IsExecutionFastEnough(sw.ElapsedMilliseconds / 5);
public static double[,] GenerateLargeInput()
var input = new double[numRows, numCols];
Random rnd = new Random(123);
for (int col = 0; col < numCols; col++)
for (int row = 0; row < numRows; row++)
input[row, col] = rnd.Next(100000);
public static void IsResultCorrect(Dictionary<string, double>[] result)
result[0]["SUM"] == 9d &&
result[1]["SUM"] == 14d &&
result[2]["SUM"] == 16d &&
result[0]["AVERAGE"] == 2.25d &&
result[1]["AVERAGE"] == 3.5d &&
result[2]["AVERAGE"] == 4d &&
result[0]["COUNT DISTINCT"] == 3d &&
result[1]["COUNT DISTINCT"] == 2d &&
result[2]["COUNT DISTINCT"] == 4d
Console.WriteLine("IsResultCorrect Passed");
Console.WriteLine("IsResultCorrect Failed");
public static void IsExecutionFastEnough(double milliSeconds)
Console.WriteLine($"IsExecutionFastEnough DIAMOND!!!: {milliSeconds}ms");
else if (milliSeconds < 85)
Console.WriteLine($"IsExecutionFastEnough GOLD!: {milliSeconds}ms");
else if (milliSeconds < 130)
Console.WriteLine($"IsExecutionFastEnough SILVER: {milliSeconds}ms");
Console.WriteLine($"IsExecutionFastEnough BRONZE: {milliSeconds}ms");