mirror of
https://github.com/SebastianStork/advent-of-code.git
synced 2026-01-21 15:41:34 +01:00
Solve 2024 day 9 in go
This commit is contained in:
parent
4fc651a297
commit
4c759a5053
4 changed files with 159 additions and 2 deletions
154
2024/go/day-09/main.go
Normal file
154
2024/go/day-09/main.go
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func readInput() (fileMap []int, err error) {
|
||||
content, err := os.ReadFile("input")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(string(content))
|
||||
for _, digit := range line {
|
||||
fileMap = append(fileMap, int(digit-'0'))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func convertToBlockMap(fileMap []int) []int {
|
||||
var blockMap []int
|
||||
|
||||
for i, digit := range fileMap {
|
||||
for _ = range digit {
|
||||
if i%2 == 0 { // Even
|
||||
blockMap = append(blockMap, i/2)
|
||||
} else { // Odd
|
||||
blockMap = append(blockMap, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockMap
|
||||
}
|
||||
|
||||
func compress1(blockMap []int) []int {
|
||||
newBlockMap := make([]int, len(blockMap))
|
||||
copy(newBlockMap, blockMap)
|
||||
|
||||
leftIndex := 0
|
||||
rightIndex := len(newBlockMap) - 1
|
||||
|
||||
for leftIndex < rightIndex {
|
||||
left := &newBlockMap[leftIndex]
|
||||
right := &newBlockMap[rightIndex]
|
||||
|
||||
if *left == -1 && *right != -1 {
|
||||
*left, *right = *right, *left
|
||||
|
||||
leftIndex++
|
||||
rightIndex--
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if *left != -1 {
|
||||
leftIndex++
|
||||
}
|
||||
if *right == -1 {
|
||||
rightIndex--
|
||||
}
|
||||
}
|
||||
|
||||
return newBlockMap
|
||||
}
|
||||
|
||||
type segment struct {
|
||||
index, length int
|
||||
}
|
||||
|
||||
func getSegments(fileMap []int) (files, freeSpaces []segment) {
|
||||
var blockIndex int
|
||||
|
||||
for segmentIndex, length := range fileMap {
|
||||
if segmentIndex%2 == 0 { // Even
|
||||
files = append(files, segment{blockIndex, length})
|
||||
} else { // Odd
|
||||
freeSpaces = append(freeSpaces, segment{blockIndex, length})
|
||||
}
|
||||
|
||||
blockIndex += length
|
||||
}
|
||||
|
||||
slices.Reverse(files)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func compress2(blockMap, fileMap []int) []int {
|
||||
newBlockMap := make([]int, len(blockMap))
|
||||
copy(newBlockMap, blockMap)
|
||||
|
||||
files, freeSpaces := getSegments(fileMap)
|
||||
|
||||
for fileIndex, file := range files {
|
||||
for freeSpaceIndex, freeSpace := range freeSpaces {
|
||||
if freeSpace.index > file.index {
|
||||
break
|
||||
}
|
||||
|
||||
if freeSpace.length >= file.length {
|
||||
// Swap blocks
|
||||
idNumber := newBlockMap[file.index]
|
||||
for i := 0; i < file.length; i++ {
|
||||
newBlockMap[freeSpaces[freeSpaceIndex].index+i] = idNumber
|
||||
newBlockMap[files[fileIndex].index+i] = -1
|
||||
}
|
||||
|
||||
// Shrink free space
|
||||
freeSpaces[freeSpaceIndex].index += file.length
|
||||
freeSpaces[freeSpaceIndex].length -= file.length
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newBlockMap
|
||||
}
|
||||
|
||||
func calculateChecksum(fileMap []int) int {
|
||||
var sum int
|
||||
|
||||
for i, num := range fileMap {
|
||||
if num == -1 {
|
||||
continue
|
||||
}
|
||||
|
||||
sum += i * num
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
|
||||
func main() {
|
||||
fileMap, err := readInput()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
blockMap := convertToBlockMap(fileMap)
|
||||
checksum1 := calculateChecksum(compress1(blockMap))
|
||||
checksum2 := calculateChecksum(compress2(blockMap, fileMap))
|
||||
|
||||
// Part one
|
||||
fmt.Println("Checksum 1:", checksum1)
|
||||
// Part two
|
||||
fmt.Println("Checksum 2:", checksum2)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue