Merge pull request 'chore: add multi-worker version of day 5' (#2) from day05 into main

Reviewed-on: xuu/advent-of-code-2023#2
This commit is contained in:
xuu 2023-12-05 15:18:48 -07:00
commit 5828cf65e1
2 changed files with 87 additions and 32 deletions

View File

@ -3,7 +3,6 @@ package main
import (
"bufio"
"fmt"
"log/slog"
"os"
"sort"
"strconv"
@ -11,11 +10,6 @@ import (
)
func main() {
var level slog.Level
if err := level.UnmarshalText([]byte(os.Getenv("DEBUG_LEVEL"))); err == nil && level != 0 {
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level})))
}
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Usage: day05 FILE")
}
@ -31,21 +25,24 @@ func main() {
fmt.Println("min location:", minLocation)
fmt.Println("min range location:", minRangeLocation)
}
func run(scan *bufio.Scanner) (int, int) {
log("begin...")
var seeds []int
var seedRanges []int
var seedRanges [][2]int
lookup := map[string]*Lookup{}
for scan.Scan() {
text := scan.Text()
if strings.HasPrefix(text, "seeds:") && len(seeds) == 0 {
seeds, seedRanges = readSeeds(text)
log("seeds", len(seeds), "ranges", len(seedRanges))
}
lookup = readMaps(scan)
log("lookups", len(lookup))
}
find := NewFinder(
@ -58,38 +55,21 @@ func run(scan *bufio.Scanner) (int, int) {
lookup["humidity-to-location"],
)
seedLocations := make([]int, len(seeds))
for i, s := range seeds {
seedLocations[i] = find.Find(s)
}
minLocation := min(seedLocations...)
seedRangeLocations := make([]int, len(seedRanges))
for i, s := range seedRanges {
seedRangeLocations[i] = find.Find(s)
}
minRangeLocation := min(seedRangeLocations...)
return minLocation, minRangeLocation
return findMinLocation(seeds, find), FindMinRangeLocationMulti(seedRanges, find)
}
func readSeeds(text string) ([]int, []int) {
var seeds, seedRanges []int
func readSeeds(text string) ([]int, [][2]int) {
var seeds [] int
var seedRanges [][2]int
sp := strings.Fields(strings.TrimPrefix(text, "seeds: "))
for i, s := range sp {
n, _ := strconv.Atoi(s)
seeds = append(seeds, n)
if i%2 == 0 {
seedRanges = append(seedRanges, n)
seedRanges = append(seedRanges, [2]int{n, 0})
} else {
lastN := seedRanges[len(seedRanges)-1]
r := make([]int, n-1)
for i := range r {
r[i] = lastN + i + 1
}
seedRanges = append(seedRanges, r...)
seedRanges[len(seedRanges)-1][1] = n
}
}
return seeds, seedRanges
@ -123,6 +103,74 @@ func readMaps(scan *bufio.Scanner) map[string]*Lookup {
return lookup
}
func findMinLocation(seeds []int, find *Finder) int {
seedLocations := make([]int, len(seeds))
for i, s := range seeds {
seedLocations[i] = find.Find(s)
}
return min(seedLocations...)
}
func FindMinRangeLocation(ranges [][2]int, find *Finder) int {
results := 0
for _, r := range ranges {
results += r[1]
}
seedLocations := make([]int, 0, results)
for _, s := range ranges {
for i := 0; i < s[1]; i++ {
seedLocations = append(seedLocations, find.Find(s[0] + i))
}
}
return min(seedLocations...)
}
func FindMinRangeLocationMulti(ranges [][2]int, find *Finder) int {
worker := func(id int, jobs <-chan [2]int, results chan<- []int) {
for s := range jobs {
res := make([]int, s[1])
for i := 0; i < s[1]; i++ {
res[i] = find.Find(s[0] + i)
}
results <- res
}
}
numWorkers := 16
jobsCh := make(chan [2]int, numWorkers)
resultsCh := make(chan []int, len(ranges))
for w := 0; w < numWorkers; w++ {
go worker(w, jobsCh, resultsCh)
}
log("started workers", numWorkers)
go func() {
for i, s := range ranges {
log("job", i, "send", s)
jobsCh <- s
}
close(jobsCh)
}()
results := 0
for _, r := range ranges {
results += r[1]
}
log("expecting results", results)
seedLocations := make([]int, 0, results)
expectResults := make([]struct{}, len(ranges))
for range expectResults {
r := <- resultsCh
seedLocations = append(seedLocations, r...)
}
return min(seedLocations...)
}
type Range struct {
src int
dest int
@ -179,6 +227,9 @@ func (f *Finder) Find(n int) int {
}
func min(arr ...int) int {
if len(arr) == 0 {
return 0
}
m := arr[0]
for _, a := range arr[1:] {
if m > a {
@ -187,3 +238,7 @@ func min(arr ...int) int {
}
return m
}
func log(v ...any) {
fmt.Fprintln(os.Stderr, v...)
}

View File

@ -22,7 +22,7 @@ func TestExample(t *testing.T) {
minLocation, minRangeLocation := run(scan)
is.Equal(minLocation, 35)
is.Equal(minRangeLocation, 47)
is.Equal(minRangeLocation, 46)
}
func SkipTestSolution(t *testing.T) {