对于唯一的整数数组,什么是好的哈希函数(或类似的东西)?

时间:2018-01-16 00:14:24

标签: algorithm math go

我正在编写一个简单的程序来分析彩票。我很好奇相同的数字模式出现的频率。

这是我在Golang中的工作代码:

package main

import (
    "fmt"
    "math/rand"
    "os"
    "sort"
    "sync"

    "github.com/mitchellh/hashstructure"
)

func do(n int, ch chan bool) {
    hashes := make(map[uint64]struct{})

    for i := 0; i < n; i++ {
        numbers := rand.Perm(45)[:6]
        sort.Ints(numbers)

        hash, err := hashstructure.Hash(numbers, nil)
        if err != nil {
            panic(err)
        }

        if _, ok := hashes[hash]; ok {
            ch <- true
            break
        } else {
            hashes[hash] = struct{}{}
        }
    }
}

func main() {
    n := 1000

    ch := make(chan bool)
    duplicated := 0.0
    done := make(chan struct{})

    wg := sync.WaitGroup{}
    for i := 0; i < n; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            do(800, ch)
        }()
    }

    go func() {
        wg.Wait()
        close(done)
    }()

    for {
        select {
        case <-ch:
            duplicated += 1
        case <-done:
            fmt.Printf("duplicated ratio: %.2f%%\n", duplicated/float64(n)*100)
            os.Exit(0)
        }
    }
}

我目前正在使用https://github.com/mitchellh/hashstructure进行散列整数数组(在Golang中,类型为[]int)。我正在寻找一种更有效的方法来测试彩票号码是否重复,因为由于反射,库的功能被认为是缓慢的。

我首先想到这样的事情:

func hashFunc(v []int) int {
    hash := 1
    for _, x := range v {
        hash ^= x
    }
    return hash
}

但它产生了哈希冲突。你能否建议我一个更好的方法来散列数组(元素是唯一的,在1~45范围内),甚至是另一种方法来有效地测试过去是否存在重复的int数组?谢谢。

1 个答案:

答案 0 :(得分:6)

您可以跳过散列并将其视为一个64位数字。每个彩票号码小于256,可以包含在1个字节中。你有6个数字,所以这是6个字节,可以包含在64位中,即8个字节。

https://play.golang.org/p/JHLfHIhAUdd

package main

import (
    "fmt"
)

func hashFunc(v []uint8) uint64 {
    var hash uint64
    var i uint
    for _, x := range v {
        hash |= uint64(x) << (i * 8)
        i++
    }
    return hash
}

func main() {
    fmt.Printf("hashFunc ({1,2,3,4,5,6}) = %#x", hashFunc([]uint8{1,2,3,4,5,6}))
}