F#!
I found today the easiest thus far, but it ended up being the most verbose solution. Despite that I'm relatively pleased with it - it runs fast and I find it readable.
namespaceDay4openSystem.Text.RegularExpressionsmoduleutil=letgetContentsfileName=System.IO.File.ReadLines(fileName)|>Seq.toListtypeLogEntry=|NewGuardofSystem.DateTime*int|AsleepofSystem.DateTime|AwakeofSystem.DateTime|NonsenseletrecordRegex=@"^\[([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-3]{2}):([0-9]{2})] (.*)$"let(|FirstRegexGroup|_|)patterninput=letm=Regex.Match(input,pattern)if(m.Success)thenSomem.Groups.[1].ValueelseNoneletsortLoglog=List.sortBy(funel->matchelwith|LogEntry.Asleepdt->dt|LogEntry.Awakedt->dt|LogEntry.NewGuard(dt,_)->dt|LogEntry.Nonsense->newSystem.DateTime())logletscrapeLoginputs=List.map(funlogEntry->letm=Regex.Match(logEntry,recordRegex)ifm.Successthenletdt=newSystem.DateTime((m.Groups.[1].Value|>System.Convert.ToInt32),(m.Groups.[2].Value|>System.Convert.ToInt32),(m.Groups.[3].Value|>System.Convert.ToInt32),(m.Groups.[4].Value|>System.Convert.ToInt32),(m.Groups.[5].Value|>System.Convert.ToInt32),0)matchm.Groups.[6].Valuewith|"falls asleep"->LogEntry.Asleep(dt)|"wakes up"->LogEntry.Awake(dt)|FirstRegexGroup"Guard #([0-9]+) begins shift"badge->LogEntry.NewGuard(dt,System.Convert.ToInt32badge)|_->LogEntry.NonsenseelseLogEntry.Nonsense)inputs|>sortLogletfirst(a,_,_)=aletsecond(_,b,_)=bletthird(_,_,c)=ctypeMinuteCounts=Map<int,int>letgetHighestminuteCounts=Map.fold(funskv->ifv>sndsthen(k,v)elses)(0,0)minuteCountstypeSingleEntry={TotalAsleep:intMinuteCounts:MinuteCounts}typeSleepLog=Map<int,SingleEntry>lettickMinute(mcs:MinuteCounts)m=match(mcs.TryFindm)with|Somex->Map.addm(x+1)mcs|None->Map.addm1mcsletaddRangeToLogsleepwakesleepLogEntry=lettimeAsleep=wake-sleepleteachMinute=[foriinsleep..wake-1doyieldi]{TotalAsleep=sleepLogEntry.TotalAsleep+timeAsleep;MinuteCounts=List.foldtickMinutesleepLogEntry.MinuteCountseachMinute}letprocessLoglog=List.fold(funsel->matchelwith|LogEntry.NewGuard(_,badge)->(Somebadge,seconds,thirds)|LogEntry.Awakedt->match(firsts)with|Somebadge->match(seconds)with|SomesleepTime->letmap:SleepLog=thirdsletnewMap=matchmap.TryFindbadgewith|Somex->Map.addbadge(addRangeToLogsleepTimedt.Minutex)map|None->Map.addbadge(addRangeToLogsleepTimedt.Minute{TotalAsleep=0;MinuteCounts=(newMap<int,int>(Seq.empty))})map(firsts,None,newMap)|None->s// This branch indicates an error in the input - there was no "time asleep" stored for a "wakes up" entry|None->s// This branch indicates an error in the input - there was no active badge for a "wakes up" entry|LogEntry.Asleepdt->(firsts,Somedt.Minute,thirds)|LogEntry.Nonsense->s)(None,None,newMap<int,SingleEntry>(Seq.empty))// Active Badge, Minute Fell Asleep, SleepLoglogletgetSleepLogfileName=getContentsfileName|>scrapeLog|>processLog|>thirdmodulepart1=openutilletgetLongestAsleepsleepLog=sleepLog|>Map.fold(funskv->ifv.TotalAsleep>firststhen(v.TotalAsleep,k,getHighestv.MinuteCounts)elses)(0,0,(0,0))letexecutefileName=letres=getSleepLogfileName|>getLongestAsleep(secondres)*(fst(thirdres))modulepart2=openutilletgetMostFrequentAsleepsleepLog=sleepLog|>Map.fold(funsk(v:SingleEntry)->leth=getHighestv.MinuteCountsifsndh>=snd(snds)then(k,h)elses)(0,(0,0))letexecutefileName=letres=getSleepLogfileName|>getMostFrequentAsleep(fstres)*(fst(sndres))
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
F#!
I found today the easiest thus far, but it ended up being the most verbose solution. Despite that I'm relatively pleased with it - it runs fast and I find it readable.