267 lines
8.1 KiB
Go
267 lines
8.1 KiB
Go
package combination
|
||
|
||
import (
|
||
"github.com/kercylan98/minotaur/utils/generic"
|
||
"github.com/kercylan98/minotaur/utils/maths"
|
||
)
|
||
|
||
type ValidatorOption[T Item] func(validator *Validator[T])
|
||
|
||
// WithValidatorHandle 通过特定的验证函数对组合进行验证
|
||
func WithValidatorHandle[T Item](handle func(items []T) bool) ValidatorOption[T] {
|
||
return func(validator *Validator[T]) {
|
||
validator.vh = append(validator.vh, handle)
|
||
}
|
||
}
|
||
|
||
// WithValidatorHandleLength 校验组合的长度是否符合要求
|
||
func WithValidatorHandleLength[T Item](length int) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
return len(items) == length
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleLengthRange 校验组合的长度是否在指定的范围内
|
||
func WithValidatorHandleLengthRange[T Item](min, max int) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
return len(items) >= min && len(items) <= max
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleLengthMin 校验组合的长度是否大于等于指定的最小值
|
||
func WithValidatorHandleLengthMin[T Item](min int) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
return len(items) >= min
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleLengthMax 校验组合的长度是否小于等于指定的最大值
|
||
func WithValidatorHandleLengthMax[T Item](max int) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
return len(items) <= max
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleLengthNot 校验组合的长度是否不等于指定的值
|
||
func WithValidatorHandleLengthNot[T Item](length int) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
return len(items) != length
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleTypeLength 校验组合成员类型数量是否为指定的值
|
||
func WithValidatorHandleTypeLength[T Item, E generic.Ordered](length int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]bool)
|
||
for _, item := range items {
|
||
types[getType(item)] = true
|
||
if len(types) > length {
|
||
return false
|
||
}
|
||
}
|
||
return len(items) == length
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleTypeLengthRange 校验组合成员类型数量是否在指定的范围内
|
||
func WithValidatorHandleTypeLengthRange[T Item, E generic.Ordered](min, max int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]bool)
|
||
for _, item := range items {
|
||
types[getType(item)] = true
|
||
if len(types) > max {
|
||
return false
|
||
}
|
||
}
|
||
return len(types) >= min && len(types) <= max
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleTypeLengthMin 校验组合成员类型数量是否大于等于指定的最小值
|
||
func WithValidatorHandleTypeLengthMin[T Item, E generic.Ordered](min int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]bool)
|
||
for _, item := range items {
|
||
types[getType(item)] = true
|
||
if len(types) > min {
|
||
return false
|
||
}
|
||
}
|
||
return len(types) >= min
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleTypeLengthMax 校验组合成员类型数量是否小于等于指定的最大值
|
||
func WithValidatorHandleTypeLengthMax[T Item, E generic.Ordered](max int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]bool)
|
||
for _, item := range items {
|
||
types[getType(item)] = true
|
||
if len(types) > max {
|
||
return false
|
||
}
|
||
}
|
||
return len(types) <= max
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleTypeLengthNot 校验组合成员类型数量是否不等于指定的值
|
||
func WithValidatorHandleTypeLengthNot[T Item, E generic.Ordered](length int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]bool)
|
||
for _, item := range items {
|
||
types[getType(item)] = true
|
||
if len(types) > length {
|
||
return false
|
||
}
|
||
}
|
||
return len(types) != length
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleContinuous 校验组合成员是否连续
|
||
func WithValidatorHandleContinuous[T Item, Index generic.Integer](getIndex func(item T) Index) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
index := make([]Index, len(items))
|
||
for i, item := range items {
|
||
index[i] = getIndex(item)
|
||
}
|
||
return maths.IsContinuityWithSort(index)
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleContinuousNot 校验组合成员是否不连续
|
||
func WithValidatorHandleContinuousNot[T Item, Index generic.Integer](getIndex func(item T) Index) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
index := make([]Index, len(items))
|
||
for i, item := range items {
|
||
index[i] = getIndex(item)
|
||
}
|
||
return !maths.IsContinuityWithSort(index)
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleGroupContinuous 校验组合成员是否能够按类型分组并且连续
|
||
func WithValidatorHandleGroupContinuous[T Item, E generic.Ordered, Index generic.Integer](getType func(item T) E, getIndex func(item T) Index) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]int)
|
||
var index = make([]Index, len(types))
|
||
for _, item := range items {
|
||
e := getType(item)
|
||
types[e]++
|
||
if types[e] == 1 {
|
||
index = append(index, getIndex(item))
|
||
}
|
||
}
|
||
var n = -1
|
||
for _, i := range types {
|
||
if n == -1 {
|
||
n = i
|
||
} else if n != i {
|
||
return false
|
||
}
|
||
}
|
||
return maths.IsContinuityWithSort(index)
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleGroupContinuousN 校验组合成员是否能够按分组为 n 组类型并且连续
|
||
func WithValidatorHandleGroupContinuousN[T Item, E generic.Ordered, Index generic.Integer](n int, getType func(item T) E, getIndex func(item T) Index) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
var types = make(map[E]int)
|
||
var index = make([]Index, len(types))
|
||
for _, item := range items {
|
||
e := getType(item)
|
||
types[e]++
|
||
if types[e] == 1 {
|
||
index = append(index, getIndex(item))
|
||
}
|
||
}
|
||
if n != len(types) {
|
||
return false
|
||
}
|
||
var n = -1
|
||
for _, i := range types {
|
||
if n == -1 {
|
||
n = i
|
||
} else if n != i {
|
||
return false
|
||
}
|
||
}
|
||
return maths.IsContinuityWithSort(index)
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleNCarryM 校验组合成员是否匹配 N 携带相同的 M 的组合
|
||
// - n: 组合中元素的数量,表示需要匹配的组合数量,n 的类型需要全部相同
|
||
// - m: 组合中元素的数量,表示需要匹配的组合数量,m 的类型需要全部相同
|
||
// - getType: 用于获取组合中元素的类型,用于判断是否相同
|
||
func WithValidatorHandleNCarryM[T Item, E generic.Ordered](n, m int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
if len(items) != n+m {
|
||
return false // 总数量不符合 n + m
|
||
}
|
||
|
||
typeCount := make(map[E]int)
|
||
for _, item := range items {
|
||
t := getType(item)
|
||
typeCount[t]++
|
||
}
|
||
|
||
if len(typeCount) != 2 {
|
||
return false
|
||
}
|
||
|
||
foundN := false
|
||
foundM := false
|
||
for _, count := range typeCount {
|
||
if count == n {
|
||
foundN = true
|
||
} else if count == m {
|
||
foundM = true
|
||
}
|
||
}
|
||
|
||
return foundN && foundM
|
||
})
|
||
}
|
||
|
||
// WithValidatorHandleNCarryIndependentM 校验组合成员是否匹配 N 携带独立的 M 的组合
|
||
// - n: 组合中元素的数量,表示需要匹配的组合数量,n 的类型需要全部相同
|
||
// - m: 组合中元素的数量,表示需要匹配的组合数量,m 的类型无需全部相同
|
||
// - getType: 用于获取组合中元素的类型,用于判断是否相同
|
||
func WithValidatorHandleNCarryIndependentM[T Item, E generic.Ordered](n, m int, getType func(item T) E) ValidatorOption[T] {
|
||
return WithValidatorHandle[T](func(items []T) bool {
|
||
if len(items) != n+m {
|
||
return false // 总数量不符合 n + m
|
||
}
|
||
|
||
typeCount := make(map[E]int)
|
||
for _, item := range items {
|
||
t := getType(item)
|
||
typeCount[t]++
|
||
}
|
||
|
||
// 检查是否有 n 个相同类型的元素
|
||
foundN := false
|
||
for _, count := range typeCount {
|
||
if count == n {
|
||
foundN = true
|
||
break
|
||
}
|
||
}
|
||
|
||
if !foundN {
|
||
return false // 没有找到 n 个相同类型的元素
|
||
}
|
||
|
||
// 检查剩余的元素数量是否为 m
|
||
remaining := len(items) - n
|
||
if remaining != m {
|
||
return false // 剩余元素数量不为 m
|
||
}
|
||
|
||
return true // 符合 N 带 M 的条件
|
||
})
|
||
}
|