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

View File

@ -40,9 +40,20 @@ func TestCombination_Best(t *testing.T) {
{Point: 5, Color: 3}, {Point: 5, Color: 3},
{Point: 6, Color: 4}, {Point: 6, Color: 4},
{Point: 7, Color: 1}, {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) fmt.Println("best:", name)
for _, item := range result { for _, item := range result {
fmt.Println(item) fmt.Println(item)

View File

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

View File

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

View File

@ -3,6 +3,7 @@ package storage_test
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/kercylan98/minotaur/utils/slice"
"github.com/kercylan98/minotaur/utils/storage" "github.com/kercylan98/minotaur/utils/storage"
"testing" "testing"
) )
@ -43,3 +44,13 @@ func TestData_Struct(t *testing.T) {
fmt.Println(string(bytes)) 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))
}