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
|
2024-01-02 09:18:14 +00:00
|
|
|
// it defines an open ended interval
|
2024-01-01 11:32:43 +00:00
|
|
|
func newBound(lower, upper int) bound {
|
2024-01-02 09:18:14 +00:00
|
|
|
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 {
|
2024-01-02 09:18:14 +00:00
|
|
|
q.enqueue(newBound(r.lower, start))
|
2024-01-01 11:32:43 +00:00
|
|
|
}
|
|
|
|
if r.upper > end {
|
2024-01-02 09:18:14 +00:00
|
|
|
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-01 11:32:43 +00:00
|
|
|
seedRanges = append(seedRanges, nextTransform(0, []bound{newBound(seeds[i], seeds[i]+seeds[i+1]-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
|
|
|
}
|