// Some serious sub-optimal linq abuse going on here protected override int GetAnswer(string input) { var events = ParseInput(input); var orderedEvents = events.OrderBy(e => e.Month) .ThenBy(e => e.Day) .ThenBy(e => e.Hour) .ThenBy(e => e.Minute) .ToArray(); var guardInfos = new Dictionary <int, GuardInfo>(); var currentGuardId = 0; for (var i = 0; i < orderedEvents.Length - 1; i++) { var evnt = orderedEvents[i]; switch (evnt.EventType) { case EventType.BeginShift: currentGuardId = evnt.GuardId.Value; if (!guardInfos.ContainsKey(currentGuardId)) { guardInfos[currentGuardId] = new GuardInfo { GuardId = currentGuardId } } ; break; case EventType.WakeUp: // Nothing to do, only care about FallAsleep -> Wakeup Transitions // Guards appear to always wake up before next guard shift break; case EventType.FallAsleep: var wakeUpEvent = orderedEvents[i + 1]; if (wakeUpEvent.EventType != EventType.WakeUp) { throw new Exception("Your assumption that a wake up event always follows fall asleep is wrong."); } for (var m = evnt.Minute; m < wakeUpEvent.Minute; m++) { guardInfos[currentGuardId].MinuteSleepCounter[m]++; guardInfos[currentGuardId].TotalMinutesSlept++; } break; } } var max = guardInfos.Values.Select(gd => gd.TotalMinutesSlept).Max(); var gi = guardInfos.Values.First(gd => gd.TotalMinutesSlept == max); return(gi.Answer); }
public static Dictionary <int, GuardInfo> ParseGuards(List <Line> lines) { if (lines == null) { throw new ArgumentNullException(nameof(lines)); } if (lines.Count == 0) { throw new ArgumentException("Value cannot be an empty collection.", nameof(lines)); } var guards = new Dictionary <int, GuardInfo>(); GuardInfo currentGuard = null; foreach (var line in lines) { if (line._kind == Line.Kind.BeginShift) { if (!guards.ContainsKey(line._guardId)) { guards.Add(line._guardId, new GuardInfo { GuardId = line._guardId, Sleeps = new List <GuardInfo.SleepTime>() }); } currentGuard = guards[line._guardId]; } else if (line._kind == Line.Kind.FallAsleep) { currentGuard.Sleeps.Add(new GuardInfo.SleepTime { Start = line._timestamp.Minute }); } else if (line._kind == Line.Kind.WakeUp) { currentGuard.Sleeps.Last().End = line._timestamp.Minute; } } return(guards); }
public static (int Minute, int SleepCount) FindMinuteWithMaxSleep(this GuardInfo guard) { var sleepCountPerMinute = new int[60]; for (var i = 0; i < guard.Sleeps.Count; i++) { var s = guard.Sleeps[i]; for (var minute = s.Start; minute < s.End; minute++) { sleepCountPerMinute[minute]++; } } var biggestIndex = 0; for (var i = 0; i < 60; i++) { if (sleepCountPerMinute[i] > sleepCountPerMinute[biggestIndex]) { biggestIndex = i; } } return(biggestIndex, sleepCountPerMinute[biggestIndex]);
static void Main(string[] args) { //sort input by date and time Regex logRegex = new Regex(@"\[1518-(\d\d)-(\d\d) (\d\d):(\d\d)\] (.*)"); MatchCollection logEntries = logRegex.Matches(System.IO.File.ReadAllText("input.txt")); LogEntry[] entries = new LogEntry[logEntries.Count]; for (int i = 0; i < logEntries.Count; i++) { //parse to get relevant info entries[i] = new LogEntry(int.Parse(logEntries[i].Groups[1].Value), int.Parse(logEntries[i].Groups[2].Value), int.Parse(logEntries[i].Groups[3].Value), int.Parse(logEntries[i].Groups[4].Value), logEntries[i].Groups[5].Value); } Array.Sort(entries); //read the log int guardID = 0, previousMinute = 0; Dictionary <int, GuardInfo> guards = new Dictionary <int, GuardInfo>(); GuardInfo current, sleepiest = new GuardInfo { id = 0, slept = 0, map = new int[60] }; //count minutes slept by each guard //and create a minute map to identify the most sleepy minute later foreach (LogEntry entry in entries) { if (entry.action.StartsWith('G')) //guard begins shift { guardID = int.Parse(entry.action.Replace("Guard #", "").Split(" ")[0]); } else if (entry.action.StartsWith('f')) //guard falls asleep { previousMinute = entry.minute; } else //guard wakes up { if (guards.ContainsKey(guardID)) { current = guards[guardID]; } else { current = new GuardInfo { id = guardID, slept = 0, map = new int[60] }; guards.Add(guardID, current); } current.slept += (entry.minute - previousMinute); for (int i = previousMinute; i < entry.minute; i++) { current.map[i]++; } guards[guardID] = current; if (current.slept > sleepiest.slept) { sleepiest = current; } } } Console.WriteLine("Sleepiest guard is " + sleepiest.id); int maxSleepCount = sleepiest.map.Max(); Console.WriteLine("Sleepiest minute is " + Array.IndexOf(sleepiest.map, maxSleepCount)); Console.WriteLine("First answer: " + sleepiest.id * Array.IndexOf(sleepiest.map, maxSleepCount)); //find absolute sleepiest minute and corresponding guard (second *) foreach (GuardInfo g in guards.Values) { if (g.map.Max() > maxSleepCount) { sleepiest = g; maxSleepCount = g.map.Max(); } } Console.WriteLine("Sleepiest guard is " + sleepiest.id); Console.WriteLine("Sleepiest minute is " + Array.IndexOf(sleepiest.map, maxSleepCount)); Console.WriteLine("Second answer: " + sleepiest.id * Array.IndexOf(sleepiest.map, maxSleepCount)); Console.Read(); }
public static void Run(List <string> inputs) { GuardState lastState = GuardState.Off; GuardInfo lastGuard = null; int lastMinute = 0; List <InputData> inputDatas = new List <InputData>(); List <GuardInfo> Guards = new List <GuardInfo>(); foreach (var input in inputs) { inputDatas.Add(new InputData(input)); } foreach (var data in inputDatas.OrderBy(i => i.Time)) { var currentMinute = data.Time.Minute; if (data.Action == "Guard") { if (lastState == GuardState.Sleep) // if last guard was sleeping, finish his shift sleeping { lastGuard.Sleep(lastMinute, MinutesInHour); } lastGuard = Guards.FirstOrDefault(g => g.GuardNum == data.GuardNum); if (lastGuard == null) { lastGuard = new GuardInfo(data.GuardNum); Guards.Add(lastGuard); } lastState = GuardState.Off; } else if (data.Action == "wakes") { if (lastState == GuardState.Sleep) { lastGuard.Sleep(lastMinute, currentMinute); } lastState = GuardState.On; } else { lastState = GuardState.Sleep; } lastMinute = currentMinute; } //part 1 var lazyGuard = Guards.Aggregate((guard1, guard2) => guard1.GetSleepTime() > guard2.GetSleepTime() ? guard1 : guard2); var sleepTime = lazyGuard.GetHighestSleptHour(); var answer1 = lastGuard.GuardNum * sleepTime; //part 2 var mostFrequentlySleepingGuard = Guards.Aggregate( (guard1, guard2) => guard1.GetMostSleptTime() > guard2.GetMostSleptTime() ? guard1 : guard2); var answer2 = mostFrequentlySleepingGuard.GetHighestSleptHour() * mostFrequentlySleepingGuard.GuardNum; }