Skip to content

Instantly share code, notes, and snippets.

@ig-sinicyn
Last active July 16, 2016 08:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ig-sinicyn/7dfe2413f88ee19244dbabf213e8119b to your computer and use it in GitHub Desktop.
Save ig-sinicyn/7dfe2413f88ee19244dbabf213e8119b to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using CodeJam.Arithmetic;
using CodeJam.Collections;
using CodeJam.PerfTests;
using JetBrains.Annotations;
using NUnit.Framework;
using static CodeJam.AssemblyWideConfig;
using static CodeJam.PerfTests.CompetitionHelpers;
// ReSharper disable once CheckNamespace
namespace CodeJam
{
#region Helpers
public static class Ext
{
public static T MyMinBy<T, TValue>(this IEnumerable<T> source, Func<T, TValue> selector)
{
var greater = Operators<TValue>.GreaterThan;
var result = default(T);
var nullResult = default(T);
var resultValue = default(TValue);
bool hasData = false;
foreach (var item in source)
{
var temp = selector(item);
if (temp == null)
{
nullResult = item;
hasData = true;
}
else if (!hasData || greater(resultValue, temp))
{
result = item;
resultValue = temp;
hasData = true;
}
}
if (!hasData && result == null)
throw new Exception("Bla-bla-bla");
return result == null ? nullResult : result;
}
public static T MyMinByComparer<T, TValue>(
this IEnumerable<T> source,
Func<T, TValue> selector,
IComparer<TValue> comparer = null)
{
comparer = comparer ?? Comparer<TValue>.Default;
var result = default(T);
var nullResult = default(T);
var resultValue = default(TValue);
bool hasData = false;
foreach (var item in source)
{
var temp = selector(item);
if (temp == null)
{
nullResult = item;
hasData = true;
}
else if (!hasData || comparer.Compare(resultValue, temp) > 0)
{
result = item;
resultValue = temp;
hasData = true;
}
}
if (!hasData && result == null)
throw new Exception("Bla-bla-bla");
return result == null ? nullResult : result;
}
}
#endregion
[PublicAPI]
[TestFixture(Category = PerfTestCategory + ": EnumHelper")]
public class TempPerfTests
{
public class Data
{
public Data(int structField)
{
StructField = structField;
StructFieldNullable = (structField % 10) == 0
? (int?)null
: structField;
StringField = (structField % 10) == 0
? null
: structField.ToString();
}
public int StructField { get; }
public int? StructFieldNullable { get; }
public string StringField { get; }
}
private static readonly Data[] _data = GetData();
private static Data[] GetData()
{
var rnd = new Random(0); // fixed seed to get repeatable results;
return Enumerable.Range(1, 1000).Select(i => new Data(rnd.Next(1000))).ToArray();
}
[Test]
public void CheckCorrectness()
{
var x1 = _data.MinBy(a => a.StructField);
var x2 = _data.MyMinBy(a => a.StructField);
var x3 = _data.MyMinByComparer(a => a.StructField);
var x4 = _data.Select(a => a.StructField).Min();
Assert.AreEqual(x1, x2);
Assert.AreEqual(x1, x3);
Assert.AreEqual(x1.StructField, x4);
var x21 = _data.MinBy(a => a.StructFieldNullable);
var x22 = _data.MyMinBy(a => a.StructFieldNullable);
var x23 = _data.MyMinByComparer(a => a.StructFieldNullable);
var x24 = _data.Select(a => a.StructFieldNullable).Min();
Assert.AreEqual(x21, x22);
Assert.AreEqual(x21, x23);
Assert.AreEqual(x21.StructFieldNullable, x24);
var x31 = _data.MinBy(a => a.StringField);
var x32 = _data.MyMinBy(a => a.StringField);
var x33 = _data.MyMinByComparer(a => a.StringField);
var x34 = _data.Select(a => a.StringField).Min();
Assert.AreEqual(x31, x32);
Assert.AreEqual(x31, x33);
Assert.AreEqual(x31.StringField, x34);
}
[Test]
public void RunMinByIntCase() => Competition.Run<MinByIntCase>(RunConfig);
public class MinByIntCase
{
[CompetitionBaseline]
public Data MinCodeJam() => _data.MinBy(x => x.StructField);
[CompetitionBenchmark(18.45, 19.60)]
public Data MinNaive() => _data.OrderBy(x => x.StructField).FirstOrDefault();
[CompetitionBenchmark(1.18, 1.33)]
public Data MyMinBy() => _data.MyMinBy(x => x.StructField);
[CompetitionBenchmark(1.35, 1.40)]
public Data MyMinByComparer() => _data.MyMinByComparer(x => x.StructField);
[CompetitionBenchmark(0.12, 0.14)]
public Data MinDoneRight()
{
Data result = null;
int resultValue = 0;
var local = _data;
foreach (var other in local)
{
if (result == null || resultValue > other.StructField)
{
result = other;
resultValue = other.StructField;
}
}
return result;
}
}
[Test]
public void RunMinByStringCase() => Competition.Run<MinByStringCase>(RunConfig);
public class MinByStringCase
{
[CompetitionBaseline]
public Data MinCodeJam() => _data.MinBy(x => x.StringField);
[CompetitionBenchmark(13.20, 14.34)]
public Data MinNaive() => _data.OrderBy(x => x.StringField).FirstOrDefault();
[CompetitionBenchmark(0.10, 0.11)]
public Data MyMinBy() => _data.MyMinBy(x => x.StringField);
[CompetitionBenchmark(0.89, 0.97)]
public Data MyMinByComparer() => _data.MyMinByComparer(x => x.StringField);
[CompetitionBenchmark(0.81, 0.87)]
public Data MinDoneRight()
{
Data result = null;
Data nullResult = null;
string resultValue = null;
var local = _data;
foreach (var other in local)
{
if (other.StringField == null)
{
nullResult = other;
}
else if (result == null || string.Compare(resultValue, other.StringField) > 0)
{
result = other;
resultValue = other.StringField;
}
}
return result ?? nullResult;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment