Skip to content

Commit

Permalink
Implementation for 4a
Browse files Browse the repository at this point in the history
  • Loading branch information
nlowe committed Dec 5, 2018
1 parent cf9bf4d commit 70d0e0a
Show file tree
Hide file tree
Showing 4 changed files with 1,091 additions and 0 deletions.
3 changes: 3 additions & 0 deletions aoc2018.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"time"

"github.com/nlowe/aoc2018/day4"

"github.com/nlowe/aoc2018/day3"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -40,6 +42,7 @@ func main() {
day1.A, day1.B,
day2.A, day2.B,
day3.A, day3.B,
day4.A,
)

flags := rootCmd.PersistentFlags()
Expand Down
124 changes: 124 additions & 0 deletions day4/a.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package day4

import (
"fmt"
"sort"
"strconv"
"strings"
"time"

"github.com/nlowe/aoc2018/util"
"github.com/spf13/cobra"
)

var A = &cobra.Command{
Use: "4a",
Short: "Day 4, Problem A",
Run: func(_ *cobra.Command, _ []string) {
fmt.Printf("Answer: %d\n", a(util.ReadInput()))
},
}

const (
timestampLayout = "2006-01-02 15:04"
ActionBeginShift = "begins shift"
ActionFallAsleep = "falls asleep"
ActionWakeUp = "wakes up"
)

type event struct {
who int
what string
when time.Time
}

func ParseEvent(line string) *event {
result := &event{who: -1}
rawTime, rest := line[1:(1+len(timestampLayout))], strings.TrimSpace(line[(2+len(timestampLayout)):])

if t, err := time.Parse(timestampLayout, rawTime); err != nil {
panic(err)
} else {
result.when = t
}

if rest == ActionFallAsleep || rest == ActionWakeUp {
result.what = rest
} else {
result.what = ActionBeginShift

idSlug := strings.Split(rest[7:], " ")[0]
if id, err := strconv.Atoi(idSlug); err != nil {
panic(err)
} else {
result.who = id
}
}

return result
}

type sleepNumber struct {
total int
minutes [60]int
}

func a(input *util.ChallengeInput) int {
var events []*event

for line := range input.Lines() {
events = append(events, ParseEvent(line))
}

sort.Slice(events, func(i, j int) bool {
return events[i].when.Before(events[j].when)
})

patterns := map[int]*sleepNumber{}

lastGuard := 0
sleepingAt := 0
for _, event := range events {
if event.what == ActionBeginShift {
lastGuard = event.who
} else {
var tracker *sleepNumber
var found bool

if tracker, found = patterns[lastGuard]; !found {
tracker = &sleepNumber{total: 1, minutes: [60]int{}}
patterns[lastGuard] = tracker
}

if event.what == ActionFallAsleep {
sleepingAt = event.when.Minute()
} else {
for m := sleepingAt; m < event.when.Minute(); m++ {
tracker.total++
tracker.minutes[m]++
}
}
}
}

var candidateId int
var candidate *sleepNumber

for k, v := range patterns {
if candidate == nil || v.total > candidate.total {
candidateId = k
candidate = v
}
}

possibleMinute := 0
possibleResult := candidate.minutes[0]
for m, betterResult := range candidate.minutes[1:] {
if betterResult > possibleResult {
possibleMinute = m + 1
possibleResult = betterResult
}
}

return candidateId * possibleMinute
}
30 changes: 30 additions & 0 deletions day4/a_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package day4

import (
"testing"

"github.com/nlowe/aoc2018/util"
"github.com/stretchr/testify/require"
)

func TestA(t *testing.T) {
input := util.TestInput(`[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
[1518-11-03 00:05] Guard #10 begins shift
[1518-11-03 00:24] falls asleep
[1518-11-03 00:29] wakes up
[1518-11-04 00:02] Guard #99 begins shift
[1518-11-04 00:36] falls asleep
[1518-11-04 00:46] wakes up
[1518-11-05 00:03] Guard #99 begins shift
[1518-11-05 00:45] falls asleep
[1518-11-05 00:55] wakes up`)

require.Equal(t, 240, a(input))
}
Loading

0 comments on commit 70d0e0a

Please sign in to comment.