using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public static void Main() {
MyLove loveOfCSharp = "CSharp";
var howDoILoveThee = loveOfCSharp.AllTheWays.Count();
Console.WriteLine($"{ nameof(howDoILoveThee).ToWords() } ({ loveOfCSharp })? Ways = { howDoILoveThee }");
var allTestsSucceeded = RunUnitTests<AdventTests>();
Console.WriteLine(allTestsSucceeded ? "All tests passed!" : "Test failures occurred");
private static bool RunUnitTests<T>() where T: class, new()
bool overallSuccess = true;
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(mi => mi.ReturnType == typeof(void))
.Where(mi => mi.GetCustomAttributes<Xunit.FactAttribute>(inherit: false).Any())
foreach(var testMethodInfo in testMethods)
var testMethodName = testMethodInfo.Name;
Console.Write($"Executing test { testMethodName }...");
testMethodInfo.Invoke(tests, new object[] {});
Console.WriteLine("PASSED!");
Console.WriteLine($"FAILED - {ex}");
public class MyLove: IComparable<MyLove>
private const string SIGN_OF_LOVE = "<3!";
private const int MAX_LOVE = 1000;
private enum MyDeclaredLoves: int
AllOtherThings = CSharp - 10
private string _thingILove;
private int _howFarDownTheList;
private MyDeclaredLoves _levelOfLove;
public IEnumerable<string> AllTheWays => Enumerable.Repeat(SIGN_OF_LOVE, MAX_LOVE + _howFarDownTheList).ToArray();
public IEnumerable<string> ThingsILoveMore =>
.GetEnumValuesDictionary<MyDeclaredLoves>()
.Where(kvp => ((int)kvp.Value) > _howFarDownTheList)
.Select(kvp => $"{kvp.Key}")
public MyLove(string thingILove)
_thingILove = thingILove;
_howFarDownTheList = DetermineWhereOnTheList(_thingILove, out _levelOfLove);
private int DetermineWhereOnTheList(string thingIMightLove, out MyDeclaredLoves levelOfLove)
if(!MyDeclaredLoves.TryParse(thingIMightLove, out levelOfLove))
levelOfLove = MyDeclaredLoves.AllOtherThings;
public MyLove(object objectOfAffection): this($"{objectOfAffection}") {}
public override string ToString() { return $"my love of {_thingILove}"; }
int IComparable<MyLove>.CompareTo(MyLove otherLove) { return this._howFarDownTheList.CompareTo(otherLove._howFarDownTheList); }
public static implicit operator MyLove(string thingILove) { return new MyLove(thingILove); }
public static bool operator >(MyLove firstLove, MyLove secondLove)
return ((IComparable<MyLove>)firstLove).CompareTo(secondLove) > 0;
public static bool operator <(MyLove firstLove, MyLove secondLove)
return ((IComparable<MyLove>)firstLove).CompareTo(secondLove) < 0;
public static bool operator ==(MyLove firstLove, MyLove secondLove)
return ((IComparable<MyLove>)firstLove).CompareTo(secondLove) == 0;
public static bool operator !=(MyLove firstLove, MyLove secondLove)
return ((IComparable<MyLove>)firstLove).CompareTo(secondLove) != 0;
public override int GetHashCode() => _thingILove.GetHashCode();
public override bool Equals(object o) { return this.GetHashCode() == o.GetHashCode(); }
public static explicit operator int(MyLove love) => (int)love._levelOfLove;
public static class AdventExtensions
public static string ToWords(this string instance) {
return string.Join(" ", Regex.Split(instance ?? "", @"(?<=[^A-Z]|I)(?=[A-Z])"));
public static IEnumerable<string> HowDoILoveThee(this string objectOfAffection)
MyLove waysILoveThee = objectOfAffection;
var result = waysILoveThee.AllTheWays;
public static IDictionary<string, object> GetEnumValuesDictionary<T>(this Type type) where T: System.Enum
.ToDictionary(f => f.Name, f => f.GetRawConstantValue());
public static IEnumerable<T> Dump<T>(this IEnumerable<T> source, string title = null, bool includeTypeInfo = false)
if(!string.IsNullOrEmpty(title))
Console.WriteLine($"# { title }");
Console.WriteLine($"[{ typeof(T).FullName }]");
if(((object)source) == null)
Console.WriteLine("[null]");
if(type.IsAssignableTo(typeof(IEnumerable)))
var items = ((IEnumerable)source).Cast<object>().Select(i=>$"{i}");
Console.WriteLine("[" + string.Join("," + Environment.NewLine, items) + "]");
Console.WriteLine($"VALUE = {source}");
private const string YES_I_COULD_USE_A_CONSTANT_FOR_CSHARP = "CSharp";
private const string BACON_IS_DEFINITELY_A_CONSTANT_DUH = "Bacon";
public void OdeToMyLove_WaysILoveCSharpIsNotZero()
var ways = "CSharp".HowDoILoveThee().Count();
ways.ShouldBeGreaterThan(0);
public void OdeToMyLove_LoveCSharpShouldExceed500()
var ways = "CSharp".HowDoILoveThee().Count();
ways.ShouldBeGreaterThan(500);
public void OdeToMyLove_WaysILoveCSharpExceedsWaysILoveBacon_ShockingIKnow()
var waysILoveCSharp = YES_I_COULD_USE_A_CONSTANT_FOR_CSHARP.HowDoILoveThee().Count();
var waysILoveBacon = BACON_IS_DEFINITELY_A_CONSTANT_DUH.HowDoILoveThee().Count();
waysILoveCSharp.ShouldBeGreaterThan(waysILoveBacon);
public void OdeToMyLove_ILoveGodSpouseChildrenAndFriendsMoreThanBaconAndCSharpButItsClose()
var thingsILoveMore = new []{ "God", "Spouse", "Children", "Friends" };
var nearTheTopButNotAsFar = new[]{ "Bacon", "CSharp" };
var wrongPriorities = thingsILoveMore
.SelectMany(l => l.ThingsILoveMore.Dump(title: $"Things I love more than {l}"))
.Dump(title: "All the things I love more...")
.Intersect(nearTheTopButNotAsFar.Dump(title: "Things near the top, but not as far ="))
.Dump(title: "Intersection");
wrongPriorities.ShouldBeEmpty();
public void OdeToMyLove_ILoveCSharpMoreThanBacon()
MyLove loveOfCSharp = "CSharp";
MyLove loveOfBacon = "Bacon";
(loveOfCSharp > loveOfBacon).ShouldBeTrue();
public void OdeToMyLove_ILoveOtherThingsAboutTheSame()
MyLove firstRandomLove = "IceCream";
MyLove secondRandomLove = "VideoGames";
(firstRandomLove == secondRandomLove).ShouldBeTrue();
public void OdeToMyLove_ThingsILoveMoreThanGodShouldBeEmpty()
MyLove loveForGod = "God";
loveForGod.ThingsILoveMore.Dump(title: "Things I love more than God").ShouldBeEmpty();
public void ToWords_CamelCaseIdentifier_SplitsCorrectly()
string expectedValue = "expected Value";
string howDoILoveThee = "how Do I Love Thee";
(nameof(expectedValue)).ToWords().ShouldBe(expectedValue);
(nameof(howDoILoveThee)).ToWords().ShouldBe(howDoILoveThee);