diff --git a/AdventOfCode2018.Tests/AdventOfCode2018.Tests.csproj b/AdventOfCode2018.Tests/AdventOfCode2018.Tests.csproj
index f87a768..f7c0d7c 100644
--- a/AdventOfCode2018.Tests/AdventOfCode2018.Tests.csproj
+++ b/AdventOfCode2018.Tests/AdventOfCode2018.Tests.csproj
@@ -61,6 +61,7 @@
+
diff --git a/AdventOfCode2018.Tests/GuardEvent_Tests.cs b/AdventOfCode2018.Tests/GuardEvent_Tests.cs
new file mode 100644
index 0000000..9431704
--- /dev/null
+++ b/AdventOfCode2018.Tests/GuardEvent_Tests.cs
@@ -0,0 +1,134 @@
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace AdventOfCode2018.Tests
+{
+ [TestClass()]
+ public class GuardEvent_Tests
+ {
+ #region FromString
+
+ [TestMethod()]
+ public void FromString__ShiftBegin()
+ {
+ GuardEvent guardEvent = GuardEvent.FromString("[1518-11-01 00:00] Guard #10 begins shift");
+
+ Assert.AreEqual(10, guardEvent.ID);
+ Assert.AreEqual(11, guardEvent.Date.Month);
+ Assert.AreEqual(1, guardEvent.Date.Day);
+ Assert.AreEqual(0, guardEvent.Date.Hour);
+ Assert.AreEqual(0, guardEvent.Date.Minute);
+ Assert.AreEqual(GuardEventType.ShiftBegin, guardEvent.Type);
+ }
+
+ [TestMethod()]
+ public void FromString__FallSleep()
+ {
+ GuardEvent guardEvent = GuardEvent.FromString("[1518-11-02 00:40] falls asleep");
+
+ Assert.AreEqual(null, guardEvent.ID);
+ Assert.AreEqual(11, guardEvent.Date.Month);
+ Assert.AreEqual(2, guardEvent.Date.Day);
+ Assert.AreEqual(0, guardEvent.Date.Hour);
+ Assert.AreEqual(40, guardEvent.Date.Minute);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvent.Type);
+ }
+
+ [TestMethod()]
+ public void FromString__WakeUp()
+ {
+ GuardEvent guardEvent = GuardEvent.FromString("[1518-11-03 00:29] wakes up");
+
+ Assert.AreEqual(null, guardEvent.ID);
+ Assert.AreEqual(11, guardEvent.Date.Month);
+ Assert.AreEqual(3, guardEvent.Date.Day);
+ Assert.AreEqual(0, guardEvent.Date.Hour);
+ Assert.AreEqual(29, guardEvent.Date.Minute);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvent.Type);
+ }
+
+ #endregion FromString
+
+ #region FromStringArray
+
+ [TestMethod()]
+ public void FromStringArray__TestBase()
+ {
+ List guardEvents = GuardEvent.FromStringArray(new string[] {
+ "[1518-11-01 00:00] Guard #10 begins shift",
+ "[1518-11-01 00:05] falls asleep",
+ "[1518-11-01 00:25] wakes up",
+ "[1518-11-01 00:30] falls asleep",
+ "[1518-11-01 00:55] wakes up",
+ "[1518-11-01 23:58] Guard #99 begins shift",
+ "[1518-11-02 00:40] falls asleep",
+ "[1518-11-02 00:50] wakes up",
+ });
+
+ Assert.AreEqual(10, guardEvents[0].ID);
+ Assert.AreEqual(GuardEventType.ShiftBegin, guardEvents[0].Type);
+
+ Assert.AreEqual(10, guardEvents[1].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[1].Type);
+
+ Assert.AreEqual(10, guardEvents[2].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[2].Type);
+
+ Assert.AreEqual(10, guardEvents[3].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[3].Type);
+
+ Assert.AreEqual(10, guardEvents[4].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[4].Type);
+
+ Assert.AreEqual(99, guardEvents[5].ID);
+ Assert.AreEqual(GuardEventType.ShiftBegin, guardEvents[5].Type);
+
+ Assert.AreEqual(99, guardEvents[6].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[6].Type);
+
+ Assert.AreEqual(99, guardEvents[7].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[7].Type);
+ }
+
+ [TestMethod()]
+ public void FromStringArray__TestBaseUnsorted()
+ {
+ List guardEvents = GuardEvent.FromStringArray(new string[] {
+ "[1518-11-01 00:00] Guard #10 begins shift",
+ "[1518-11-01 23:58] Guard #99 begins shift",
+ "[1518-11-01 00:30] falls asleep",
+ "[1518-11-02 00:40] falls asleep",
+ "[1518-11-01 00:05] falls asleep",
+ "[1518-11-02 00:50] wakes up",
+ "[1518-11-01 00:55] wakes up",
+ "[1518-11-01 00:25] wakes up",
+ });
+
+ Assert.AreEqual(10, guardEvents[0].ID);
+ Assert.AreEqual(GuardEventType.ShiftBegin, guardEvents[0].Type);
+
+ Assert.AreEqual(10, guardEvents[1].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[1].Type);
+
+ Assert.AreEqual(10, guardEvents[2].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[2].Type);
+
+ Assert.AreEqual(10, guardEvents[3].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[3].Type);
+
+ Assert.AreEqual(10, guardEvents[4].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[4].Type);
+
+ Assert.AreEqual(99, guardEvents[5].ID);
+ Assert.AreEqual(GuardEventType.ShiftBegin, guardEvents[5].Type);
+
+ Assert.AreEqual(99, guardEvents[6].ID);
+ Assert.AreEqual(GuardEventType.FallSleep, guardEvents[6].Type);
+
+ Assert.AreEqual(99, guardEvents[7].ID);
+ Assert.AreEqual(GuardEventType.WakeUp, guardEvents[7].Type);
+ }
+
+ #endregion FromStringArray
+ }
+}
\ No newline at end of file
diff --git a/AdventOfCode2018/Day04.cs b/AdventOfCode2018/Day04.cs
index a5a313d..c132faf 100644
--- a/AdventOfCode2018/Day04.cs
+++ b/AdventOfCode2018/Day04.cs
@@ -1,4 +1,8 @@
-namespace AdventOfCode2018
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode2018
{
/*
--- Day 4: Repose Record ---
@@ -59,12 +63,185 @@
{
public string ResolvePart1(string[] inputs)
{
- return null;
+ List guardEvents = GuardEvent.FromStringArray(inputs);
+ Dictionary dictFullHistogram = BuildFullHistorgram(guardEvents);
+
+ // Find sleepier guard
+ GuardSleepHistogram highestSleeperHistogram = null;
+ long highestTotalSleep = long.MinValue;
+ foreach (GuardSleepHistogram guardHistogram in dictFullHistogram.Values)
+ {
+ int totalSleep = guardHistogram.SleepOnMunute.Sum();
+
+ if (totalSleep > highestTotalSleep)
+ {
+ highestSleeperHistogram = guardHistogram;
+ highestTotalSleep = totalSleep;
+ }
+ }
+
+ // Find sleepier minute
+ int maxSleepMinute = int.MinValue;
+ int maxSleepMinuteValue = int.MinValue;
+ for (int i = 0; i < GuardSleepHistogram.MinutesOnHour; i++)
+ {
+ if (highestSleeperHistogram.SleepOnMunute[i] > maxSleepMinuteValue)
+ {
+ maxSleepMinute = i;
+ maxSleepMinuteValue = highestSleeperHistogram.SleepOnMunute[i];
+ }
+ }
+
+ int result = highestSleeperHistogram.ID * maxSleepMinute;
+ return result.ToString();
}
public string ResolvePart2(string[] inputs)
{
return null;
}
+
+ private static Dictionary BuildFullHistorgram(List guardEvents)
+ {
+ Dictionary dictFullHistogram = new Dictionary();
+ foreach (IGrouping group in guardEvents.GroupBy(guardEvent => guardEvent.Date.DayOfYear))
+ {
+ Dictionary dictDayHistogram = new Dictionary();
+ foreach (GuardEvent guardEvent in group)
+ {
+ if (guardEvent.ID == null) { continue; }
+ GuardSleepHistogram dayGuardHistogram = null;
+ if (dictDayHistogram.ContainsKey((int)guardEvent.ID))
+ {
+ dayGuardHistogram = dictDayHistogram[(int)guardEvent.ID];
+ }
+ else
+ {
+ dayGuardHistogram = new GuardSleepHistogram { ID = (int)guardEvent.ID };
+ dictDayHistogram.Add(dayGuardHistogram.ID, dayGuardHistogram);
+ }
+ if (guardEvent.Type == GuardEventType.FallSleep)
+ {
+ dayGuardHistogram.FallSleep(guardEvent.Date.Minute);
+ }
+ if (guardEvent.Type == GuardEventType.WakeUp)
+ {
+ dayGuardHistogram.WakeUp(guardEvent.Date.Minute);
+ }
+ }
+
+ foreach (GuardSleepHistogram dayGuardHistogram in dictDayHistogram.Values)
+ {
+ GuardSleepHistogram guardHistogram = null;
+ if (dictFullHistogram.ContainsKey(dayGuardHistogram.ID))
+ {
+ guardHistogram = dictFullHistogram[dayGuardHistogram.ID];
+ guardHistogram.AddHistogram(dayGuardHistogram);
+ }
+ else
+ {
+ dictFullHistogram.Add(dayGuardHistogram.ID, dayGuardHistogram);
+ }
+ }
+ }
+
+ return dictFullHistogram;
+ }
+ }
+
+ public enum GuardEventType
+ {
+ ShiftBegin,
+ FallSleep,
+ WakeUp,
+ }
+
+ public class GuardEvent
+ {
+ public DateTime Date { get; set; }
+ public int? ID { get; set; }
+ public GuardEventType Type { get; set; }
+
+ public static GuardEvent FromString(string strEvent)
+ {
+ GuardEvent guardEvent = new GuardEvent();
+ string[] parts = strEvent.Split(new string[] { "[", "-", " ", ":", "]", "#", }, StringSplitOptions.RemoveEmptyEntries);
+ guardEvent.Date = new DateTime(
+ Convert.ToInt32(parts[0]),
+ Convert.ToInt32(parts[1]),
+ Convert.ToInt32(parts[2]),
+ Convert.ToInt32(parts[3]),
+ Convert.ToInt32(parts[4]),
+ 0
+ );
+ if (parts[5] == "Guard")
+ {
+ guardEvent.ID = Convert.ToInt32(parts[6]);
+ guardEvent.Type = GuardEventType.ShiftBegin;
+ }
+ if (parts[5] == "falls")
+ {
+ guardEvent.Type = GuardEventType.FallSleep;
+ }
+ if (parts[5] == "wakes")
+ {
+ guardEvent.Type = GuardEventType.WakeUp;
+ }
+ return guardEvent;
+ }
+
+ public static List FromStringArray(string[] strEvents)
+ {
+ List guardEvents = strEvents
+ .Select(strEvent => FromString(strEvent))
+ .OrderBy(guardEvent => guardEvent.Date)
+ .ToList();
+
+ int? guardID = null;
+ foreach (GuardEvent guardEvent in guardEvents)
+ {
+ if (guardEvent.Type == GuardEventType.ShiftBegin)
+ {
+ guardID = guardEvent.ID;
+ }
+ else
+ {
+ guardEvent.ID = guardID;
+ }
+ }
+
+ return guardEvents;
+ }
+ }
+
+ public class GuardSleepHistogram
+ {
+ public const int MinutesOnHour = 60;
+ public int ID { get; set; }
+ public int[] SleepOnMunute { get; } = new int[MinutesOnHour];
+
+ public void FallSleep(int minute)
+ {
+ for (int i = minute; i < MinutesOnHour; i++)
+ {
+ SleepOnMunute[i] = 1;
+ }
+ }
+
+ public void WakeUp(int minute)
+ {
+ for (int i = minute; i < MinutesOnHour; i++)
+ {
+ SleepOnMunute[i] = 0;
+ }
+ }
+
+ public void AddHistogram(GuardSleepHistogram histogram)
+ {
+ for (int i = 0; i < MinutesOnHour; i++)
+ {
+ SleepOnMunute[i] += histogram.SleepOnMunute[i];
+ }
+ }
}
}