go-pwgen/helpers.go

92 lines
1.5 KiB
Go
Raw Normal View History

2023-04-25 13:56:11 +00:00
package pwgen
func runeFor(alphabet []rune, prng Int32n) rune {
return alphabet[prng.Int31n(int32(len(alphabet)))]
}
func alphabet(start, end rune) (result []rune) {
length := end - start + 1
result = make([]rune, length)
for i := int32(0); i < length; i++ {
result[i] = start + i
}
return result
}
func merge[T any](slices ...[]T) []T {
var totalLength int
for i := range slices {
totalLength += len(slices[i])
}
result := make([]T, totalLength)
var offset int
for i := range slices {
copy(result[offset:], slices[i])
offset += len(slices[i])
}
return result
}
func shuffle[T comparable](in []T, prng Int32n) (result []T) {
if !canShuffle(in) {
return in
}
for {
result = make([]T, 0, len(in))
temp := make([]T, len(in))
copy(temp, in)
for len(temp) > 0 {
var i int32
for {
i = prng.Int31n(int32(len(temp)))
if i != int32(len(result)) {
break
}
}
result = append(result, temp[i])
copy(temp[i:], temp[i+1:])
temp = temp[:len(temp)-1]
}
if !sequenceEqual(in, result) {
return result
}
}
}
func canShuffle[T comparable](in []T) bool {
if len(in) < 2 {
return false
}
uniq := make(map[T]bool)
for _, r := range in {
uniq[r] = true
if len(uniq) > 1 {
return true
}
}
return false
}
func sequenceEqual[T comparable](first, second []T) bool {
if len(first) != len(second) {
return false
}
for i := range first {
if first[i] != second[i] {
return false
}
}
return true
}