aoc2023/day-5/two.go

90 lines
1.8 KiB
Go
Raw Permalink Normal View History

2023-12-06 04:01:17 +00:00
package main
import (
"math"
"sync"
)
2024-01-01 11:32:43 +00:00
var wg sync.WaitGroup
2024-01-02 06:58:03 +00:00
var mu sync.Mutex
2023-12-06 04:01:17 +00:00
2024-01-01 11:32:43 +00:00
const UNLIMITED = -1
2023-12-06 04:01:17 +00:00
2024-01-01 11:32:43 +00:00
// bound represents the lower and upper limits of a single range
2023-12-06 04:01:17 +00:00
type bound struct {
2024-01-01 11:32:43 +00:00
lower, upper int
2023-12-06 04:01:17 +00:00
}
2024-01-01 11:32:43 +00:00
// newBound returns a bound type
// it defines an open ended interval
2024-01-01 11:32:43 +00:00
func newBound(lower, upper int) bound {
return bound{lower: lower, upper: upper - 1}
2024-01-01 11:32:43 +00:00
}
2023-12-06 04:01:17 +00:00
2024-01-01 11:32:43 +00:00
// nextTransform recursively calculates each new set of seed ranges for each set of data in dataMap
func nextTransform(i int, in []bound) []bound {
if i == len(identifiers) {
return in
2023-12-06 04:01:17 +00:00
}
2024-01-01 11:32:43 +00:00
q := newQueue(UNLIMITED, in)
in = make([]bound, 0)
for !q.isEmpty() {
r := q.dequeue()
hasOverlap := func() bool {
for _, data := range dataMap[identifiers[i]] {
start := max(r.lower, data.source)
end := min(r.upper, data.source+data.offset)
if isOverlapping(start, end) {
// add new seed range
in = append(in, newBound(data.transform(start, end)))
// append unmatched portions of seed range back into queue
if start > r.lower {
q.enqueue(newBound(r.lower, start))
2024-01-01 11:32:43 +00:00
}
if r.upper > end {
q.enqueue(newBound(end, r.upper))
2024-01-01 11:32:43 +00:00
}
return true
}
}
return false
}()
2023-12-06 04:01:17 +00:00
2024-01-01 11:32:43 +00:00
// there was no overlap, add the seed range as is
if !hasOverlap {
in = append(in, r)
2023-12-06 04:01:17 +00:00
}
2024-01-01 11:32:43 +00:00
}
2023-12-06 04:01:17 +00:00
2024-01-01 11:32:43 +00:00
return nextTransform(i+1, in)
}
// two returns the lowest location for any seed in seedRanges
func two(lines []string) int {
var seedRanges = []bound{}
for i := 0; i < len(seeds); i += 2 {
2023-12-06 04:01:17 +00:00
wg.Add(1)
2024-01-01 11:32:43 +00:00
go func(i int) {
2023-12-06 04:01:17 +00:00
defer wg.Done()
2024-01-02 06:58:03 +00:00
mu.Lock()
2024-01-02 09:20:51 +00:00
seedRanges = append(seedRanges, nextTransform(0, []bound{newBound(seeds[i], seeds[i]+seeds[i+1])})...)
2024-01-02 06:58:03 +00:00
mu.Unlock()
2024-01-01 11:32:43 +00:00
}(i)
2023-12-06 04:01:17 +00:00
}
wg.Wait()
2024-01-01 11:32:43 +00:00
lowest := math.MaxInt
for _, r := range seedRanges {
if r.lower < lowest {
lowest = r.lower
}
}
return lowest
2023-12-06 04:01:17 +00:00
}