Compare commits

...

10 Commits

Author SHA1 Message Date
Huangzj 9ba69e98d5 feat(Go-Tool):2021/06/16 新增一个数拆分成N个数且N个数相加和等于这个数工具、测试方法 2021-06-16 11:57:20 +08:00
Huangzj 092ab58276 feat(Go-Tool):2021/03/26: 新增全排列的递归实现、字典序实现、递增进制位实现、递减进制位实现 2021-03-26 09:13:34 +08:00
Huangzj 00ada130fa feat(Go-Tool):2021/03/18:新增超过半数数字系列算法题,新增出现次数不同的数字系列算法题 2021-03-18 15:55:40 +08:00
Huangzj 8dbfebe5be feat(Go-Tool):2021/03/14: 新增Manacher算法,求最长回文串 2021-03-14 19:34:22 +08:00
Huangzj 1aa86ce5b8 更新readme 2021-03-11 15:06:26 +08:00
Huangzj ed71f9b607 feat(Go-Tool):2021/03/11: 新增Kr、Shift and/or字符串匹配算法 2021-03-11 15:04:41 +08:00
Huangzj 351df675bd feat(Go-Tool):优化Sunday代码 2021-03-04 13:49:03 +08:00
Huangzj dc5d924a2c feat(Go-Tool):
2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
            2021/03/02: 修复Rand包随机获取方法
2021-03-02 13:33:07 +08:00
Huangzj 74dd19c675 feat(Go-Tool):
2021/02/23:删除linq包使用示例,修改二进制工具与单测类,修改lomuto划分,修改前缀树与单测类,修改时间比较工具
2021-02-23 10:57:41 +08:00
Huangzj 39cee0ce6a feat(Go-Tool):2020/02/18:bitStore新增特殊档位获取方法,修改档位数目的参数标识 2021-02-18 11:17:19 +08:00
61 changed files with 2047 additions and 825 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

+11
View File
@@ -0,0 +1,11 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 16:46
* @Description
*/
package numberList
type i interface {
Doc() string
}
@@ -0,0 +1,48 @@
/*
* @Author : huangzj
* @Time : 2021/3/18 13:08
* @Description
*/
package NumberCount
type OnlyOneNumberOtherKObj struct{}
func (*OnlyOneNumberOtherKObj) Doc() string {
return `
给定一个整型数组 arr和一个大于1的整数k。已知 arr中只有1个数出现了1次,其他的数都出现了k次,请返回只出现了1次的数。
【要求】
时间复杂度为 O(N),额外空间复杂度为 O(1)。
`
}
func OnlyOneNumberOtherK(numList []int, k int) int {
bitList := make([]int, 32)
for _, num := range numList {
//把每个数字转换成二进制
store := make([]int, 32)
for i := 0; num != 0; i++ {
store[i] = num % k
num = num / k
}
for j := 0; j < 32; j++ {
//不进位加法
bitList[j] = (store[j] + bitList[j]) % k
}
}
//k进制转换回十进制
power := 1 //k的次方值
result := 0 //只出现一次的数字
for i, bit := range bitList {
power = 1
for j := 0; j < i; j++ {
power = power * k
}
result = result + power*bit
}
return result
}
@@ -0,0 +1,25 @@
/*
* @Author : huangzj
* @Time : 2021/3/18 13:09
* @Description
*/
package NumberCount
import (
"fmt"
"testing"
)
func TestOnlyOneNumberOtherK(t *testing.T) {
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 2, 3, 4}, 2)) //1
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 2, 3, 4, 2, 3, 4}, 3)) //1
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 3, 4, 4, 5, 6, 2, 2, 3, 5, 5, 3, 4, 6, 6}, 3)) //1
fmt.Println(OnlyOneNumberOtherK([]int{1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, 10)) //1
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 3000, 4, 2, 3, 4}, 2)) //3000
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 4, 2, 9999, 3, 4, 2, 3, 4}, 3)) //9999
fmt.Println(OnlyOneNumberOtherK([]int{2, 3, 4, 4, 5, 6, 321, 2, 2, 3, 5, 5, 3, 4, 6, 6}, 3)) //321
fmt.Println(OnlyOneNumberOtherK([]int{2, 2, 2, 2, 2, 2, 2, 5891, 2, 2, 2}, 10)) //5891
}
@@ -0,0 +1,53 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 21:53
* @Description
*/
package NumberCount
type OnlyOneNumberOtherThreeObj struct{}
func (*OnlyOneNumberOtherThreeObj) Doc() string {
return `
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
要求:线性时间复杂度。 不使用额外空间来实现
`
}
func OnlyOneNumberOtherThree1(numList []int) int {
bitList := make([]int, 32)
for _, num := range numList {
for i := 0; i < 32; i++ {
bitList[i] += (num >> i) & 1
}
}
res := 0
for i := 0; i < 32; i++ {
if bitList[i]%3 != 0 {
res += 1 << i
}
}
return res
}
//通过二进制的方式,本质上就是要构造一个相应的回路,即出现num的次数分别从1~3应该是 01 -> 10 -> 00 ...
func OnlyOneNumberOtherThree2(numList []int) int {
var a uint
var b uint
//第一次出现num计算的结果 a = num ,b = 0
//第二次出现num计算的结果 a = 0 ,b = num
//第三次出现num计算的结果 a = num ,b = 0
//因此直接返回a即可
for _, num := range numList {
a = a ^ uint(num)&(^b)
b = b ^ uint(num)&(^a)
}
return int(a)
}
@@ -0,0 +1,26 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 21:55
* @Description
*/
package NumberCount
import (
"fmt"
"testing"
)
func TestOnlyOneNumberOtherThree1(t *testing.T) {
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 1, 1, 2, 2, 2, 3, 3, 3, 4})) //4
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 4})) //4
fmt.Println(OnlyOneNumberOtherThree1([]int{1, 15, 23, 67, 15, 67, 67, 23, 23, 14, 15, 1, 1})) //14
fmt.Println(OnlyOneNumberOtherThree1([]int{100, 200, 300, 4, 6, 100, 100, 6, 6, 4, 200, 300, 200, 300, 5, 4})) //5
}
func TestOnlyOneNumberOtherThree2(t *testing.T) {
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 1, 1, 2, 2, 2, 3, 3, 3, 4})) //4
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 4})) //4
fmt.Println(OnlyOneNumberOtherThree2([]int{1, 15, 23, 67, 15, 67, 67, 23, 23, 14, 15, 1, 1})) //14
fmt.Println(OnlyOneNumberOtherThree2([]int{100, 200, 300, 4, 6, 100, 100, 6, 6, 4, 200, 300, 200, 300, 5, 4})) //5
}
@@ -0,0 +1,25 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 17:51
* @Description
*/
package NumberCount
type OnlyOneNumberShowOnceObj struct{}
func (*OnlyOneNumberShowOnceObj) Doc() string {
return `
一个整型数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)。
`
}
//通过异或解决
func OnlyOneNumberShowOnce(numberList []int) int {
result := 0
for _, num := range numberList {
result ^= num
}
return result
}
@@ -0,0 +1,19 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 17:52
* @Description
*/
package NumberCount
import (
"fmt"
"testing"
)
func TestOnlyOneNumberShowOnce(t *testing.T) {
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4})) //1
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4, 1, 5})) //5
fmt.Println(OnlyOneNumberShowOnce([]int{1, 2, 3, 2, 3, 4, 4, 1, 10})) //10
fmt.Println(OnlyOneNumberShowOnce([]int{2, 2, 2, 2, 1, 3, 3, 3, 3})) //1
}
@@ -0,0 +1,58 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 18:01
* @Description
*/
package NumberCount
type OnlyTwoNumberShowOnceObj struct {
}
func (*OnlyTwoNumberShowOnceObj) Doc() string {
return `
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1)。
`
}
func OnlyTwoNumberShowOnce(numList []int) (int, int) {
if len(numList) < 2 {
panic("数组长度不能小于两个")
}
result := 0
//先进行异或,得到异或的结果
for _, num := range numList {
result = result ^ num
}
//找到异或后为1的位置
pos := 0
for ; pos < 32; pos++ {
if ((result >> pos) & 1) == 1 {
break
}
}
firstList := make([]int, 0)
secondList := make([]int, 0)
//根据异或位的结果,把数组分成两组
for _, num := range numList {
if ((num >> pos) & 1) == 1 {
firstList = append(firstList, num)
} else {
secondList = append(secondList, num)
}
}
first := 0
for _, num := range firstList {
first ^= num
}
second := 0
for _, num := range secondList {
second ^= num
}
return first, second
}
@@ -0,0 +1,19 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 18:02
* @Description
*/
package NumberCount
import (
"fmt"
"testing"
)
func TestOnlyTwoNumberShowOnce(t *testing.T) {
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7})) //1,7
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7, 8, 9, 0, 19, 19, 0, 8, 9})) //1,7
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 1, 7, 5, 4, 3, 2})) //1,7
fmt.Println(OnlyTwoNumberShowOnce([]int{2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 7, 1, 100})) //1,100
}
@@ -0,0 +1,48 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 15:45
* @Description
*/
package NumberMoreThan
type NumberMoreThanHalfObj struct{}
func (n *NumberMoreThanHalfObj) Doc() string {
return `
题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
要求:时间复杂度O(N),空间复杂度O(1)
`
}
func NumberMoreThanHalf(numList []int) int {
var number, count int
for _, j := range numList {
if number == j {
count++
} else if number != j && count <= 1 {
number = j
} else {
//number !=j && count >1
count--
}
}
//最后验证,确保一定超过
countValid := 0
for _, j := range numList {
if j == number {
countValid++
}
}
if countValid <= len(numList)/2 {
return -1
}
return number
}
@@ -0,0 +1,20 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 16:23
* @Description
*/
package NumberMoreThan
import (
"fmt"
"testing"
)
func TestNumberMoreThanHalf(t *testing.T) {
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3})) //-1
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 1, 1})) //1
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 1})) //-1
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 2, 3, 2, 3, 3})) //-1
fmt.Println(NumberMoreThanHalf([]int{1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1})) //1
}
@@ -0,0 +1,68 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 16:46
* @Description
*/
package NumberMoreThan
type NumberMoreThanKObj struct{}
func (*NumberMoreThanKObj) Doc() string {
return `
给定一个整型数组arr(数组长度为N) 与一个整数k,打印所有出现次数大于 N/K 的数。如果没有这样的数,返回-1。
要求:时间复杂度为O(N*K),额外空间复杂度为O(K)。
`
}
func NumberMoreThanK(numList []int, k int) []int {
//小于2的情况是肯定不会超过.
if k < 2 {
return []int{}
}
//用来保存数字与其出现次数
numMap := make(map[int]int, 0)
for _, num := range numList {
//如果不存在则数值设置为1
if _, ok := numMap[num]; !ok {
numMap[num] = 1
} else {
//存在则出现次数+1
numMap[num] = numMap[num] + 1
}
//当容器的大小为k
if len(numMap) == k {
for key, value := range numMap {
//个数正好等于1的要删掉,因为本次减一之后,就等于0了
if value == 1 {
delete(numMap, key)
}
}
continue
}
}
//map的key是可能出现次数超过N/k的数
//这里主要是为了拿到key
for key := range numMap {
numMap[key] = 0
}
//重新计算对应数字的出现次数
for _, num := range numList {
if _, ok := numMap[num]; ok {
numMap[num]++
}
}
//出现次数超过k次的判断
result := make([]int, 0)
for key, value := range numMap {
if value > len(numList)/k {
result = append(result, key)
}
}
return result
}
@@ -0,0 +1,19 @@
/*
* @Author : huangzj
* @Time : 2021/3/16 16:59
* @Description
*/
package NumberMoreThan
import (
"fmt"
"testing"
)
func TestNumberMoreThanK(t *testing.T) {
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}, 3)) //1
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3, 1}, 4)) //1,2,3
fmt.Println(NumberMoreThanK([]int{1, 2, 3, 1, 2, 3, 1, 2, 3}, 2)) //
fmt.Println(NumberMoreThanK([]int{1, 2, 3}, 2)) //
}
+25 -3
View File
@@ -1,3 +1,6 @@
#我的公众号二维码
![](.readme_images/B5F8E89A-CE33-4a78-A461-E9014B10A3D9.png)
# 作用 # 作用
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本工程仅供个人学习记录,刚开始学习go(之前是java),本工程积累一些反射的用法。后期查询更加快捷 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本工程仅供个人学习记录,刚开始学习go(之前是java),本工程积累一些反射的用法。后期查询更加快捷
@@ -60,7 +63,7 @@
2020/11/25:完善linq包使用示例 2020/11/25:完善linq包使用示例
2020/12/7 :更新bit位操作工作 BitTool 2020/12/7 : 更新bit位操作工作 BitTool
2020/12/15:添加前缀树工具,实现前缀搜索和字符串搜索功能 2020/12/15:添加前缀树工具,实现前缀搜索和字符串搜索功能
@@ -68,7 +71,19 @@
2020/12/31:新增项目案例(角色技能树) 2020/12/31:新增项目案例(角色技能树)
2021/2/5: 新增二分查找区间内数值方法 2021/02/05: 新增二分查找区间内数值方法
2021/03/02: 新增字符串匹配 暴力匹配、KMP匹配、SunDay匹配算法
2021/03/11: 新增Kr、Shift and/or字符串匹配算法
2021/03/14: 新增Manacher算法,求最长回文串
2021/03/18:新增超过半数数字系列算法题,新增出现次数不同的数字系列算法题
2021/03/26: 新增全排列的递归实现、字典序实现、递增进制位实现、递减进制位实现
2021/06/16 新增一个数拆分成N个数且N个数相加和等于这个数工具、测试方法
# 修复日志 # 修复日志
2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组) 2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组)
@@ -79,7 +94,13 @@
2020/12/31:删除源码学习部分,挪到Go-Study工程 2020/12/31:删除源码学习部分,挪到Go-Study工程
2021/1/4 reflectM包添加indirect处理指针和非指针,获取type、value 2021/01/04reflectM包添加indirect处理指针和非指针,获取type、value
2021/02/18bitStore新增特殊档位获取方法,修改档位数目的参数标识
2021/02/23: 删除linq包使用示例,修改二进制工具与单测类,修改lomuto划分,修改前缀树与单测类,修改时间比较工具
2021/03/02: 修复Rand包随机获取方法
# mod vendor模式加载包 # mod vendor模式加载包
通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到 通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到
@@ -94,3 +115,4 @@
- 通过 go mod vendor 切换到vendor管理 - 通过 go mod vendor 切换到vendor管理
- 在文件中import引用对应的路径 - 在文件中import引用对应的路径
- vendor加载对应的包 - vendor加载对应的包
+56
View File
@@ -0,0 +1,56 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 15:29
* @Description
*/
package FullPermutation
import (
sort2 "Go-Tool/util/sort"
)
//字典序获取全排列
func (per *Permutation) DictionaryOrder(b []byte) {
//先排序
sort2.QuickSortByte(b, 0, len(b)-1)
for {
bef := 0
afr := 0
result := make([]byte, len(b))
copy(result, b)
per.bytes = append(per.bytes, result)
//从右往左找到第一个左边比右边小的数字
for bef = len(b) - 2; ; bef-- {
if bef < 0 {
return
}
if b[bef] < b[bef+1] {
break
}
}
//知道q的位置之后
//从q开始向右边查找比位置q的数字大的第一个数字的位置
for afr = len(b) - 1; afr > 0; afr-- {
if b[afr] > b[bef] {
break
}
}
//交换两个数字
b[bef], b[afr] = b[afr], b[bef]
//把后面的数字进行转置成递增顺序
b = per.Reverse(b, bef+1, len(b)-1)
}
}
func (per *Permutation) Reverse(b []byte, start, end int) []byte {
for start <= end {
b[start], b[end] = b[end], b[start]
start++
end--
}
return b
}
@@ -0,0 +1,52 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 15:29
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestDictionaryOrder(t *testing.T) {
p := NewPermutation()
p.DictionaryOrder([]byte("1234"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("12345"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("abcde"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("abcdea"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
}
func TestPermutation_Reverse(t *testing.T) {
p := NewPermutation()
fmt.Println(p.Reverse([]byte{1, 2, 3, 4}, 0, 3))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5}, 0, 4))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6}, 0, 5))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6, 7}, 0, 6))
}
+71
View File
@@ -0,0 +1,71 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 17:06
* @Description
*/
package FullPermutation
func DigitDecreases(b []int) [][]int {
result := make([][]int, 0)
bit := make([]int, len(b)-1)
sum := 1
//计算中的结果数,阶乘
for i := 1; i <= len(b); i++ {
sum = sum * i
}
for i := 0; i < sum; i++ {
result = append(result, getRangeBySpace1(b, bit))
bit = decreaseBit(bit)
}
return result
}
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
//origin 原始数组
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
func getRangeBySpace1(origin []int, increaseBit []int) []int {
permutation := make([]int, len(origin))
flag := make(map[int]bool, 0)
//排列数组从左往右,即从大到小
for i := 0; i < len(origin)-1; i++ {
p := increaseBit[i] //从右到左,对应数字应该填充的位置
j := len(origin) - 1 //该数字在本次排列的位置
for ; ; j-- {
//该位置未被填充
if !flag[j] {
p--
}
//找到对应位置需要推出循环
if p < 0 {
flag[j] = true
break
}
}
permutation[j] = origin[i]
}
for i := 0; i < len(origin); i++ {
if !flag[i] {
permutation[i] = origin[len(origin)-1]
}
}
return permutation
}
//递减进制位
//每次加一,计算新的数组结果
func decreaseBit(bit []int) []int {
//数组下标从小到大,进制位从大到小
for i := 0; i < len(bit); i++ {
if bit[i]+1 >= len(bit)+1-i {
bit[i] = (bit[i] + 1) % (len(bit) + 1 - i)
} else {
bit[i] += 1
break
}
}
return bit
}
@@ -0,0 +1,59 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 19:53
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestDecreaseBit(t *testing.T) {
bit := []int{0, 0}
for i := 0; i < 6; i++ {
fmt.Println(bit)
bit = decreaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0}
for i := 0; i < 24; i++ {
fmt.Println(bit)
bit = decreaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0, 0}
for i := 0; i < 120; i++ {
fmt.Print(bit)
bit = decreaseBit(bit)
}
}
func TestGetRangeBySpace1(t *testing.T) {
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{4, 3, 2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{3, 0, 0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{1, 3, 2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5, 6, 7}, []int{3, 4, 2, 2, 2, 1}))
}
func TestDigitDecrease(t *testing.T) {
fmt.Println(DigitDecreases([]int{1, 2, 3}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 67}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 99, 18213}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 78321, 2321, 432}))
}
+71
View File
@@ -0,0 +1,71 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 17:05
* @Description
*/
package FullPermutation
func DigitIncrease(b []int) [][]int {
result := make([][]int, 0)
bit := make([]int, len(b)-1)
sum := 1
//计算中的结果数,阶乘
for i := 1; i <= len(b); i++ {
sum = sum * i
}
for i := 0; i < sum; i++ {
result = append(result, getRangeBySpace(b, bit))
bit = increaseBit(bit)
}
return result
}
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
//origin 原始数组
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
func getRangeBySpace(origin []int, increaseBit []int) []int {
permutation := make([]int, len(origin))
flag := make(map[int]bool, 0)
//排列数组从左往右,即从大到小
for i := len(origin) - 1; i > 0; i-- {
p := increaseBit[i-1] //从右到左,对应数字应该填充的位置
j := len(origin) - 1 //该数字在本次排列的位置
//中介数计算从左到右,即从大到小
for ; ; j-- {
//该位置未被填充
if !flag[j] {
p--
}
//找到对应位置需要推出循环
if p < 0 {
flag[j] = true
break
}
}
permutation[j] = origin[i]
}
for i := 0; i < len(origin); i++ {
if !flag[i] {
permutation[i] = origin[0]
}
}
return permutation
}
//递增进制位
//根据递增进制位进行+1操作,返回递增的结果
func increaseBit(bit []int) []int {
//最开始是从二进制开始
for i, num := range bit {
if num+1 >= i+2 {
bit[i] = (num + 1) % (i + 2)
} else {
bit[i] = num + 1
break
}
}
return bit
}
@@ -0,0 +1,57 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 19:54
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestGetRangeBySpace(t *testing.T) {
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 0})) //123
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 0})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 1})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 1})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 2})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 2})) //321
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0})) //12345
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1})) //21354
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4})) //54321
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 3})) //12534
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 1})) //43251
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5, 6, 7}, []int{1, 2, 2, 2, 4, 3})) //3647521
}
func TestIncreaseBit(t *testing.T) {
bit := []int{0, 0}
for i := 0; i < 6; i++ {
fmt.Println(bit)
bit = increaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0, 0}
for i := 0; i < 120; i++ {
bit = increaseBit(bit)
fmt.Println(bit)
}
bit = []int{0, 0, 0}
for i := 0; i < 24; i++ {
bit = increaseBit(bit)
fmt.Println(bit)
}
}
func TestDigitIncrease(t *testing.T) {
fmt.Println(DigitIncrease([]int{1, 2, 3}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 67}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 99, 18213}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 78321, 2321, 432}))
}
+39
View File
@@ -0,0 +1,39 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 11:09
* @Description
*/
package FullPermutation
type Permutation struct {
bytes [][]byte
}
func NewPermutation() *Permutation {
return &Permutation{
bytes: [][]byte{},
}
}
func (per *Permutation) Recursion(b []byte, start int) {
//递归交换到最后一个位置结束
if start == len(b)-1 {
bCopy := make([]byte, len(b))
copy(bCopy, b)
per.bytes = append(per.bytes, bCopy)
}
for i := start; i < len(b); i++ {
//交换固定位置
b[i], b[start] = b[start], b[i]
//固定某一个数字位置,递归后面的其他数字
per.Recursion(b, start+1)
//还原固定位置,进行下一次操作
b[i], b[start] = b[start], b[i]
}
}
func (per *Permutation) Reset() {
per.bytes = [][]byte{}
}
+45
View File
@@ -0,0 +1,45 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 11:22
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestRecursion(t *testing.T) {
p := NewPermutation()
p.Recursion([]byte("123"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("12345"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("abcde"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("abcdea"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
}
+10 -7
View File
@@ -13,7 +13,8 @@ import (
//判断num的二进制表示某个位置是否为1 //判断num的二进制表示某个位置是否为1
func JudgeOneWithPosition(num int, position int) bool { func JudgeOneWithPosition(num int, position int) bool {
if position < 1 { if position < 1 {
panic(fmt.Sprintf("输入有误:Position不能小于1当前出入的Position为%d", position)) panic(fmt.Sprintf("输入有误:Position不能小于1"+
"当前出入的Position为%d", position))
} }
return num&(1<<uint(position-1)) != 0 return num&(1<<uint(position-1)) != 0
} }
@@ -30,16 +31,17 @@ func JudgeIfOdd(num int) bool {
//判断一个数的二进制形式是否只有一个位置为1,这个方法可以用来判断是不是2的n次方 //判断一个数的二进制形式是否只有一个位置为1,这个方法可以用来判断是不是2的n次方
func JudgeOnlyOneBitWithOne(num int) bool { func JudgeOnlyOneBitWithOne(num int) bool {
//解析:num & (num -1) 当num为2的N次方的时候, 2N次方 & (2N次方 - 1) ,因为做了最高位的右移(2N次方只有一个1,2N次方-1除了2N次方的那一个1的位置为0,其他都为1) if num == 0 {
//所以&的结果就是 0 ,而0 & 2N次方一定是0,所以如果结果是0,那么一定是2N次方,只有一个位置有1 return false
//那么 num & (num -1) 当num不是2的N次方的时候,他的结果原来有1的最高位置,一定为1,所以再和num进行 & 操作的时候,结果也一定是大于0,所以不止一个1 }
return num&(num&(num-1)) == 0 return num&(num-1) == 0
} }
//设置num的某一个位置为1,如果原来就是1的话,就不发生变化 //设置num的某一个位置为1,如果原来就是1的话,就不发生变化
func SetOneByPosition(num int, position int) int { func SetOneByPosition(num int, position int) int {
if position < 1 { if position < 1 {
panic(fmt.Sprintf("输入有误:Position不能小于1当前出入的Position为%d", position)) panic(fmt.Sprintf("输入有误:Position不能小于1"+
"当前出入的Position为%d", position))
} }
return num | (1 << uint(position-1)) return num | (1 << uint(position-1))
} }
@@ -52,7 +54,8 @@ func JudgeWithEqualSymbol(num1 int, num2 int) bool {
//设置某一个数num的二进制Position位为0 //设置某一个数num的二进制Position位为0
func SetZeroBuPosition(num int, position int) int { func SetZeroBuPosition(num int, position int) int {
if position < 1 { if position < 1 {
panic(fmt.Sprintf("输入有误:Position不能小于1当前出入的Position为%d", position)) panic(fmt.Sprintf("输入有误:Position不能小于1"+
"当前出入的Position为%d", position))
} }
return num &^ (1 << uint(position-1)) return num &^ (1 << uint(position-1))
} }
+3 -6
View File
@@ -102,12 +102,9 @@ func TestJudgeIfEven(t *testing.T) {
func TestJudgeOnlyOneBitWithOne(t *testing.T) { func TestJudgeOnlyOneBitWithOne(t *testing.T) {
fmt.Println("判断二进制表示是不是只有一个位为1") fmt.Println("判断二进制表示是不是只有一个位为1")
fmt.Println(JudgeOnlyOneBitWithOne(1)) for i := 0; i <= 32; i++ {
fmt.Println(JudgeOnlyOneBitWithOne(2)) fmt.Println(fmt.Sprintf("%d是不是2的n次方,结果为%v", i, JudgeOnlyOneBitWithOne(i)))
fmt.Println(JudgeOnlyOneBitWithOne(3)) }
fmt.Println(JudgeOnlyOneBitWithOne(4))
fmt.Println(JudgeOnlyOneBitWithOne(56))
fmt.Println(JudgeOnlyOneBitWithOne(64))
fmt.Println() fmt.Println()
fmt.Println(JudgeOnlyOneBitWithOne(-1)) fmt.Println(JudgeOnlyOneBitWithOne(-1))
fmt.Println(JudgeOnlyOneBitWithOne(-2)) fmt.Println(JudgeOnlyOneBitWithOne(-2))
+68 -13
View File
@@ -12,13 +12,13 @@ package bitStore
import "fmt" import "fmt"
const ( const (
bit = 32 bit = 32 //作为标识,没有实际作用
realBit = 31 realBit = 31 //真实参与计算的每个数字代表的档位数量
) )
type BitStore struct { type BitStore struct {
MaxGear int //存储的最大挡位 MaxGear int //存储的最大挡位
GearPickList []int GearPickList []int //用来表示档位的数组(每一个数表示【下标 * bit】位的档位存储结果)
} }
//初始化方法,gear表示最大的领取档位是多少.(档位刚开始计算,没有值的情况) //初始化方法,gear表示最大的领取档位是多少.(档位刚开始计算,没有值的情况)
@@ -34,6 +34,19 @@ func NewBitStore(gear int, gearPickList []int) *BitStore {
} }
} }
//返回指定档位长度的领取状态数组
func (bitStore *BitStore) FindSpecialGearList(gear int) []bool {
bitStore.checkGearRight(gear) //校验传进来的长度是否正确
bitStore.getSizeOrInit() //如果数组没有初始化,进行初始化
return bitStore.getGearListByGear(gear) //返回指定长度的领取状态数组
}
//获取当前有记录的档位的Map
func (bitStore *BitStore) FindGearMap() map[int]bool {
listSize := bitStore.getSizeOrInit() //获取当前数组长度,如果数组没有初始化,进行初始化
return bitStore.shortListDeal(listSize, listSize) //短数组的处理(没有达到最大大小的数组长度)
}
//获取所有档位对应的Map //获取所有档位对应的Map
func (bitStore *BitStore) FindAllGearMap() map[int]bool { func (bitStore *BitStore) FindAllGearMap() map[int]bool {
length := bitStore.getGearListLength(bitStore.MaxGear) //获取最大档位的长度 length := bitStore.getGearListLength(bitStore.MaxGear) //获取最大档位的长度
@@ -60,10 +73,25 @@ func (bitStore *BitStore) ReceiveByGear(gear int) ([]int, map[int]bool) {
bitStore.checkIfReceive(gear) //校验是否被领取了 bitStore.checkIfReceive(gear) //校验是否被领取了
length := bitStore.dynamicGrowth(gear) //数组进行动态增长 length := bitStore.dynamicGrowth(gear) //数组进行动态增长
position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置 position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置
bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] + (1 << uint(position)) bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] | (1 << uint(position))
return bitStore.GearPickList, bitStore.FindAllGearMap() return bitStore.GearPickList, bitStore.FindAllGearMap()
} }
//设置某一档位为未领取
func (bitStore *BitStore) UnReceiveByGear(gear int) ([]int, map[int]bool) {
bitStore.checkIfUnReceive(gear) //检验是否被领取
length := bitStore.dynamicGrowth(gear) //数组进行动态增长
position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置
bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] - (1 << uint(position))
return bitStore.GearPickList, bitStore.FindAllGearMap()
}
func (bitStore *BitStore) checkIfUnReceive(gear int) {
if !bitStore.IsGearReceive(gear) {
panic("当前档位未领取,不可重置")
}
}
//判断档位是否正确 //判断档位是否正确
func (bitStore *BitStore) checkGearRight(gear int) { func (bitStore *BitStore) checkGearRight(gear int) {
if gear > bitStore.MaxGear { if gear > bitStore.MaxGear {
@@ -73,12 +101,12 @@ func (bitStore *BitStore) checkGearRight(gear int) {
//获取当前档位对应的数组长度(这边的length是从1开始的.) //获取当前档位对应的数组长度(这边的length是从1开始的.)
func (bitStore *BitStore) getGearListLength(gear int) int { func (bitStore *BitStore) getGearListLength(gear int) int {
return ((gear - 1) + (bit - 1)) / (bit - 1) return ((gear - 1) + realBit) / realBit
} }
//获取档位所在的二进制位置 //获取档位所在的二进制位置
func (bitStore *BitStore) getGearPosition(gear, length int) int { func (bitStore *BitStore) getGearPosition(gear, length int) int {
return (gear - 1) % (bit - 1) return (gear - 1) - realBit*(length-1)
} }
func (bitStore *BitStore) getSizeOrInit() int { func (bitStore *BitStore) getSizeOrInit() int {
@@ -91,8 +119,8 @@ func (bitStore *BitStore) getSizeOrInit() int {
func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool { func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool {
resultMap := make(map[int]bool, 0) resultMap := make(map[int]bool, 0)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
for j := 0; j < bit-1 && bitStore.MaxGear > i*(bit-1)+j; j++ { for j := 0; j < realBit && bitStore.MaxGear > i*realBit+j; j++ {
resultMap[i*(bit-1)+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0 resultMap[i*realBit+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0
} }
} }
return resultMap return resultMap
@@ -101,13 +129,14 @@ func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool {
func (bitStore *BitStore) shortListDeal(listSize, length int) map[int]bool { func (bitStore *BitStore) shortListDeal(listSize, length int) map[int]bool {
resultMap := make(map[int]bool, 0) resultMap := make(map[int]bool, 0)
for i := 0; i < listSize; i++ { for i := 0; i < listSize; i++ {
for j := 0; j < (bit - 1); j++ { for j := 0; j < realBit; j++ {
resultMap[i*(bit-1)+j+1] = (bitStore.GearPickList[i] & (1 << uint(j))) > 0 resultMap[i*realBit+j+1] =
(bitStore.GearPickList[i] & (1 << uint(j))) > 0
} }
} }
for i := listSize; i < length; i++ { for i := listSize; i < length; i++ {
for j := 0; j < (bit-1) && bitStore.MaxGear > i*(bit-1)+j; j++ { for j := 0; j < realBit && bitStore.MaxGear > i*realBit+j; j++ {
resultMap[i*(bit-1)+j+1] = false resultMap[i*realBit+j+1] = false
} }
} }
return resultMap return resultMap
@@ -131,3 +160,29 @@ func (bitStore *BitStore) checkIfReceive(gear int) {
panic("当前档位已被领取,不可重复领取") panic("当前档位已被领取,不可重复领取")
} }
} }
func (bitStore *BitStore) getGearListByGear(gear int) []bool {
gearList := make([]bool, 0)
listAllGear := len(bitStore.GearPickList) * realBit //当前已领取数组可表示的总档位
//如果指定的长度大于gear已有数组长度,需要特殊处理
if listAllGear <= gear {
for i := 0; i < (listAllGear-1)/realBit+1; i++ {
for j := 0; j < realBit && realBit*i+j < gear; j++ {
gearList = append(gearList, (bitStore.GearPickList[i]&(1<<uint(j))) > 0)
}
}
for i := 0; i < gear-listAllGear; i++ {
for j := 0; j < realBit && realBit*i+j < gear-listAllGear; j++ {
gearList = append(gearList, false)
}
}
return gearList
}
//如果获取的档位比实际记录的档位小
for i := 0; i < (gear-1)/realBit+1; i++ {
for j := 0; j < realBit && realBit*i+j < gear; j++ {
gearList = append(gearList, (bitStore.GearPickList[i]&(1<<uint(j))) > 0)
}
}
return gearList
}
+72 -11
View File
@@ -7,12 +7,74 @@
package bitStore package bitStore
import ( import (
"Go-Tool/util/sort"
"fmt" "fmt"
"math" "math"
"testing" "testing"
) )
func TestBitStore(t *testing.T) {
fmt.Println("测试2档的情况")
testTwo()
fmt.Println()
fmt.Println("测试10档的情况")
testTen()
fmt.Println()
fmt.Println("测试18档的情况")
testEighteen()
fmt.Println()
fmt.Println("测试33档的情况")
testThirtyThree()
fmt.Println()
fmt.Println("测试58档的情况")
testFiftyEight()
fmt.Println()
fmt.Println("测试1000档的情况")
testOneThousand(t)
fmt.Println()
}
func TestBitStoreFind(t *testing.T) {
bitStore := NewBitStore(120, nil)
bitStore.ReceiveByGear(1)
bitStore.ReceiveByGear(3)
bitStore.ReceiveByGear(5)
bitStore.ReceiveByGear(7)
bitStore.ReceiveByGear(13)
bitStore.ReceiveByGear(10)
bitStore.ReceiveByGear(16)
bitStore.ReceiveByGear(33)
bitStore.ReceiveByGear(35)
fmt.Println(bitStore.FindGearMap())
fmt.Println(bitStore.FindSpecialGearList(1))
fmt.Println(len(bitStore.FindSpecialGearList(1)))
fmt.Println(bitStore.FindSpecialGearList(4))
fmt.Println(len(bitStore.FindSpecialGearList(4)))
fmt.Println(bitStore.FindSpecialGearList(2))
fmt.Println(len(bitStore.FindSpecialGearList(2)))
fmt.Println(bitStore.FindSpecialGearList(10))
fmt.Println(len(bitStore.FindSpecialGearList(10)))
fmt.Println(bitStore.FindSpecialGearList(13))
fmt.Println(len(bitStore.FindSpecialGearList(13)))
fmt.Println(bitStore.FindSpecialGearList(14))
fmt.Println(len(bitStore.FindSpecialGearList(14)))
fmt.Println(bitStore.FindSpecialGearList(20))
fmt.Println(len(bitStore.FindSpecialGearList(20)))
fmt.Println(bitStore.FindSpecialGearList(32))
fmt.Println(len(bitStore.FindSpecialGearList(32)))
fmt.Println(bitStore.FindSpecialGearList(63))
fmt.Println(len(bitStore.FindSpecialGearList(63)))
fmt.Println(bitStore.FindSpecialGearList(64))
fmt.Println(len(bitStore.FindSpecialGearList(64)))
fmt.Println(bitStore.FindSpecialGearList(65))
fmt.Println(len(bitStore.FindSpecialGearList(65)))
}
func newStoreMap(bitStore *BitStore) { func newStoreMap(bitStore *BitStore) {
gearMap := bitStore.FindAllGearMap() gearMap := bitStore.FindAllGearMap()
falseList := make([]int, 0) falseList := make([]int, 0)
@@ -34,22 +96,21 @@ func getReceiveResult(bitStore *BitStore) {
keyList = append(keyList, key) keyList = append(keyList, key)
} }
} }
sort.BubbleSort(keyList)
fmt.Println("已经领取的档位信息如下") fmt.Println("已经领取的档位信息如下")
for value := range keyList { for value := range keyList {
fmt.Print(fmt.Sprintf("%d,", keyList[value])) fmt.Print(fmt.Sprintf("%d,", keyList[value]))
} }
} }
func TestOneThousand(t *testing.T) { func testOneThousand(t *testing.T) {
bitStore := NewBitStore(1000, nil) bitStore := NewBitStore(1000, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
fmt.Println() fmt.Println()
bitStore.ReceiveByGear(1) bitStore.ReceiveByGear(3)
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0])) fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0]))
fmt.Println(fmt.Sprintf("这个时候领取结果 1应该返回true,结果是:%v", bitStore.IsGearReceive(3))) fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3)))
bitStore.ReceiveByGear(8) bitStore.ReceiveByGear(8)
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0])) fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[0]))
fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8))) fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8)))
@@ -76,10 +137,10 @@ func TestOneThousand(t *testing.T) {
fmt.Println(fmt.Sprintf("这个时候领取结果 44应该返回true,结果是:%v", bitStore.IsGearReceive(44))) fmt.Println(fmt.Sprintf("这个时候领取结果 44应该返回true,结果是:%v", bitStore.IsGearReceive(44)))
bitStore.ReceiveByGear(48) bitStore.ReceiveByGear(48)
fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[1])) fmt.Println(fmt.Sprintf("%b", bitStore.GearPickList[1]))
fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48)))
fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList))) fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList)))
fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48)))
bitStore.ReceiveByGear(123) bitStore.ReceiveByGear(123)
fmt.Println(fmt.Sprintf("这个时候领取结果 123应该返回true,结果是:%v", bitStore.IsGearReceive(123))) fmt.Println(fmt.Sprintf("这个时候领取结果 123应该返回true,结果是:%v", bitStore.IsGearReceive(123)))
@@ -100,7 +161,7 @@ func TestOneThousand(t *testing.T) {
getReceiveResult(bitStore) getReceiveResult(bitStore)
} }
func TestFiftyEight(t *testing.T) { func testFiftyEight() {
bitStore := NewBitStore(58, nil) bitStore := NewBitStore(58, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
@@ -133,7 +194,7 @@ func TestFiftyEight(t *testing.T) {
} }
} }
func TestThirtyThree(t *testing.T) { func testThirtyThree() {
bitStore := NewBitStore(33, nil) bitStore := NewBitStore(33, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
@@ -160,7 +221,7 @@ func TestThirtyThree(t *testing.T) {
} }
} }
func TestEighteen(t *testing.T) { func testEighteen() {
bitStore := NewBitStore(18, nil) bitStore := NewBitStore(18, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
@@ -181,7 +242,7 @@ func TestEighteen(t *testing.T) {
} }
} }
func TestTen(t *testing.T) { func testTen() {
bitStore := NewBitStore(10, nil) bitStore := NewBitStore(10, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
@@ -200,7 +261,7 @@ func TestTen(t *testing.T) {
} }
} }
func TestTwo(t *testing.T) { func testTwo() {
bitStore := NewBitStore(2, nil) bitStore := NewBitStore(2, nil)
newStoreMap(bitStore) //初始化的校验 newStoreMap(bitStore) //初始化的校验
-127
View File
@@ -1,127 +0,0 @@
/*
* @Author : huangzj
* @Time : 2020/11/12 14:04
* @Description
*/
package linqUse
import "time"
type Book struct {
Name string
Author string
Money float64
WordsNum int
PublishTime time.Time
}
func MakeBook() []Book {
bookList := make([]Book, 0)
bookList = append(bookList, Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Effective Java",
Author: "Java",
Money: 78,
WordsNum: 9000,
PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Java语言",
Author: "Java",
Money: 50,
WordsNum: 3000,
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Lua语言",
Author: "Lua",
Money: 75,
WordsNum: 45000,
PublishTime: time.Date(2020, 1, 10, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "React语言",
Author: "React",
Money: 99,
WordsNum: 14500,
PublishTime: time.Date(2020, 7, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Red语言",
Author: "Red",
Money: 28,
WordsNum: 880,
PublishTime: time.Date(2019, 4, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "JavaScript语言",
Author: "JavaScript",
Money: 81,
WordsNum: 3776,
PublishTime: time.Date(2019, 5, 17, 10, 0, 0, 0, time.Local),
})
return bookList
}
func MakeBook1() []Book {
bookList := make([]Book, 0)
bookList = append(bookList, Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Effective Java",
Author: "Java",
Money: 78,
WordsNum: 9000,
PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Go语言(第二版)",
Author: "Go",
Money: 50,
WordsNum: 3000,
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
})
return bookList
}
func MakeBook2() []Book {
bookList := make([]Book, 0)
bookList = append(bookList, Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
return bookList
}
func MakeBook3() []Book {
bookList := make([]Book, 0)
bookList = append(bookList, Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
bookList = append(bookList, Book{
Name: "Go语言(第三版)",
Author: "Go",
Money: 50,
WordsNum: 3000,
PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
})
return bookList
}
-57
View File
@@ -1,57 +0,0 @@
/*
* @Author : huangzj
* @Time : 2020/11/24 16:17
* @Description
*/
package linqUse
type Person struct {
Name string //拥有者的名字
}
type Pet struct {
Name string //动物的名字
OwnerName string //拥有者的名字
}
type Man struct {
Name string //拥有者的名字
Pets []Pets //宠物们
}
type Pets struct {
Name string //动物的名字
}
func MakeInnerData() []Man {
man := make([]Man, 0)
man = append(man, Man{
Name: "康康",
Pets: []Pets{{Name: "康康的狗"}, {Name: "康康的猫"}},
})
man = append(man, Man{
Name: "老施",
Pets: []Pets{{Name: "老施的🐟"}, {Name: "老施的鸟"}},
})
man = append(man, Man{
Name: "小明",
Pets: []Pets{{Name: "小明的🐖"}, {Name: "小明的狗"}},
})
return man
}
func MakeJoinData() ([]Person, []Pet) {
kangkang := Person{Name: "爱吃合合乐的康康"}
laoshi := Person{Name: "老施"}
xiaoming := Person{Name: "不要催-小明"}
expect := Person{Name: "我是没有宠物的人"}
dog := Pet{Name: "康康的狗", OwnerName: kangkang.Name}
cat := Pet{Name: "康康的猫", OwnerName: kangkang.Name}
fish := Pet{Name: "老施的🐟", OwnerName: laoshi.Name}
pig := Pet{Name: "小明的🐖", OwnerName: xiaoming.Name}
return []Person{kangkang, laoshi, xiaoming, expect}, []Pet{dog, cat, fish, pig}
}
-41
View File
@@ -1,41 +0,0 @@
/*
* @Author : huangzj
* @Time : 2020/11/12 14:43
* @Description:测试方法集合
*/
package linqUse
import "time"
//书籍发布时间是否早于--.--.--
var PublishTimeBeforeFunc = func(thisBook interface{}) bool {
if thisBook.(Book).PublishTime.Before(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)) {
return true
}
return false
}
//书籍发布时间是否晚于--.--.--
var PublishTimeAfterFunc = func(thisBook interface{}) bool {
if thisBook.(Book).PublishTime.After(time.Date(2018, 1, 1, 0, 0, 0, 0, time.Local)) {
return true
}
return false
}
//书籍发布时间是否晚于--.--.--
var PublishTimeAfterFunc2 = func(thisBook interface{}) bool {
if thisBook.(Book).PublishTime.After(time.Date(2021, 1, 1, 0, 0, 0, 0, time.Local)) {
return true
}
return false
}
//自定义聚合操作方法
var AggregateFunc = func(first interface{}, second interface{}) interface{} {
if first.(Book).PublishTime.Before(second.(Book).PublishTime) {
return first
}
return second
}
-531
View File
@@ -1,531 +0,0 @@
/*
* @Author : huangzj
* @Time : 2020/11/12 10:52
* @Description:这边是linq包的使用操作,为之后的使用做一些示例
* 包引用命令: go get github.com/ahmetb/go-linq
* 示例参考地址:https://godoc.org/github.com/ahmetb/go-linq#
* 在Idea中对应方法名上使用 Shift+F1 组合键操作可以直接跳转到方法对应的地址
*/
package linqUse
import (
"Go-Tool/util/timed"
"fmt"
"github.com/ahmetb/go-linq"
"strconv"
"testing"
"time"
)
func Test(t *testing.T) {
Aggregate() //自定义聚合操作
All() //判断数组的所有元素是否都满足条件
Where() //根据条件查询对应的元素
AnyWith() //判断数组是否有任意个元素满足条件
Calculate() //这个方法只能计算数值类型
Combine() //组合两个数组的两种方式
Contains() //包含
FirstAndLast() //第一个和最后一个
Distinct() //返回数组中唯一的元素
Except() //返回第一个序列没有出现在第二个序列中的成员
GroupBy() //按照对应规则进行分组
Intersect() //产生两个数组的交集
OrderBy() //排序
Skip() //略过指定条件的元素
Count() //计算数组总长度
Result() //对结果集进行操作
Take() //获取对应数量的元素,一般多用在排序后前几个的元素
Select() //筛选结构体中对应的元素
SelectMany() //对多维数组进行合并或者其他处理 对结构体中的数组进行处理(与结构体结合操作)
Join() //对两个有关联的数据进行处理
}
func Where() {
bookList := MakeBook()
query := linq.From(bookList)
fmt.Println()
fmt.Println()
query.WhereT(func(book Book) bool {
return book.Money > float64(70)
}).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
})
}
func Take() {
bookList := MakeBook()
query := linq.From(bookList)
query.OrderByDescendingT(func(book Book) string {
return book.Author
}).Take(3).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
})
fmt.Println()
fmt.Println()
//超出对应数量的元素会不会报错(输出所有的元素)
query.OrderByDescendingT(func(book Book) string {
return book.Author
}).Take(100).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
})
fmt.Println()
fmt.Println()
//负数会发生什么情况(直接返回,不做操作)
query.OrderByDescendingT(func(book Book) string {
return book.Author
}).Take(-2).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
})
//TakeWhile系列的方法,虽然能够根据条件进行查询,但是有一个弊端就是一旦查询到的结果和条件不符合则直接返回,也就是说后面满足条件的元素不会再被做筛选
//那么比如这边的这个大于的操作,就需要对整个数组进行排序之后然后进行筛选,如果不希望排序,则用原生的for循环可能会更好
fmt.Println()
fmt.Println()
query.TakeWhileT(func(book Book) bool {
return book.Money > float64(70)
}).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", book.Author, book.Name))
})
}
func Result() {
bookList := MakeBook()
query := linq.From(bookList)
bookMap := make(map[string]string, 0)
query.SelectT(func(book Book) linq.KeyValue {
return linq.KeyValue{
Key: book.Author,
Value: book.Name,
}
}).ToMap(&bookMap)
for key, value := range bookMap {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value))
}
fmt.Println()
fmt.Println()
//如果key相同的话,前面的元素会被覆盖掉(只会保留最后一个)
bookList1 := MakeBook1()
query1 := linq.From(bookList1)
bookMap1 := make(map[string]string, 0)
query1.SelectT(func(book Book) linq.KeyValue {
return linq.KeyValue{
Key: book.Author,
Value: book.Name,
}
}).ToMap(&bookMap1)
for key, value := range bookMap1 {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value))
}
fmt.Println()
fmt.Println()
bookList2 := MakeBook()
query2 := linq.From(bookList2)
bookMap2 := make(map[string]Book, 0)
query2.ToMapByT(&bookMap2,
//这个方法决定key的字段是什么
func(book Book) string {
return book.Author
}, //这个方法决定value的字段是什么
func(book Book) Book {
return book
})
for key, value := range bookMap2 {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", key, value.Name))
}
fmt.Println()
fmt.Println()
bookListResult := make([]Book, 0)
linq.From(MakeBook()).OrderByDescendingT(func(book Book) string {
return book.Author
}).ToSlice(&bookListResult)
for _, value := range bookListResult {
fmt.Println(fmt.Sprintf("作者%v,写了一本书叫做%v", value.Author, value.Name))
}
}
func Count() {
bookList := MakeBook()
query := linq.From(bookList)
fmt.Println(fmt.Sprintf("数组中发布时间早于2019-1-1的书有%d本", query.CountWithT(PublishTimeBeforeFunc)))
fmt.Println(fmt.Sprintf("数组中发布时间晚于2018-1-1的书有%d本", query.CountWithT(PublishTimeAfterFunc)))
}
func Skip() {
bookList := MakeBook()
query := linq.From(bookList)
fmt.Println(fmt.Sprintf("跳过三个元素,返回的数组中包含%d个元素", len(query.Skip(3).Results())))
fmt.Println(fmt.Sprintf("跳过发布时间在2018.1.1之后的元素,返回的数组中包含%d个元素", query.SkipWhile(PublishTimeAfterFunc).Count()))
}
func SelectMany() {
input := [][]int{{1, 2, 3}, {4, 5, 6, 7}}
//二位数组进行合并
linq.From(input).SelectManyT(
func(i []int) linq.Query {
return linq.From(i)
},
).ForEachT(func(num int) {
fmt.Println(num)
})
fmt.Println()
fmt.Println()
//三维数组进行合并
input1 := [][][]int{{{1, 2, 3}}, {{4, 5, 6, 7}, {8, 9, 10}}}
linq.From(input1).SelectManyT(
func(i [][]int) linq.Query {
return linq.From(i)
},
).SelectManyT(
func(i []int) linq.Query {
return linq.From(i)
},
).ForEachT(func(num int) {
fmt.Print(num)
fmt.Print(" ")
})
//SelectMany的主要作用是,结构体中包含数组元素,可以把数组元素取出来和结构体做相应的操作
//如果是结构体中有多个数组的操作,可以把对应的多个数组放到一个新定义的结构体数组中
fmt.Println()
men := MakeInnerData()
linq.From(men).
//第一个方法筛选出结构体对应的数组
SelectManyByT(func(man Man) linq.Query {
return linq.From(man.Pets)
},
//第二个方法这边可以拿到数组中元素对应的结构体的数据.
func(pet Pets, man Man) map[string]Pets {
return map[string]Pets{
man.Name: pet,
}
}).ForEachT(func(petWithMan map[string]Pets) {
for key, value := range petWithMan {
fmt.Println(fmt.Sprintf("%v拥有一只宠物,它的名字叫做%v", key, value.Name))
}
})
}
func Select() {
bookList := MakeBook()
query := linq.From(bookList)
//筛选出结构体对应的元素
query.SelectT(func(book Book) string {
return book.Name
}).ForEachT(func(bookName string) {
fmt.Println(fmt.Sprintf("书名%v", bookName))
})
fmt.Println()
fmt.Println()
//根据下标进行返回,如果是跟下标有关的,则可以通过这个方法进行组合然后返回.
query.SelectIndexedT(func(index int, book Book) []string {
return []string{strconv.Itoa(index + 1), book.Name}
}).ForEachT(func(book []string) {
fmt.Println(fmt.Sprintf("第%v本书,书名%v", book[0], book[1]))
})
}
//OrderBy可以按照对应的规则进行排序,可以实现多重排序,需要注意的就是OrderBy是从到达,orderByDescending是从大到小
func OrderBy() {
bookList := MakeBook()
query := linq.From(bookList)
query = query.OrderByDescendingT(func(book Book) string {
return book.Name
}).ThenByDescendingT(func(book Book) string {
return book.Author
}).ThenByDescendingT(func(book Book) float64 {
return book.Money
}).Query
query.ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
fmt.Println()
fmt.Println()
//reverse: 把结果逆序
query.Reverse().ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
}
func Join() {
//任务和动物有关联,直接找到对应的关系,没有对应关系的数据不会处理,正常情况下应该用更单一的数据来做关联
persons, pets := MakeJoinData()
query1 := linq.From(persons)
query2 := linq.From(pets)
query1.JoinT(query2,
func(person Person) string {
return person.Name
},
func(pet Pet) string {
return pet.OwnerName
},
func(person Person, pet Pet) map[string]Pet {
petMap := make(map[string]Pet)
petMap[person.Name] = pet
return petMap
},
).ForEachT(func(petMap map[string]Pet) {
for key, value := range petMap {
fmt.Println(fmt.Sprintf("%v拥有一只宠物,它的名字叫做:%v", key, value.Name))
}
})
}
func Intersect() {
bookList1 := MakeBook1()
query1 := linq.From(bookList1)
bookList2 := MakeBook2()
query2 := linq.From(bookList2)
fmt.Println("输出对应的书籍元素,按照结构体判断交集")
query3 := query1.Intersect(query2)
query3.ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
fmt.Println()
fmt.Println("输出对应的书籍元素,按照元素判断交集")
query3 = query1.IntersectByT(query2, func(book Book) string {
return book.Author
})
query3.ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
//这边计算是按照结构体的一个元素进行比较。事实证明无论是否按照结构体的元素筛选,返回的都是完全相同的元素
fmt.Println()
fmt.Println("输出对应的书籍元素,按照元素判断交集2")
bookList1 = MakeBook1()
query1 = linq.From(bookList1)
bookList3 := MakeBook3()
query2 = linq.From(bookList3)
query3 = query2.IntersectByT(query1, func(book Book) string {
return book.Author
})
query3.ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
fmt.Println()
fmt.Println("判断是否会不重复的处理")
query1 = linq.From([]int{1, 2, 3, 4, 5, 3})
query2 = linq.From([]int{1, 3, 3, 78, 99, 0, 111})
query3 = query2.IntersectByT(query1, func(i int) int {
return i
})
fmt.Println(query3.Results())
}
func GroupBy() {
bookList1 := MakeBook1()
query := linq.From(bookList1)
fmt.Println("输出对应书名和作者")
//第一个func是分组的依据,第二个func是分组后返回的元素.
query = query.GroupByT(func(book Book) string {
return book.Author
}, func(book Book) Book {
return book
})
query.ForEachT(func(bookGroup linq.Group) {
fmt.Println(fmt.Sprintf("作者是%v", bookGroup.Key))
for _, item := range bookGroup.Group {
fmt.Println(fmt.Sprintf("书名%v,作者%v", item.(Book).Name, item.(Book).Author))
fmt.Println()
}
})
fmt.Println()
fmt.Println("输出对应书名")
bookList1 = MakeBook1()
query = linq.From(bookList1)
var nameGroups []linq.Group
query.GroupByT(
func(book Book) string { return book.Author },
func(book Book) string { return book.Name },
).ToSlice(&nameGroups)
for _, item := range nameGroups {
fmt.Println(fmt.Sprintf("作者是%v", item.Key))
for _, row := range item.Group {
fmt.Println(fmt.Sprintf("书名%v", row))
}
}
}
func Except() {
bookList1 := MakeBook1()
query1 := linq.From(bookList1)
bookList2 := MakeBook2()
query2 := linq.From(bookList2)
fmt.Println("输出对应书名和作者")
//判断结构结构体本身是否相等
query1.Except(query2).
ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
fmt.Println()
fmt.Println("输出对应书名和作者")
//判断结构体的某个字段是否出现
query1.ExceptByT(query2, func(book Book) string {
return book.Author
}).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
}
func Distinct() {
bookList := MakeBook()
query := linq.From(bookList)
query = query.Append(Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
bookList1 := make([]Book, 0)
query.ToSlice(&bookList1)
fmt.Println(fmt.Sprintf("筛选之前query中总共有%d个数据", query.Count()))
//这边的distinct如果是结构体,则判断的是结构体的所有值,如果是指针则判断的是指针地址.
query = query.Distinct()
fmt.Println(fmt.Sprintf("筛选之后query中总共有%d个数据", query.Count()))
fmt.Println()
fmt.Println("输出对应书名和作者")
query = query.Append(Book{
Name: "Go语言(第二版)",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})
//根据对应的规则来判断是否相同 -- 如果对应的字段一样,只会保留第一个找到的,后面的会被清除掉
query.DistinctByT(func(book Book) string {
return book.Author
}).ForEachT(func(book Book) {
fmt.Println(fmt.Sprintf("书名%v,作者%v", book.Name, book.Author))
})
}
func Combine() {
bookList := MakeBook()
query := linq.From(bookList)
query1 := query.Concat(query) //不会排除重复项
query2 := query.Union(query) //会排除重复项
fmt.Println(fmt.Sprintf("不会排除重复项的方法返回的元素个数是%d", len(query1.Results())))
fmt.Println(fmt.Sprintf("会排除重复项的方法返回的元素个数是%d", len(query2.Results())))
query1 = query1.Append(Book{Name: "Last One"}) //加在原来的Query的最后面
query2 = query2.Prepend(Book{Name: "First One"}) //加在原来的Query的第一个
fmt.Println(fmt.Sprintf("最后一个元素是%v", query1.Last()))
fmt.Println(fmt.Sprintf("第一个元素是%v", query2.First()))
}
func FirstAndLast() {
bookList := MakeBook()
query := linq.From(bookList)
fmt.Println(fmt.Sprintf("数组第一本书书名叫:%s", query.First().(Book).Name))
fmt.Println(fmt.Sprintf("数组第一本书发布时间在2018年1月1号之后的书书名叫:%s", query.FirstWith(PublishTimeAfterFunc).(Book).Name))
fmt.Println(fmt.Sprintf("数组最后一本书书名叫:%s", query.Last().(Book).Name))
fmt.Println(fmt.Sprintf("数组最后一本书发布时间在2018年1月1号之后的书书名叫:%s", query.LastWith(PublishTimeAfterFunc).(Book).Name))
}
func Contains() {
bookList := MakeBook()
query := linq.From(bookList)
//这边需要注意是的是如果要判断两个元素是否相等,在go里面不能使用元素的地址
// 所以这边加到query里面的必须不能是元素的地址,否则没办法比较结构体本身,而是比较结构体的地址
fmt.Println(fmt.Sprintf("判断当前数组是否包含相同的元素,判断的是所有的值,而不是地址,结果是%v", query.Contains(Book{
Name: "Go语言",
Author: "Go",
Money: 100,
WordsNum: 1000,
PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
})))
}
func Calculate() {
query := linq.From([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
fmt.Println(fmt.Sprintf("平均值为:%f", query.Average()))
fmt.Println(fmt.Sprintf("最大的值为%d", query.Max()))
fmt.Println(fmt.Sprintf("最小的值为%d", query.Min()))
}
func AnyWith() {
bookList := MakeBook()
query := linq.From(bookList)
result := query.AnyWith(PublishTimeBeforeFunc) //判断是否有任意个元素满足条件
fmt.Println(fmt.Sprintf("是否有任意书的发表时间早于2020年1月1号,答案是%v", result))
result = query.AnyWith(PublishTimeAfterFunc2) //判断是否有任意个元素满足条件
fmt.Println(fmt.Sprintf("是否有任意书的发表时间晚于2021年1月1号,答案是%v", result))
}
func All() {
bookList := MakeBook()
query := linq.From(bookList)
result := query.All(PublishTimeBeforeFunc)
fmt.Println(fmt.Sprintf("是否所有的书的发表时间都早于2020年1月1号,答案是%v", result))
result = query.All(PublishTimeAfterFunc)
fmt.Println(fmt.Sprintf("是否所有的书的发表时间都晚于2018年1月1号,答案是%v", result))
}
func Aggregate() {
bookList := MakeBook()
query := linq.From(bookList)
// 这边的聚合操作其实就是【自定义对应的比较方法】。
// 根据注释,第一次拿到的是数组的第一个元素,然后跟第二个元素进行比较,如果第二个元素符合条件则【替换第一个元素】,否则当前聚合操作还是持有第一个元素。
// 以此类推后面的元素
result := query.Aggregate(AggregateFunc).(Book)
fmt.Println(fmt.Sprintf("聚合操作查询出的结果是【%s】这本书,它的发布时间最早为:%v", result.Name, timed.GetTimeDefaultFormatString(result.PublishTime.Unix())))
}
+55
View File
@@ -0,0 +1,55 @@
/*
* @Author : huangzj
* @Time : 2021/3/13 21:58
* @Description
*/
package palindrome
import "fmt"
//返回字符串中最大回文的数量和回文字符串
func Manacher(allString string) (int, string) {
maxMid := 0 //当前最大回文串中部下标
radiusPos := 0 //最大回文半径对应的右边的下标位置
result := generateString(allString)
point := make([]int, len(result)) //以j为中心的最长回文半径
maxLen := -1
var palindrome string
for i := 1; i < len(result); i++ {
j := 2*maxMid - i //与i下标对称的左边的下标
if i >= radiusPos {
point[i] = 1
} else if radiusPos-i > point[j] {
point[i] = point[j]
} else {
// point[j] >= radiusPos-i
point[i] = radiusPos - i
}
//从后面的位置继续开始找对应的字符
for (i-point[i] >= 0 && i+point[i] < len(result)) && result[i+point[i]] == result[i-point[i]] {
point[i]++
}
//更新最长回文串信息
if i+point[i] > radiusPos {
maxMid = i
radiusPos = i + point[i]
}
if maxLen < point[i]-1 && point[i]-1 > 1 {
maxLen = point[i] - 1
palindrome = allString[maxMid/2-maxLen/2 : radiusPos/2]
}
}
return maxLen, palindrome
}
//把字符串转换成特殊的字符串
func generateString(allString string) string {
var result string
for i := range allString {
result = fmt.Sprintf("%s%s%c", result, "#", allString[i])
}
return fmt.Sprintf("%s%s", result, "#")
}
+28
View File
@@ -0,0 +1,28 @@
/*
* @Author : huangzj
* @Time : 2021/3/13 21:58
* @Description
*/
package palindrome
import (
"fmt"
"testing"
)
func TestGenerateString(t *testing.T) {
fmt.Println(generateString("abcdef"))
fmt.Println(generateString("abc2342def"))
fmt.Println(generateString("abcdef3213"))
fmt.Println(generateString("abcderewrewr312f"))
fmt.Println(generateString("312312abcdef321e"))
}
func TestPalindrome(t *testing.T) {
fmt.Println(Manacher("abcabccbacba"))
fmt.Println(Manacher("mabcabccbacbammm"))
fmt.Println(Manacher("habcabccbacbammm"))
fmt.Println(Manacher("hmmmabcabccbacbammm"))
fmt.Println(Manacher("abcdefghij"))
}
+12
View File
@@ -0,0 +1,12 @@
/*
* @Author : huangzj
* @Time : 2021/2/23 20:52
* @Description
*/
package rand
type AwardWeight struct {
Award interface{} //奖励数据
Weight int //权重
}
+2 -2
View File
@@ -1,7 +1,7 @@
/* /*
* @Author : huangzj * @Author : huangzj
* @Time : 2020/6/29 10:48 * @Time : 2020/6/29 10:48
* @Description这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层 * @Description
*/ */
package rand package rand
@@ -47,7 +47,7 @@ func GetRandIntNoRepeat(count, min, max int) []int {
return randAttr return randAttr
} }
//从一个数组中获取到X个不重复随机数 //从一个数组中获取到X个不重复下标的随机数
func GetDiffNum(data []int, count int) []int { func GetDiffNum(data []int, count int) []int {
if count > len(data) { if count > len(data) {
panic("获取随机数数量有误") panic("获取随机数数量有误")
+1 -1
View File
@@ -1,7 +1,7 @@
/* /*
* @Author : huangzj * @Author : huangzj
* @Time : 2020/6/29 10:23 * @Time : 2020/6/29 10:23
* @Description这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层 * @Description
*/ */
package rand package rand
+62
View File
@@ -0,0 +1,62 @@
/*
* @Author : huangzj
* @Time : 2021/2/23 20:50
* @Description
*/
package rand
func GetAwardWeightByWeight(awardWeight []*AwardWeight) *AwardWeight {
//求总权重
weight := 0
for _, award := range awardWeight {
weight += award.Weight
}
randNum := GetRandInt(1, weight)
sum := 0
for _, award := range awardWeight {
sum += award.Weight
if sum >= randNum {
return award
}
}
return nil
}
//根据权重不放回的抽取,出参是:抽到的道具、剩余没有抽的道具
func GetByWeightWithLeftAward(awardWeight []*AwardWeight) (*AwardWeight, []*AwardWeight) {
weight := 0
leftAwards := make([]*AwardWeight, 0)
for _, award := range awardWeight {
weight += award.Weight
}
randNum := GetRandInt(1, weight)
sum := 0
for index, award := range awardWeight {
sum += award.Weight
if sum >= randNum {
//如果获取到奖励则将当前获取的奖励扣除
leftAwards = append(awardWeight[0:index], awardWeight[index+1:]...)
return award, leftAwards
}
}
return nil, leftAwards
}
// 根据权重不放回的抽取X个元素,直接返回这些元素
// 入参:奖池、抽取数量,出参:获得的所有道具,剩余的其他道具
func GetSomeAwardsFromPool(srcAwardPool []*AwardWeight, count int) ([]*AwardWeight, []*AwardWeight) {
if count > len(srcAwardPool) {
panic("抽取数量不对")
}
var finalAwardList []*AwardWeight
var award *AwardWeight
var leftAward = make([]*AwardWeight, len(srcAwardPool))
copy(leftAward, srcAwardPool)
for i := 0; i < count; i++ {
award, leftAward = GetByWeightWithLeftAward(leftAward)
finalAwardList = append(finalAwardList, award)
}
return finalAwardList, leftAward
}
+46
View File
@@ -0,0 +1,46 @@
/*
* @Author : huangzj
* @Time : 2021/2/23 22:08
* @Description
*/
package rand
import (
"fmt"
"testing"
)
func TestRandByAwardWeight(t *testing.T) {
awardList := make([]*AwardWeight, 0)
awardList = append(awardList, &AwardWeight{
Award: []int{1, 2},
Weight: 10,
})
awardList = append(awardList, &AwardWeight{
Award: []int{2, 2},
Weight: 20,
})
awardList = append(awardList, &AwardWeight{
Award: []int{3, 2},
Weight: 30,
})
award := GetAwardWeightByWeight(awardList)
fmt.Println(award.Award)
award1, list3 := GetByWeightWithLeftAward(awardList)
fmt.Println(award1.Award)
for _, award := range list3 {
fmt.Println(award.Award)
}
list4, left := GetSomeAwardsFromPool(awardList, 2)
for _, award := range list4 {
fmt.Println(award.Award)
}
for _, award := range left {
fmt.Println(award.Award)
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ func LomutoPartition(list []int, start int, end int) int {
if list[i] < compareValue { if list[i] < compareValue {
moveSubscript++ moveSubscript++
charge++ charge++
list[moveSubscript], list[i] = list[i], list[moveSubscript] list[moveSubscript], list[i] = list[i], list[moveSubscript] //交换元素
} }
} }
charge++ charge++
+17 -8
View File
@@ -13,17 +13,26 @@ import (
func TestPartition(t *testing.T) { func TestPartition(t *testing.T) {
list := []int{99, 1, 2, 3, 4, 100, 200, 90, 5} list := []int{99, 1, 2, 3, 4, 100, 200, 90, 5}
s := LomutoPartition(list, 0, 9-1)
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s)) for i := 1; i <= len(list); i++ {
for _, r := range list { s := LomutoPartition(list, 0, len(list)-1)
fmt.Print(r, " ") fmt.Println()
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
for _, r := range list {
fmt.Print(r, " ")
}
} }
s = LomutoPartition(list, 0, 9-1) fmt.Println()
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s)) for i := 1; i <= len(list); i++ {
for _, r := range list { num, _, _ := LomutoQuiteSelect(list, i)
fmt.Print(r, " ") fmt.Println(fmt.Sprintf("第%d个位置的数是:%d", i, num))
} }
for i := 0; i < len(list); i++ {
fmt.Println(list[i])
}
} }
func doc() string { func doc() string {
+27
View File
@@ -17,6 +17,14 @@ func QuickSort(list []int, start, end int) {
} }
} }
func QuickSortByte(list []byte, start, end int) {
if start < end {
position := hoarePartition1(list, start, end)
QuickSortByte(list, start, position) //注意这边结束的下表是position,而不是position + 1
QuickSortByte(list, position+1, end)
}
}
//通过lomuto划分来实现快速排序 //通过lomuto划分来实现快速排序
func QuickSort1(list []int, start, end int) { func QuickSort1(list []int, start, end int) {
if start < end { if start < end {
@@ -26,6 +34,25 @@ func QuickSort1(list []int, start, end int) {
} }
} }
func hoarePartition1(list []byte, start int, end int) int {
value := list[start] //比较的元素
s := start
e := end
for s < e {
//找到数组终止前,比目标数(value)大的数字
for ; s < end && list[s] < value; s++ {
}
//找到数组结束前,比目标数(value)小的数字
for ; e > start && list[e] >= value; e-- {
}
if s < e {
list[s], list[e] = list[e], list[s]
}
}
list[start], list[e] = list[e], list[start]
return e
}
func hoarePartition(list []int, start int, end int) int { func hoarePartition(list []int, start int, end int) int {
value := list[start] //比较的元素 value := list[start] //比较的元素
s := start s := start
+9
View File
@@ -0,0 +1,9 @@
## 需求
这里的实际需求是策划案中的掷骰子,先随机得到骰子的总和,再将骰子拆分成三个随机的骰子数,策划案中说明有对出现豹子进行控制,这边不把这个实现做进来
如果需要进行控制,则在获取结果之后进行控制即可,重新掷骰子的概率不会特别高,因为豹子本身就是一个低概率的事件。
## 实现
总共两个实现,一个是实际需求中的三个数的拆分
另一个是N个数的拆分,这边用Splitter结构体实现,在创建的时候需要进行数字与数量的校验
+44
View File
@@ -0,0 +1,44 @@
/*
* @Author : huangZJ
* @Time : 2021/6/16 10:50
* @Description
*/
package splitNumToN
import (
"Go-Tool/util/rand"
"fmt"
)
//将一个数拆解成三个
func SplitNumTo3(num int) {
randNumList := make([]int, 0)
var count int
for i := 0; i < 2; i++ {
randNum := getRandValue(num-count, 3-1-i)
randNumList = append(randNumList, randNum)
count = count + randNum
}
randNumList = append(randNumList, num-count)
for _, num := range randNumList {
fmt.Print(fmt.Sprintf("%d ", num))
}
}
//num 被随机的数
//count count + 1 = 总随机数数量
func getRandValue(num int, count int) int {
minValue := num - 6*count
if minValue <= 0 {
minValue = 1
}
maxValue := num - count*1
if maxValue > 6 {
maxValue = 6
}
return rand.GetRandInt(minValue, maxValue)
}
+24
View File
@@ -0,0 +1,24 @@
/*
* @Author : huangZJ
* @Time : 2021/6/16 10:52
* @Description
*/
package splitNumToN
import (
"fmt"
"testing"
)
func TestSplitNumTo3(t *testing.T) {
for i := 4; i <= 17; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 100; j++ {
fmt.Println()
SplitNumTo3(i)
}
fmt.Println()
}
}
+72
View File
@@ -0,0 +1,72 @@
/*
* @Author : huangZJ
* @Time : 2021/6/15 11:20
* @Description:将一个数拆分成其他N个数,这N个数相加的结果等于这个数
*/
package splitNumToN
import "Go-Tool/util/rand"
type Splitter struct {
NumCount int //拆分成随机数的数量
Num int //被拆分的总数
MinValue int //被拆分的最小值
MaxValue int //被拆分的最大值
SplitNumList []int //存放拆解之后的结果
}
func NewSplitter(numCount, num int) *Splitter {
//给定默认的限制的最大最小值
splitter := &Splitter{
NumCount: numCount,
Num: num,
MinValue: 1,
MaxValue: 6,
SplitNumList: make([]int, 0),
}
//校验数值是否满足
splitter.checkValue()
return splitter
}
func (splitter *Splitter) checkValue() {
if splitter.MinValue*splitter.NumCount > splitter.Num {
panic("被拆分的数值过小")
}
if splitter.MaxValue*splitter.NumCount < splitter.Num {
panic("被拆分的数值过大")
}
}
//将一个数拆成N个,并且保证N个数相加值等于被拆分的这个数
func (splitter *Splitter) SplitNumToN() {
var count int
for i := 0; i < splitter.NumCount-1; i++ {
randNum := splitter.getRandValue(splitter.Num-count, splitter.NumCount-1-i)
splitter.SplitNumList = append(splitter.SplitNumList, randNum)
count = count + randNum
}
splitter.SplitNumList = append(splitter.SplitNumList, splitter.Num-count)
}
func (splitter *Splitter) GetRandNumList() []int {
return splitter.SplitNumList
}
//num 被随机的数
//count count + 1 = 总随机数数量
func (splitter *Splitter) getRandValue(num int, count int) int {
minValue := num - splitter.MaxValue*count
if minValue <= 0 {
minValue = splitter.MinValue
}
maxValue := num - count*1
if maxValue > splitter.MaxValue {
maxValue = splitter.MaxValue
}
return rand.GetRandInt(minValue, maxValue)
}
+103
View File
@@ -0,0 +1,103 @@
/*
* @Author : huangZJ
* @Time : 2021/6/16 9:50
* @Description
*/
package splitNumToN
import (
"fmt"
"testing"
)
func TestSplitNumToNWith2(t *testing.T) {
fmt.Println("测试两个数的情况")
for i := 3; i <= 11; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 20; j++ {
splitter := NewSplitter(2, i)
splitter.SplitNumToN()
for _, num := range splitter.GetRandNumList() {
fmt.Print(fmt.Sprintf("%d ", num))
}
fmt.Println()
}
fmt.Println()
}
}
func TestSplitNumToNWith3(t *testing.T) {
fmt.Println()
fmt.Println("测试三个数的情况")
for i := 4; i <= 17; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 20; j++ {
splitter := NewSplitter(3, i)
fmt.Println()
splitter.SplitNumToN()
for _, num := range splitter.GetRandNumList() {
fmt.Print(fmt.Sprintf("%d ", num))
}
}
fmt.Println()
}
}
func TestSplitNumToNWith4(t *testing.T) {
fmt.Println()
fmt.Println("测试四个数的情况")
for i := 5; i <= 23; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 100; j++ {
splitter := NewSplitter(4, i)
fmt.Println()
splitter.SplitNumToN()
for _, num := range splitter.GetRandNumList() {
fmt.Print(fmt.Sprintf("%d ", num))
}
}
fmt.Println()
}
}
func TestSplitNumToNWith5(t *testing.T) {
fmt.Println()
fmt.Println("测试五个数的情况")
for i := 6; i <= 29; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 100; j++ {
splitter := NewSplitter(5, i)
fmt.Println()
splitter.SplitNumToN()
for _, num := range splitter.GetRandNumList() {
fmt.Print(fmt.Sprintf("%d ", num))
}
}
fmt.Println()
}
}
func TestSplitNumToNWith6(t *testing.T) {
fmt.Println()
fmt.Println("测试六个数的情况")
for i := 7; i <= 35; i++ {
fmt.Println()
fmt.Println(fmt.Sprintf("当前随机数为%d", i))
for j := 0; j < 100; j++ {
splitter := NewSplitter(6, i)
fmt.Println()
splitter.SplitNumToN()
for _, num := range splitter.GetRandNumList() {
fmt.Print(fmt.Sprintf("%d ", num))
}
}
fmt.Println()
}
}
+6 -4
View File
@@ -14,13 +14,15 @@ import (
func TestHorspool(t *testing.T) { func TestHorspool(t *testing.T) {
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "abcd")) //输出0 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "abcd")) //输出0
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "bcd")) //输出1 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "bcd")) //输出1
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "fgh")) //输出6 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "fgh")) //输出5
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "hijk")) //输出8 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "hijk")) //输出7
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "jk")) //输出10 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "jk")) //输出9
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "k")) //输出11 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "k")) //输出10
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kbz")) //输出-1 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kbz")) //输出-1
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kdasdsad")) //输出-1 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "kdasdsad")) //输出-1
fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "dsadsa")) //输出-1 fmt.Println("该子串的位置为:", Horspool("abcdefghijk", "dsadsa")) //输出-1
fmt.Println(shiTable("abdabe"))
} }
+55
View File
@@ -0,0 +1,55 @@
/*
* @Author : huangzj
* @Time : 2021/2/24 13:19
* @DescriptionKMP字符串匹配算法,参考地址:https://www.cnblogs.com/en-heng/p/5091365.html
* http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
*/
package stringMatch
func KmpMatch(allString string, match string) int {
next := getNext(match)
i := 0 //被匹配的字符串下标
j := 0 //模式匹配字符串下标
sLength := len(allString) - 1
mLength := len(match) - 1
for i <= sLength && j <= mLength {
if j == -1 || allString[i] == match[j] {
j++
i++
} else {
j = next[j]
}
}
if j == len(match) {
return i - j
}
return -1
}
//失配表函数构建(部分匹配函数)
func getNext(match string) []int {
next := make([]int, len(match))
next[0] = -1
i := 0
j := -1
mLength := len(match) - 1
for i < mLength {
//处理两种情况: 1.数组第一个数是-1 2. match对应位置字符相等的情况
if j == -1 || match[i] == match[j] {
//如果这里是数组第一个数的时候,下标要往后移动
//如果这里是数组相等的情况,要比较下一个相应的字符,所以下标需要往后移动,而next需要在上一个的基础上去做+1操作
i++
j++
next[i] = j
} else {
//如果匹配过程中,出现对应不上的情况,也就是说 match[i] != match[j],
j = next[j]
}
}
return next
}
+54
View File
@@ -0,0 +1,54 @@
/*
* @Author : huangzj
* @Time : 2021/2/24 17:52
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestKmpMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult(s, m)
s = "abcbvxs"
m = "bx"
showResult(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult(s, m)
}
func TestMatchNum(t *testing.T) {
s := "ababababca"
m := "abababca"
showResult(s, m)
}
func showResult(s, m string) {
i := KmpMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}
func TestGetNext(t *testing.T) {
next := getNext("abababca")
fmt.Println(next)
next1 := getNext("abababc")
fmt.Println(next1)
next2 := getNext("abababcxy")
fmt.Println(next2)
next3 := getNext("abababcxyxyy")
fmt.Println(next3)
next4 := getNext("abcdabd")
fmt.Println(next4)
next5 := getNext("abcxabcxabcyabcz")
fmt.Println(next5)
}
+28
View File
@@ -0,0 +1,28 @@
/*
* @Author : huangzj
* @Time : 2021/3/5 13:17
* @Description
*/
package stringMatch
func KarpRabinMatch(allString, modeString string) int {
hashMode := hash(modeString)
for i := 0; i < len(allString)-len(modeString)+1; i++ {
hashKey := hash(allString[i : i+len(modeString)+1])
if hashMode == hashKey {
for j := 0; j < len(modeString); j++ {
if allString[i+j] != modeString[j] {
break
}
}
return i
}
}
return -1
}
func hash(s string) int {
return 1
}
+25
View File
@@ -0,0 +1,25 @@
/*
* @Author : huangzj
* @Time : 2021/3/5 13:25
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestKarpRabinMatch(t *testing.T) {
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "abcd")) //输出0
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "bcd")) //输出1
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "fgh")) //输出5
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "hijk")) //输出7
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "jk")) //输出9
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "k")) //输出10
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "kbz")) //输出-1
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "kdasdsad")) //输出-1
fmt.Println("该子串的位置为:", KarpRabinMatch("abcdefghijk", "dsadsa")) //输出-1
}
+78
View File
@@ -0,0 +1,78 @@
/*
* @Author : huangzj
* @Time : 2021/3/8 14:42
* @Description
*/
package stringMatch
import "fmt"
func ShiftAndMatch(allString, modeString string) int {
if len(modeString) > 32 {
panic("暂只支持32位大小")
}
bitap := GenerateTable(modeString)
fmt.Println("bitap的二进制:")
for i := 0; i < len(modeString); i++ {
fmt.Println(fmt.Sprintf("当前字符:%c,对应二进制:%08b", modeString[i], bitap[modeString[i]-'a']))
}
fmt.Println("")
var status int
for i := 0; i < len(allString); i++ {
status = ((status << 1) | 1) & bitap[allString[i]-'a']
fmt.Println(fmt.Sprintf("当前字符:%c,对应的二进制结果:%08b", allString[i], status))
if status&(1<<(len(modeString)-1)) > 0 {
return i - len(modeString) + 1
}
}
return -1
}
func GenerateTable(modeString string) []int {
bitap := make([]int, 32)
for i := 0; i < len(modeString); i++ {
bitap[modeString[i]-'a'] |= 1 << i
}
return bitap
}
func ShiftOrMatch(allString, modeString string) int {
if len(modeString) > 32 {
panic("暂只支持32位大小")
}
bitap := make([]int, 32)
for i := 0; i < 32; i++ {
bitap[i] = ^0
}
var shift = 1
for i := 0; i < len(modeString); i++ {
bitap[modeString[i]-'a'] &= ^shift
shift <<= 1
}
fmt.Println("bitap的二进制:")
for i := 0; i < len(modeString); i++ {
fmt.Println(fmt.Sprintf("当前字符:%c,对应二进制:%08b", modeString[i], uint32(bitap[modeString[i]-'a'])))
}
fmt.Println()
status := ^0
mask := ^(1 << (len(modeString) - 1))
fmt.Println(fmt.Sprintf("mask:%08b", uint32(mask)))
for i := 0; i < len(allString); i++ {
status = (status << 1) | bitap[allString[i]-'a']
fmt.Println(fmt.Sprintf("当前字符:%c,对应的二进制结果:%08b", allString[i], uint32(status)))
if ^(status | mask) > 0 {
return i - len(modeString) + 1
}
}
return -1
}
+42
View File
@@ -0,0 +1,42 @@
/*
* @Author : huangzj
* @Time : 2021/3/8 14:51
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestShiftAndMatch(t *testing.T) {
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "abcd")) //输出0
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "bcd")) //输出1
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "fgh")) //输出5
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "hijk")) //输出7
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "jk")) //输出9
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "k")) //输出10
//
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "kbz")) //输出-1
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "kdasdsad")) //输出-1
//fmt.Println("该子串的位置为:", ShiftAndMatch("abcdefghijk", "dsadsa")) //输出-1
fmt.Println("该子串的位置为:", ShiftAndMatch("cbcbcbaefd", "cbcba"))
}
func TestShiftOrMatch(t *testing.T) {
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "abcd")) //输出0
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "bcd")) //输出1
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "fgh")) //输出5
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "hijk")) //输出7
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "jk")) //输出9
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "k")) //输出10
//
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "kbz")) //输出-1
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "kdasdsad")) //输出-1
//fmt.Println("该子串的位置为:", ShiftOrMatch("abcdefghijk", "dsadsa")) //输出-1
fmt.Println("该子串的位置为:", ShiftOrMatch("cbcbcbaefd", "cbcba"))
}
+45
View File
@@ -0,0 +1,45 @@
/*
* @Author : huangzj
* @Time : 2021/3/2 11:21
* @Description
*/
package stringMatch
func ShiftTable(mode string) []int {
shiftTable := make([]int, 256)
//一开始设置所有的字符匹配不上向右移动大小为:模式字符串长度 + 1(因为要移动到下一个字符的后一位)
for i := range shiftTable {
shiftTable[i] = len(mode) + 1
}
//设置模式字符串中每一个字符的移动长度.
for i := range mode {
shiftTable[mode[i]] = len(mode) - i
}
return shiftTable
}
func SundayMatch(allString, modeString string) int {
table := ShiftTable(modeString)
aLength := len(allString)
mLength := len(modeString)
i := 0 //这个参数记录的是移动过程中,,模式字符串对应原始字符串的第一个位置.
for i < aLength-mLength {
j := 0
for allString[i+j] == modeString[j] {
j++
if j >= len(modeString) {
return i
}
}
//找到移动后模式字符串对应原始字符串的第一个位置
move := allString[i+mLength]
i = i + table[move]
}
return -1
}
+33
View File
@@ -0,0 +1,33 @@
/*
* @Author : huangzj
* @Time : 2021/3/2 11:21
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestSundayMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult2(s, m)
s = "abcbvxs"
m = "bx"
showResult2(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult2(s, m)
}
func showResult2(s, m string) {
i := SundayMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}
+32
View File
@@ -0,0 +1,32 @@
/*
* @Author : huangzj
* @Time : 2021/2/25 11:11
* @Description
*/
package stringMatch
func ViolentMatch(allString, match string) int {
i := 0
j := 0
sLength := len(allString)
mLenght := len(match)
for i < sLength && j < mLenght {
//当前字符如果匹配,继续匹配下一个字符,坐标移动
if allString[i] == match[j] {
j++
i++
} else {
//如果字符不匹配,match从头开始,被匹配的字符串从之前匹配的下一个字符开始,坐标修改
i = i - j + 1
j = 0
}
}
if j == len(match) {
return i - j
}
return -1
}
+33
View File
@@ -0,0 +1,33 @@
/*
* @Author : huangzj
* @Time : 2021/2/25 11:11
* @Description
*/
package stringMatch
import (
"fmt"
"testing"
)
func TestViolentMatch(t *testing.T) {
s := "abcbvxs"
m := "bcb"
showResult1(s, m)
s = "abcbvxs"
m = "bx"
showResult1(s, m)
s = "abcbvxssdaadsad"
m = "cbvxssdaa"
showResult1(s, m)
}
func showResult1(s, m string) {
i := ViolentMatch(s, m)
if i == -1 {
fmt.Println("未找到对应字符串")
} else {
fmt.Println(fmt.Sprintf("匹配到的字符串是:%v", s[i:len(m)+i]))
}
}
+9
View File
@@ -42,6 +42,15 @@ func TestTimeIntervalUtil(t *testing.T) {
o2 := GetIntervalBetweenTimes(time.Now().AddDate(3, 2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix(), time.Now().Unix()) o2 := GetIntervalBetweenTimes(time.Now().AddDate(3, 2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix(), time.Now().Unix())
o3 := GetIntervalBetweenTimes(time.Now().Unix(), time.Now().AddDate(3, -2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix()) o3 := GetIntervalBetweenTimes(time.Now().Unix(), time.Now().AddDate(3, -2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix())
O4 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2))
O5 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2).Add(5*time.Hour))
O6 := GetIntervalDay(time.Now(), time.Now().AddDate(0, 0, 2).Add(25*time.Hour))
fmt.Println("相差天数计算:")
fmt.Println(O4)
fmt.Println(O5)
fmt.Println(O6)
ox := GetIntervalBetweenTimes(time.Now().Unix(), time.Date(2020, 5, 6, 0, 0, 0, 0, time.Local).Unix()) ox := GetIntervalBetweenTimes(time.Now().Unix(), time.Date(2020, 5, 6, 0, 0, 0, 0, time.Local).Unix())
fmt.Println(ox) fmt.Println(ox)
+14
View File
@@ -136,6 +136,20 @@ func GetIntervalBetweenTimes(timestamp, stamp int64) vo.IntervalObj {
} }
// 获取两个时间点之间相差多少天
func GetIntervalDay(beforeTime, afterTime time.Time) int {
timestamp := beforeTime.Unix()
stamp := afterTime.Unix()
//时间大小保证前小后大
if timestamp > stamp {
timestamp, stamp = stamp, timestamp
}
timeBefore := time.Unix(timestamp, 0)
timeAfter := time.Unix(stamp, 0)
m := timeAfter.Sub(timeBefore)
return int(m.Hours() / 24)
}
/* /*
* @param timestamp 时间戳 * @param timestamp 时间戳
* @param stamp 时间戳 * @param stamp 时间戳
+10 -2
View File
@@ -32,7 +32,7 @@ func initTrie() *Trie {
} }
//往前缀树中添加对应的字符串(build模式) //往前缀树中添加对应的字符串(build模式)
func (trie *Trie) insert(word string) *Trie { func (trie *Trie) Insert(word string) *Trie {
traverse := trie traverse := trie
for _, v := range []rune(word) { for _, v := range []rune(word) {
if _, ok := traverse.Child[v]; !ok { if _, ok := traverse.Child[v]; !ok {
@@ -48,13 +48,21 @@ func (trie *Trie) insert(word string) *Trie {
//删除对应的字符串,如果查找不到则直接返回(build模式) //删除对应的字符串,如果查找不到则直接返回(build模式)
func (trie *Trie) Delete(word string) *Trie { func (trie *Trie) Delete(word string) *Trie {
traverse := trie traverse := trie
parent := trie
var value rune
for _, v := range []rune(word) { for _, v := range []rune(word) {
if _, ok := traverse.Child[v]; !ok { if _, ok := traverse.Child[v]; !ok {
return trie return trie
} }
parent = traverse
traverse = traverse.Child[v] traverse = traverse.Child[v]
value = v
} }
traverse.Word = emptyTag if len(parent.Child) == 0 {
delete(parent.Child, value)
return trie
}
parent.Child[value].Word = emptyTag
return trie return trie
} }
+12 -10
View File
@@ -14,15 +14,16 @@ import (
//模糊查询前缀匹配的所有字符串 //模糊查询前缀匹配的所有字符串
func TestSearchTrieVague(t *testing.T) { func TestSearchTrieVague(t *testing.T) {
fmt.Println() fmt.Println()
fmt.Println("模糊查询 查找前缀匹配的所有字符串") fmt.Println("模糊查询 查找前缀匹配的所有字符串,输入\"新年快乐\" ")
trie := New() trie := New()
trie.insert("abcuuid").insert("abcuued").insert("abcMxns").insert("abssde").insert("avddfa") trie.Insert("abcuuid").Insert("abcuued").Insert("abcMxns").Insert("abssde").Insert("avddfa")
trie.insert("我爱中国").insert("我爱祖国").insert("我爱学习").insert("我是谁").insert("我在哪里") trie.Insert("我爱中国").Insert("我爱祖国").Insert("我爱学习").Insert("我是谁").Insert("我在哪里")
trie.insert("我是你").insert("我").insert("我喜欢学习").insert("我在厦门").insert("我是一个程序员") trie.Insert("我是你").Insert("我").Insert("我喜欢学习").Insert("我在厦门").Insert("我是一个程序员")
trie.Insert("新年快乐,你好呀").Insert("新年新气象").Insert("新的一年新的开始")
fmt.Println() fmt.Println()
fmt.Println() fmt.Println()
result3, _ := trie.SearchTrieVague("我爱她") result3, _ := trie.SearchTrieVague("新年快乐")
for _, r := range result3 { for _, r := range result3 {
fmt.Println(r) fmt.Println(r)
} }
@@ -33,8 +34,8 @@ func TestSearchTrie(t *testing.T) {
fmt.Println() fmt.Println()
fmt.Println("查找前缀匹配的所有字符串") fmt.Println("查找前缀匹配的所有字符串")
trie := New() trie := New()
trie.insert("abcuuid").insert("abcuued").insert("abcMxns").insert("abssde").insert("avddfa") trie.Insert("abcuuid").Insert("abcuued").Insert("abcMxns").Insert("abssde").Insert("avddfa")
trie.insert("我爱中国").insert("我爱祖国").insert("我爱学习").insert("我是谁").insert("我在哪里") trie.Insert("我爱中国").Insert("我爱祖国").Insert("我爱学习").Insert("我是谁").Insert("我在哪里")
fmt.Println() fmt.Println()
fmt.Println() fmt.Println()
@@ -62,7 +63,7 @@ func TestSearchTrie(t *testing.T) {
//敏感词汇屏蔽测试 //敏感词汇屏蔽测试
func TestSensitiveWordsTest(t *testing.T) { func TestSensitiveWordsTest(t *testing.T) {
trie := New() trie := New()
trie.insert("粗话").insert("fuck").insert("fuckk").insert("脏话") trie.Insert("粗话").Insert("fuck").Insert("fuckk").Insert("脏话")
s := "我是脏话,我是粗话,fuckk,fuck,fffuccck" s := "我是脏话,我是粗话,fuckk,fuck,fffuccck"
word := trie.DealFunc(s, func(sentence []rune, start int, end int) string { word := trie.DealFunc(s, func(sentence []rune, start int, end int) string {
var replace string var replace string
@@ -73,13 +74,14 @@ func TestSensitiveWordsTest(t *testing.T) {
runes = append(runes, sentence[end:]...) runes = append(runes, sentence[end:]...)
return string(runes) return string(runes)
}) })
fmt.Println(word) fmt.Println(fmt.Sprintf("原来的字符串: \"%v\"", s))
fmt.Println(fmt.Sprintf("转换后的字符串: \"%v\"", word))
} }
//常规功能测试 //常规功能测试
func TestCommonTest(t *testing.T) { func TestCommonTest(t *testing.T) {
trie := New() trie := New()
trie.insert("ABC").insert("AB").insert("ABE").insert("ABEX").insert("XYZ").insert("你").insert("你好").insert("你是谁") trie.Insert("ABC").Insert("AB").Insert("ABE").Insert("ABEX").Insert("XYZ").Insert("你").Insert("你好").Insert("你是谁")
result := trie.Traverse() result := trie.Traverse()
for _, r := range result { for _, r := range result {
fmt.Println(r) fmt.Println(r)