package day09 func Part1(input string) int { files, gaps, lengthOfFinalFile := parseInput(input) checksum := compactFiles(files, gaps, lengthOfFinalFile) return checksum } func Part2(input string) int { files, freeSpaces := parseInputPart2(input) checksum := calculateChecksum(files, freeSpaces) return checksum } func parseInput(input string) ([]int, []int, int) { var files []int var gaps []int lengthOfFinalFile := 0 for i, char := range input { if i%2 == 0 { files = append(files, int(char-'0')) lengthOfFinalFile += int(char - '0') } else { gaps = append(gaps, int(char-'0')) } } return files, gaps, lengthOfFinalFile } func parseInputPart2(input string) ([][]int, [][]int) { files, freeSpaces, position := [][]int{}, [][]int{}, 0 for index, char := range input { length := int(char - '0') if index%2 == 0 { files = append(files, generateRange(position, position+length)) } else { freeSpaces = append(freeSpaces, generateRange(position, position+length)) } position += length } return files, freeSpaces } func compactFiles(files []int, gaps []int, lengthOfFinalFile int) int { fileIndex := len(files) - 1 gapIndex := 0 position := files[0] checksum := 0 fileID := files[0] for lengthOfFinalFile != position { // If there's a gap and a file to move then move the file if gaps[gapIndex] > 0 && files[fileIndex] > 0 { files[fileIndex]-- gaps[gapIndex]-- checksum += fileIndex * position position++ } // If this file is fully moved go to next file if files[fileIndex] == 0 { fileIndex-- fileID++ } // Update gapIndex if this gap is filled if gaps[gapIndex] == 0 { gapIndex++ for f := 0; f < files[gapIndex]; f++ { checksum += gapIndex * position position++ } } } return checksum } func generateRange(start, end int) []int { rangeList := make([]int, end-start) for i := range rangeList { rangeList[i] = start + i } return rangeList } func calculateChecksum(files, freeSpaces [][]int) int { checksum := 0 for fileIndex := len(files) - 1; fileIndex >= 0; fileIndex-- { for spaceIndex := 0; spaceIndex < len(freeSpaces); spaceIndex++ { if len(freeSpaces[spaceIndex]) >= len(files[fileIndex]) && files[fileIndex][0] > freeSpaces[spaceIndex][0] { files[fileIndex] = freeSpaces[spaceIndex][:len(files[fileIndex])] freeSpaces[spaceIndex] = freeSpaces[spaceIndex][len(files[fileIndex]):] } } } for fileID, file := range files { for _, block := range file { checksum += fileID * block } } return checksum }