mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2026-04-09 02:23:36 +00:00
reimplement day-09 with min heaps
re-run benchmarks
This commit is contained in:
@@ -2,5 +2,5 @@ goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/onyx-and-iris/aoc2024/day-09/internal/one
|
||||
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
|
||||
BenchmarkSolve-12 1000000000 0.1535 ns/op
|
||||
ok github.com/onyx-and-iris/aoc2024/day-09/internal/one 1.893s
|
||||
BenchmarkSolve-12 1000000000 0.2909 ns/op
|
||||
ok github.com/onyx-and-iris/aoc2024/day-09/internal/one 5.021s
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package one
|
||||
|
||||
const empty = -1
|
||||
|
||||
type block struct {
|
||||
used int
|
||||
free int
|
||||
}
|
||||
@@ -1,59 +1,24 @@
|
||||
package one
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
import "slices"
|
||||
|
||||
type disk struct {
|
||||
data []int
|
||||
totalUsed int
|
||||
data []int
|
||||
}
|
||||
|
||||
func newDisk(blocks []block) disk {
|
||||
var totalUsed int
|
||||
data := []int{}
|
||||
for id, block := range blocks {
|
||||
for range block.used {
|
||||
data = append(data, id)
|
||||
}
|
||||
for range block.free {
|
||||
data = append(data, empty)
|
||||
}
|
||||
totalUsed += block.used
|
||||
}
|
||||
|
||||
return disk{
|
||||
data: data,
|
||||
totalUsed: totalUsed,
|
||||
func newDisk(raw []int) *disk {
|
||||
return &disk{
|
||||
data: raw,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *disk) len() int {
|
||||
return d.totalUsed
|
||||
}
|
||||
|
||||
func (d *disk) sort() {
|
||||
func (d *disk) reorganise() {
|
||||
for i := len(d.data) - 1; i >= 0; i-- {
|
||||
if d.data[i] != empty {
|
||||
indx := slices.Index(d.data, empty)
|
||||
if indx == d.len() {
|
||||
break
|
||||
}
|
||||
d.data[i], d.data[indx] = d.data[indx], d.data[i]
|
||||
indx := slices.Index(d.data, empty)
|
||||
if indx >= i {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *disk) debug() string {
|
||||
var sb strings.Builder
|
||||
for _, n := range d.data {
|
||||
if n == empty {
|
||||
sb.WriteRune('.')
|
||||
} else {
|
||||
sb.WriteString(fmt.Sprintf("%d", n))
|
||||
}
|
||||
d.data[i], d.data[indx] = d.data[indx], d.data[i]
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
@@ -1,27 +1,70 @@
|
||||
package one
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"slices"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const empty = -1
|
||||
|
||||
func Solve(buf []byte) (int, error) {
|
||||
r := bytes.NewReader(buf)
|
||||
blocks, err := parseLines(r)
|
||||
expandedRaw, err := parseLines(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
disk := newDisk(blocks)
|
||||
disk.sort()
|
||||
log.Debug(disk.debug())
|
||||
disk := newDisk(expandedRaw)
|
||||
disk.reorganise()
|
||||
|
||||
var i, checksum int
|
||||
for range disk.len() {
|
||||
checksum += i * disk.data[i]
|
||||
i++
|
||||
var checksum int
|
||||
for i, n := range disk.data {
|
||||
if n == empty {
|
||||
break
|
||||
}
|
||||
checksum += i * n
|
||||
}
|
||||
|
||||
return checksum, nil
|
||||
}
|
||||
|
||||
func parseLines(r io.Reader) ([]int, error) {
|
||||
var line string
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line = scanner.Text()
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw := [][]int{}
|
||||
for i, id := 0, 0; i < len(line); i, id = i+2, id+1 {
|
||||
raw = append(raw, []int{id, mustConv(string(line[i]))})
|
||||
var free int
|
||||
if i < len(line)-1 {
|
||||
free = mustConv(string(line[i+1]))
|
||||
}
|
||||
raw = append(raw, []int{empty, free})
|
||||
}
|
||||
|
||||
expandedRaw := []int{}
|
||||
for _, vals := range raw {
|
||||
segment := slices.Repeat([]int{vals[0]}, vals[1])
|
||||
expandedRaw = append(expandedRaw, segment...)
|
||||
}
|
||||
|
||||
return expandedRaw, nil
|
||||
}
|
||||
|
||||
func mustConv(s string) int {
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package one
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func parseLines(r io.Reader) ([]block, error) {
|
||||
var blocks []block
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
for i := 0; i < len(line); i += 2 {
|
||||
var free int
|
||||
if i < len(line)-1 {
|
||||
free = mustConv(string(line[i+1]))
|
||||
}
|
||||
blocks = append(blocks, block{mustConv(string(line[i])), free})
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return []block{}, err
|
||||
}
|
||||
|
||||
return blocks, nil
|
||||
}
|
||||
|
||||
func mustConv(s string) int {
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
Reference in New Issue
Block a user