in internal/utils.go [58:115]
func PackingIterator[T any](itr iter.Seq[T], targetWeight int64, lookback int, weightFunc func(T) int64, largestBinFirst bool) iter.Seq[[]T] {
bins := make([]Bin[T], 0)
findBin := func(weight int64) *Bin[T] {
for i := range bins {
if bins[i].CanAdd(weight) {
return &bins[i]
}
}
return nil
}
removeBin := func() Bin[T] {
if largestBinFirst {
maxBin := slices.MaxFunc(bins, func(a, b Bin[T]) int {
return cmp.Compare(a.Weight(), b.Weight())
})
i := slices.IndexFunc(bins, func(e Bin[T]) bool {
return e.Weight() == maxBin.Weight()
})
bins = slices.Delete(bins, i, i+1)
return maxBin
}
var out Bin[T]
out, bins = bins[0], bins[1:]
return out
}
return func(yield func([]T) bool) {
for item := range itr {
w := weightFunc(item)
bin := findBin(w)
if bin != nil {
bin.Add(item, w)
} else {
bin := Bin[T]{targetWeight: targetWeight}
bin.Add(item, w)
bins = append(bins, bin)
if len(bins) > lookback {
if !yield(removeBin().items) {
return
}
}
}
}
for len(bins) > 0 {
if !yield(removeBin().items) {
return
}
}
}
}