Day09
This commit is contained in:
104
2024/gareth/day09/day09.go
Normal file
104
2024/gareth/day09/day09.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
22
2024/gareth/day09/day09_test.go
Normal file
22
2024/gareth/day09/day09_test.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package day09
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPart1(t *testing.T) {
|
||||||
|
r := Part1(`12345`)
|
||||||
|
assert.Equal(t, 60, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPart1Long(t *testing.T) {
|
||||||
|
r := Part1(`2333133121414131402`)
|
||||||
|
assert.Equal(t, 1928, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPart2(t *testing.T) {
|
||||||
|
r := Part2(`2333133121414131402`)
|
||||||
|
assert.Equal(t, 2858, r)
|
||||||
|
}
|
||||||
1
2024/gareth/day09/input.txt
Normal file
1
2024/gareth/day09/input.txt
Normal file
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"aoc2024/day08"
|
"aoc2024/day09"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@@ -9,9 +9,11 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
data, _ := os.ReadFile("day08/input.txt")
|
data, _ := os.ReadFile("day09/input.txt")
|
||||||
fmt.Printf("part 1: %d\n", day08.Part1(string(data)))
|
fmt.Printf("part 1: %d\n", day09.Part1(string(data)))
|
||||||
fmt.Printf("part 2: %d\n", day08.Part2(string(data)))
|
fmt.Printf("part 2: %d\n", day09.Part2(string(data)))
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
fmt.Printf("Execution time: %s\n", elapsed)
|
fmt.Printf("Execution time: %s\n", elapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6320029754031
|
||||||
|
|||||||
Reference in New Issue
Block a user