Skip to content

Instantly share code, notes, and snippets.

@SpaceAntelope
Last active March 8, 2016 07:31
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 SpaceAntelope/d0ed8a241f8bbac8e132 to your computer and use it in GitHub Desktop.
Save SpaceAntelope/d0ed8a241f8bbac8e132 to your computer and use it in GitHub Desktop.
Paste into a C# Interactive window and press enter.
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using static LifeBoundary;
/*
* The idea is to use a stack to keep track of how many presidents
* are alive at a given time.
*
* When a president is born we push a birth year to the stack, while popping a
* year for every death.
*
* Thus, if we check the length of the stack every time we are about to pop a year,
* we have the number of living presidents from the year in the first element of
* the stack until the death year that caused the popping event.
*/
/// <summary>
/// POCO that holds a year and the indication whether
/// it is a birth year or a death year
/// </summary>
public sealed class LifeBoundary
{
public enum YearKind { Open, Close };
public YearKind Kind { get; private set; }
public int Year { get; private set; }
public LifeBoundary(YearKind kind, int year) { Kind = kind; Year = year; }
public override string ToString() => $"{Year} {(Kind == YearKind.Close ? "✟" : "🎂")}";
}
/// <summary>
/// An object meant to keep track of the number of presidents
/// alive at a given period of years
/// </summary>
public sealed class Range
{
public int FromYear { get; private set; }
public int ToYear { get; private set; }
public int LivingPresidents { get; private set; }
public int Length => ToYear - FromYear;
public Range(int start, int stop, int presidentsCount) { FromYear = start; ToYear = stop; LivingPresidents = presidentsCount;}
public override string ToString() => $"{LivingPresidents} alive in {FromYear} - {ToYear}";
}
var stack = new Stack<LifeBoundary>();
File.ReadAllLines(@"Presidents.csv")
.Skip(1)
.Select(line => line.Split(',').Select(field => field.Trim()).ToArray())
.SelectMany(record => new[] {
new LifeBoundary (YearKind.Open,DateTime.Parse(record[1]).Year),
new LifeBoundary (YearKind.Close, string.IsNullOrEmpty(record[3])
? DateTime.Today.Year
: DateTime.Parse(record[3]).Year)})
.OrderBy(item => item.Year)
.ThenBy(item => item.Kind)
// Sorting according to kind prevents a death from neutralizing a birth in
// the same year, as long as the birth year comes first
.Select(item =>
{
switch (item.Kind)
{
case YearKind.Open:
stack.Push(item);
break;
case YearKind.Close:
var currentRange = new Range(stack.First().Year, item.Year, stack.Count);
stack.Pop();
return currentRange;
}
return new Range(0, 0, 0);
})
.GroupBy(range=> range.LivingPresidents )
.OrderBy(group=> group.Key)
.Last()
.Select(line => string.Join(", ", line))
.ToList()
.ForEach(Console.WriteLine);
;;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment