package main import ( "bufio" "fmt" "log" "os" "sort" "strconv" "strings" "time" ) var guards map[int]*Guard func main() { inp := StdinToStringSlice() buildGuardMap(inp) part1() part2() } func buildGuardMap(inp []string) { sort.Strings(inp) guards = make(map[int]*Guard) var currGuard int var sleepStart time.Time for _, v := range inp { t, _ := time.Parse("2006-01-02 15:04", v[1:17]) actionParts := strings.Split(v[19:], " ") switch actionParts[0][0] { case 'G': currGuard = Atoi(actionParts[1][1:]) case 'f': sleepStart = t case 'w': if _, ok := guards[currGuard]; !ok { guards[currGuard] = &Guard{ id: currGuard, totalSleepTime: 0, sleepLog: make([]Nap, 0, 5), } } guards[currGuard].TakeNap(sleepStart, t) } } } func part1() { var sleepiest int var sleepiestTime int for k, v := range guards { if v.TotalNapTime() > sleepiestTime { sleepiest = k sleepiestTime = v.TotalNapTime() } } min, _ := guards[sleepiest].GetSleepiestMinute() fmt.Println("= Part 1 =") fmt.Println("Sleepiest Guard:", sleepiest, "(", sleepiestTime, ") Sleepiest Minute:", min) fmt.Println("= Answer =") fmt.Println(sleepiest * min) } func part2() { var sleepiestTime int type tuple struct { v1, v2 int } sleepiestMinutes := make(map[int]tuple) for _, v := range guards { v1, v2 := v.GetSleepiestMinute() sleepiestMinutes[v.id] = tuple{v1, v2} if v.TotalNapTime() > sleepiestTime { sleepiestTime = v.TotalNapTime() } } var highestCount, highestCountGuard, highestCountMinute int for k, v := range sleepiestMinutes { if v.v2 > highestCount { highestCount = v.v2 highestCountGuard = k highestCountMinute = v.v1 } } fmt.Println("= Part 2 =") fmt.Printf("Guard: %d\nMinute: %d\nCount: %d\n", highestCountGuard, highestCountMinute, highestCount) fmt.Println("= Answer =") fmt.Println(highestCountGuard * highestCountMinute) } type Guard struct { id int totalSleepTime int sleepLog []Nap } func (g *Guard) TakeNap(start, end time.Time) { g.sleepLog = append( g.sleepLog, Nap{start: start, end: end}) } func (g *Guard) TotalNapTime() int { var ret int for _, v := range g.sleepLog { ret += int(v.end.Sub(v.start).Minutes()) } return ret } func (g *Guard) GetSleepiestMinute() (int, int) { minuteMap := make(map[int]int) for _, v := range g.sleepLog { wrkMin := v.start.Minute() for wrkMin < v.end.Minute() { minuteMap[wrkMin]++ wrkMin++ } } var sleepiestMinute, sleepiestCount int for k, v := range minuteMap { if v > sleepiestCount { sleepiestMinute = k sleepiestCount = v } } return sleepiestMinute, minuteMap[sleepiestMinute] } type Nap struct { start time.Time end time.Time } func StdinToStringSlice() []string { var input []string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { input = append(input, scanner.Text()) } return input } func Atoi(i string) int { var ret int var err error if ret, err = strconv.Atoi(i); err != nil { log.Fatal("Invalid Atoi") } return ret }