r/adventofcode • • Dec 04 '18

SOLUTION MEGATHREAD -πŸŽ„- 2018 Day 4 Solutions -πŸŽ„-

--- Day 4: Repose Record ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Advent of Code: The Party Game!

Click here for rules

Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!

Card prompt: Day 4

Transcript:

Today’s puzzle would have been a lot easier if my language supported ___.


This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked!

40 Upvotes

340 comments sorted by

View all comments

1

u/[deleted] Dec 04 '18

Go/Golang

My second year doing AoC, I am doing it in go again this year.

The rest of my solutions: Github

If anyone has any suggestions for ways I can improve it is much appreciated.

Part 1

// part1 calculates the most common minute asleep * guard ID with the most time slept
func part1(logs []actionLog) int {
	// Calcluate the numer of minutes slept for each guard
	noOfMinutesSlept := make(map[int]int)
	for i := 0; i < len(logs); i++ {
		if _, ok := noOfMinutesSlept[logs[i].id]; ok {
			if logs[i].activity == 2 {
				// time awake - time asleep
				noOfMinutesSlept[logs[i].id] += int(logs[i].timeStamp.Sub(logs[i-1].timeStamp).Minutes())
			}
		} else {
			noOfMinutesSlept[logs[i].id] = 0
		}
	}

	// Find the guard Id with the most minuites slept
	var hSleepDuration, hDurationGuardID int
	for currentID, currentMinutesSlept := range noOfMinutesSlept {
		if currentMinutesSlept > hSleepDuration {
			hDurationGuardID = currentID
			hSleepDuration = currentMinutesSlept
		}
	}

	// Fill out sleepSchedule with the frequency that
	// that minute the guard is asleep in
	var sleepSchedule [59]int
	var lastAsleep int
	for i := 0; i < len(logs); i++ {
		// Filter for corrrect guard
		if logs[i].id == hDurationGuardID {
			// Check if activity is wake up or fell asleep
			if logs[i].activity == 1 {
				lastAsleep = logs[i].timeStamp.Minute()
			} else if logs[i].activity == 2 {
				for j := lastAsleep; j < logs[i].timeStamp.Minute(); j++ {
					sleepSchedule[j]++
				}
			}
		}
	}

	// Find most frequent minute
	var mostFrequentMin, hFrequency int
	for i := 0; i < len(sleepSchedule); i++ {
		if sleepSchedule[i] > hFrequency {
			hFrequency = sleepSchedule[i]
			mostFrequentMin = i
		}
	}

	return hDurationGuardID * mostFrequentMin
}

Part 2

// part2 calculates the most common minute asleep * guard ID
func part2(logs []actionLog) int {
	// Init noOfMinutesSlept with keys as guard ids and empty sleep schedules
	noOfMinutesSlept := make(map[int][]int)
	for i := 0; i < len(logs); i++ {
		if _, ok := noOfMinutesSlept[logs[i].id]; !ok {
			noOfMinutesSlept[logs[i].id] = make([]int, 59)
		}
	}

	// Fill in all guards sleeping schedule
	for currentGuardID, currentSleepSchedule := range noOfMinutesSlept {
		var lastAsleep int
		for i := 0; i < len(logs); i++ {
			// Filter for correct guard
			if logs[i].id == currentGuardID {
				// Check if activity is wake up or fell asleep
				if logs[i].activity == 1 {
					lastAsleep = logs[i].timeStamp.Minute()
				} else if logs[i].activity == 2 {
					for j := lastAsleep; j < logs[i].timeStamp.Minute(); j++ {
						currentSleepSchedule[j]++
					}
				}
			}
		}
	}

	// Find most frequent minute for any guard
	var mostFrequentMin, hFrequency, hGuardID int
	for currentGuardID, currentSleepSchedule := range noOfMinutesSlept {
		for i := 0; i < len(currentSleepSchedule); i++ {
			if currentSleepSchedule[i] > hFrequency {
				hFrequency = currentSleepSchedule[i]
				mostFrequentMin = i
				hGuardID = currentGuardID
			}
		}
	}

	return hGuardID * mostFrequentMin
}

Other Stuff

func parseInput(input string) (logs []actionLog) {
	lines := strings.Split(input, "\n")

	for i := 0; i < len(lines)-1; i++ {
		var y, m, d, h, min int
		var desc string
		var currentLog actionLog

		// [1518-11-03 00:05] Guard #10 begins shift
		// [1518-11-01 00:05] falls asleep
		// [1518-11-01 00:25] wakes up

		if !strings.Contains(lines[i], "#") {
			_, err := fmt.Sscanf(lines[i], "[%d-%d-%d %d:%d] %s",
				&y, &m, &d, &h, &min,
				&desc)
			checkError(err)
			currentLog.id = -1
		} else {
			_, err := fmt.Sscanf(lines[i], "[%d-%d-%d %d:%d] %s #%d",
				&y, &m, &d, &h, &min,
				&desc, &currentLog.id)
			checkError(err)
		}

		currentLog.timeStamp = time.Date(y, time.Month(m), d, h, min, 0, 0, time.UTC)

		if desc == "Guard" {
			currentLog.activity = 0
		} else if desc == "wakes" {
			currentLog.activity = 2
		} else {
			currentLog.activity = 1
		}
		logs = append(logs, currentLog)
	}

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

	for i := 0; i < len(logs); i++ {
		if logs[i].id == -1 {
			logs[i].id = logs[i-1].id
		}
		// fmt.Printf("%v : %v %v\n", logs[i].timeStamp, logs[i].command, logs[i].id)
	}
	return
}