perf: 优化 combination 包 NCarryM 性能

This commit is contained in:
kercylan98 2023-07-29 16:01:09 +08:00
parent 57936b2b25
commit abd1db5586
5 changed files with 51 additions and 19 deletions

View File

@ -88,6 +88,9 @@ func (slf *Combination[T]) Best(items []T) (name string, result []T) {
for _, n := range slf.priority {
matcher := slf.matchers[n]
matcherBest := matcher.Best(items)
if len(matcherBest) == 0 {
continue
}
if score := matcher.evaluate(matcherBest); score > best || best == -1 {
best = score
name = n
@ -103,6 +106,9 @@ func (slf *Combination[T]) Worst(items []T) (name string, result []T) {
for _, n := range slf.priority {
matcher := slf.matchers[n]
matcherWorst := matcher.Worst(items)
if len(matcherWorst) == 0 {
continue
}
if score := matcher.evaluate(matcherWorst); score < worst || worst == -1 {
worst = score
name = n

View File

@ -40,9 +40,20 @@ func TestCombination_Best(t *testing.T) {
{Point: 5, Color: 3},
{Point: 6, Color: 4},
{Point: 7, Color: 1},
{Point: 8, Color: 2},
{Point: 9, Color: 3},
{Point: 10, Color: 4},
{Point: 11, Color: 1},
{Point: 12, Color: 2},
{Point: 13, Color: 3},
{Point: 10, Color: 3},
{Point: 11, Color: 2},
{Point: 12, Color: 1},
{Point: 13, Color: 4},
{Point: 10, Color: 2},
}
name, result := combine.Best(cards)
name, result := combine.Worst(cards)
fmt.Println("best:", name)
for _, item := range result {
fmt.Println(item)

View File

@ -147,18 +147,24 @@ func WithMatcherNCarryM[T Item, E generic.Ordered](n, m int, getType func(item T
if len(group) != n {
continue
}
ms := slice.Combinations(slice.SubWithCheck(items, group, func(a, b T) bool { return reflect.DeepEqual(a, b) }))
for i := 0; i < len(ms); i++ {
ts := make(map[E][]T)
for _, t := range ms[i] {
tt := getType(t)
ts[tt] = append(ts[tt], t)
}
for _, cs := range ts {
if len(cs) == m {
combinations = append(combinations, slice.Merge(group, cs))
other := slice.SubWithCheck(items, group, func(a, b T) bool { return reflect.DeepEqual(a, b) })
ms := slice.LimitedCombinations(other, m, m)
for _, otherGroup := range ms {
var t E
var init = true
var same = true
for _, item := range otherGroup {
if init {
init = false
t = getType(item)
} else if getType(item) != t {
same = false
break
}
}
if same {
combinations = append(combinations, slice.Merge(group, otherGroup))
}
}
}
return combinations
@ -185,12 +191,9 @@ func WithMatcherNCarryIndependentM[T Item, E generic.Ordered](n, m int, getType
if len(group) != n {
continue
}
ms := slice.Combinations(slice.SubWithCheck(items, group, func(a, b T) bool { return reflect.DeepEqual(a, b) }))
for i := 0; i < len(ms); i++ {
is := ms[i]
if len(is) == m {
combinations = append(combinations, slice.Merge(group, is))
}
ms := slice.LimitedCombinations(slice.SubWithCheck(items, group, func(a, b T) bool { return reflect.DeepEqual(a, b) }), m, m)
for _, otherGroup := range ms {
combinations = append(combinations, slice.Merge(group, otherGroup))
}
}
return combinations

View File

@ -1,6 +1,7 @@
package slice
import (
"fmt"
"math/rand"
"reflect"
)
@ -223,10 +224,10 @@ func Combinations[T any](a []T) [][]T {
n := len(a)
// 去除重复元素,保留唯一元素
uniqueSet := make(map[uintptr]bool)
uniqueSet := make(map[string]bool)
uniqueSlice := make([]T, 0, n)
for _, val := range a {
ptr := reflect.ValueOf(val).Pointer()
ptr := fmt.Sprintf("%p", val)
if !uniqueSet[ptr] {
uniqueSet[ptr] = true
uniqueSlice = append(uniqueSlice, val)

View File

@ -3,6 +3,7 @@ package storage_test
import (
"encoding/json"
"fmt"
"github.com/kercylan98/minotaur/utils/slice"
"github.com/kercylan98/minotaur/utils/storage"
"testing"
)
@ -43,3 +44,13 @@ func TestData_Struct(t *testing.T) {
fmt.Println(string(bytes))
}
func TestData_Handle(t *testing.T) {
var is []int
for i := 1; i <= 23; i++ {
is = append(is, i)
}
res := slice.LimitedCombinations(is, 5, 5)
fmt.Println("Count:", len(res))
}