Mapping bits to int - go

I'm trying to map a uint64 array bit positions to an int array (see below). BitSet is a []uint64. Below is my code as currently setup. But I am wondering if there could be a std function in golang that can reduce this code. Other language has BitArray or other objects that makes life much easier.
So, in golang, do we have to code this? is there a better to do this?
// Indexes the index positions of '1' bits as an int array
func (b BitSet) Indexes() []int {
// set up masks for bit ANDing
masks := make([]uint64, _BitsPerUint64)
for i := 0; i < _BitsPerUint64; i++ {
masks[i] = (1 << uint(i))
}
// iterate bitset
indexes := make([]int, 0, len(b)*4)
for i := 0; i < len(b); i++ {
for m := 0; m < _BitsPerUint64; m++ {
if masks[m]&b[i] > 0 {
indexes = append(indexes, i*_BitsPerUint64+m)
}
}
}
return indexes
}

func (b BitSet) Indexes() []int {
retval := make([]int, 0, len(b)*64)
for idx, value := range b {
for i := 0; i < 64; i++ {
if value & (1<<uint(i)) != 0 {
retval = append(retval, idx*64 + i)
}
}
}
return retval
}

Related

Why does this goroutine behave like it's call by reference?

I'm trying to learn the basics of Go and I'm a bit confused about the difference between call by value and call by reference in a code snippet I tested.
I tried to solve a coding game puzzle in which a solution for a tic-tac-toe field is to be calculated.
The code I'm using
Because I'm learning Go, I wanted to use a goroutine to test every field of the tic-tac-toe board, check whether this field is the solution and then put a pointer to this field in a channel for the main method to have the result. The code I used looks like this:
package main
import "fmt"
import "os"
var player int = int('O')
var opponent int = int('X')
var empty int = int('.')
type board struct {
fields [][]int
}
func main() {
lines := [3]string {"OO.", "...", "..."}
var b board
b.fillBoard(lines)
fmt.Fprintln(os.Stderr, "input board:")
b.printBoard(true)
resultChannel := make(chan *board)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
go tryField(b, [2]int{i, j}, resultChannel) // goroutine call that isn't working as expected
}
}
fmt.Fprintln(os.Stderr, "\nresult:")
for i := 0; i < 9; i++ {
resultBoard := <- resultChannel
if (resultBoard != nil) {
resultBoard.printBoard(false)
return
}
}
// fmt.Fprintln(os.Stderr, "Debug messages...")
fmt.Println("false")// Write answer to stdout
}
func tryField(b board, field [2]int, result chan *board) {
b.printBoard(true)
fmt.Fprintln(os.Stderr, "add O to field: ", field)
fmt.Fprint(os.Stderr, "\n")
if (b.fields[field[0]][field[1]] != empty) {
result <- nil
}
b.fields[field[0]][field[1]] = player
if (b.isWon()) {
result <- &b
} else {
result <- nil
}
}
func (b *board) fillBoard(lines [3]string) {
b.fields = make([][]int, 3)
for i := 0; i < 3; i++ {
b.fields[i] = make([]int, 3)
}
for i, line := range lines {
for j, char := range line {
b.fields[i][j] = int(char)
}
}
}
func (b *board) printBoard(debug bool) {
var stream *os.File
if (debug) {
stream = os.Stderr
} else {
stream = os.Stdout
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Fprint(stream, string(b.fields[i][j]))
}
fmt.Fprint(stream, "\n")
}
}
func (b *board) isWon() bool {
for i := 0; i < 3; i++ {
rowFull := true
colFull := true
for j := 0; j < 3; j++ {
rowFull = rowFull && b.fields[i][j] == player
colFull = rowFull && b.fields[j][i] == player
}
if (rowFull || colFull) {
return true
}
}
diagonal1Full := true
diagonal2Full := true
for i := 0; i < 3; i++ {
diagonal1Full = diagonal1Full && b.fields[i][i] == player
diagonal2Full = diagonal2Full && b.fields[i][2-i] == player
}
if (diagonal1Full ||diagonal2Full) {
return true
}
return false
}
You can run it in the go playground.
The problem
Since the last function in the snippet is declared as func tryField(b board, field [2]int, result chan *board) I assume the board b to be an indipendent copy, each time I call the method, because it's call by value. So changing this board should not affect the other boards in the other goroutines. But unfortunately changing the board in one goroutine does affect the boards in the other goroutines as the output of the programm is the following:
input board:
OO.
...
...
result:
OO.
...
...
add O to field: [1 0]
OO.
O..
...
add O to field: [2 1]
OO.
O..
.O.
As you can see the initial field has two O's at the first and the second col in the first line. Adding an O to the position [1 0] works like expected, but when adding an O to the field [2 1] the there is also an O at [1 0], which was added in the previous goroutine and shouldn't be there since it's call by value.
The question
Why does the code in my snippet behave like it's call by reference although the function doesn't use a pointer?
Thanks in advance !
Slices are references to arrays. When modifying a slice without copying it, the underlaying array will be modified. Therefore, all slices that point to the same underlaying array will see this change.

How does a Go function without return values modify data?

I don't understand how the bubbleSort() slice a be applied at the main().
I don't give a return a and don't write a global variable.
package main
import (
"fmt"
)
func bubbleSort(a []int) {
var temp int
for j := 0; j < len(a); j++ {
for i := 0; i < (len(a) - 1); i++ {
if a[i] > a[i+1] {
temp = a[i]
a[i] = a[i+1]
a[i+1] = temp
}
}
}
}
func inputNums() []int {
var input int
var number int
fmt.Scan(&input)
s := make([]int, input)
for i := 0; i < input; i++ {
fmt.Scan(&number)
s[i] = number
}
return s
}
func outputNums(b []int) {
for i := 0; i < len(b); i++ {
fmt.Print(b[i])
fmt.Print(" ")
}
}
func main() {
nums := inputNums()
bubbleSort(nums)
outputNums(nums)
}
src/runtime/slice.go
type slice struct {
array unsafe.Pointer
len int
cap int
}
In Go all arguments are passed by value. The slice descriptor, a struct, is passed by value as if by assignment. The slice descriptor contains a pointer to its underlying array.
func bubbleSort(a []int) receives the a argument by value but uses the pointer a.array to modify the underlying array elements.
References:
The Go Blog: Go Slices: usage and internals
The Go Programming Language Specification

Why does Go map vs slice performance have 10x speed difference here

I just solved problem 23 on Project Euler, but I noticed a big difference between map[int]bool, and []bool in terms of performance.
I have a function that sums up the proper divisors of a number:
func divisorsSum(n int) int {
sum := 1
for i := 2; i*i <= n; i++ {
if n%i == 0 {
sum += i
if n/i != i {
sum += n / i
}
}
}
return sum
}
And then in main I do like this:
func main() {
start := time.Now()
defer func() {
elapsed := time.Since(start)
fmt.Printf("%s\n", elapsed)
}()
n := 28123
abundant := []int{}
for i := 12; i <= n; i++ {
if divisorsSum(i) > i {
abundant = append(abundant, i)
}
}
sums := map[int]bool{}
for i := 0; i < len(abundant); i++ {
for j := i; j < len(abundant); j++ {
if abundant[i]+abundant[j] > n {
break
}
sums[abundant[i]+abundant[j]] = true
}
}
sum := 0
for i := 1; i <= 28123; i++ {
if _, ok := sums[i]; !ok {
sum += i
}
}
fmt.Println(sum)
}
This code takes 450ms on my computer. But if I change the main code to below with slice of bool instead of map like this:
func main() {
start := time.Now()
defer func() {
elapsed := time.Since(start)
fmt.Printf("%s\n", elapsed)
}()
n := 28123
abundant := []int{}
for i := 12; i <= n; i++ {
if divisorsSum(i) > i {
abundant = append(abundant, i)
}
}
sums := make([]bool, n)
for i := 0; i < len(abundant); i++ {
for j := i; j < len(abundant); j++ {
if abundant[i]+abundant[j] < n {
sums[abundant[i]+abundant[j]] = true
} else {
break
}
}
}
sum := 0
for i := 0; i < len(sums); i++ {
if !sums[i] {
sum += i
}
}
fmt.Println(sum)
}
Now it takes only 40ms, below 1/10 of the speed from previous. I thought maps were supposed to have faster look ups. What is up with the performance difference here?
You can profile your code and see, but in general, there are two main reasons:
You pre-allocate sums in the second example to its desired size. This means it never has to grow, and all this is very efficient, there's no GC pressure, no reallocs, etc. Try creating the map with the desired size in advance and see how much it improves things.
I don't know the internal implementation of Go's hash map, but in general, random access of an array/slice by integer index is super efficient, and a hash table adds overhead on top of it, especially if it hashes the integers (it might do so to create better distribution).

How to implement slowEqual with golang

I tried to implement a slowEqual with golang,but xor operation is limited to int and int8 and I have no idea to convert string to int[] or int8[] , even it can be converted it seems little awkward, and I found bytes.Equal but it seems not a slowEqual implementation.Any advices?
This is my impletation.
//TODO real slow equal
func slowEquals(a, b string) bool {
al := len(a)
bl := len(b)
aInts := make([]int, al)
bInts := make([]int, bl)
for i := 0; i < al; i++ {
aInts[i] = int(a[i])
}
for i := 0; i < bl; i++ {
bInts[i] = int(b[i])
}
var diff uint8 = uint8(al ^ bl)
for i := 0; i < al && i < bl; i++ {
diff |= a[i] ^ b[i]
}
return diff == 0
//长度相等为0
/*
abytes := []int8()
bbytes := []int8()
al := len(a)
bl := len(b)
diff := al ^ bl
for i := 0; i < al && i < bl; i++ {
diff |= a[i] ^ b[i]
}
return diff == 0
*/
}
Or:(after first answer)
import "crypto/subtle"
func SlowEquals(a, b string) bool {
if len(a) != len(b) {
return subtle.ConstantTimeCompare([]byte(a), make([]byte,len(a))) == 1
}else{
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
}
}
Perhaps this:
import "crypto/subtle"
func SlowEquals(a, b string) bool {
if len(a) != len(b) {
return false
}
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
}
This returns quickly if the lengths are different, but there's a timing attack against the original code that reveals the length of a, so I think this isn't worse.

How to compare two version number strings in golang

I have two strings (they are actually version numbers and they could be any version numbers)
a := "1.05.00.0156"
b := "1.0.221.9289"
I want to compare which one is bigger. How to do it in golang?
There is a nice solution from Hashicorp - https://github.com/hashicorp/go-version
import github.com/hashicorp/go-version
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
Some time ago I created a version comparison library: https://github.com/mcuadros/go-version
version.CompareSimple("1.05.00.0156", "1.0.221.9289")
//Returns: 1
Enjoy it!
Here's a general solution.
package main
import "fmt"
func VersionOrdinal(version string) string {
// ISO/IEC 14651:2011
const maxByte = 1<<8 - 1
vo := make([]byte, 0, len(version)+8)
j := -1
for i := 0; i < len(version); i++ {
b := version[i]
if '0' > b || b > '9' {
vo = append(vo, b)
j = -1
continue
}
if j == -1 {
vo = append(vo, 0x00)
j = len(vo) - 1
}
if vo[j] == 1 && vo[j+1] == '0' {
vo[j+1] = b
continue
}
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
vo = append(vo, b)
vo[j]++
}
return string(vo)
}
func main() {
versions := []struct{ a, b string }{
{"1.05.00.0156", "1.0.221.9289"},
// Go versions
{"1", "1.0.1"},
{"1.0.1", "1.0.2"},
{"1.0.2", "1.0.3"},
{"1.0.3", "1.1"},
{"1.1", "1.1.1"},
{"1.1.1", "1.1.2"},
{"1.1.2", "1.2"},
}
for _, version := range versions {
a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
switch {
case a > b:
fmt.Println(version.a, ">", version.b)
case a < b:
fmt.Println(version.a, "<", version.b)
case a == b:
fmt.Println(version.a, "=", version.b)
}
}
}
Output:
1.05.00.0156 > 1.0.221.9289
1 < 1.0.1
1.0.1 < 1.0.2
1.0.2 < 1.0.3
1.0.3 < 1.1
1.1 < 1.1.1
1.1.1 < 1.1.2
1.1.2 < 1.2
go-semver is a semantic versioning library for Go. It lets you parse and compare two semantic version strings.
Example:
vA := semver.New("1.2.3")
vB := semver.New("3.2.1")
fmt.Printf("%s < %s == %t\n", vA, vB, vA.LessThan(*vB))
Output:
1.2.3 < 3.2.1 == true
Here are some of the libraries for version comparison:
https://github.com/blang/semver
https://github.com/Masterminds/semver
https://github.com/hashicorp/go-version
https://github.com/mcuadros/go-version
I have used blang/semver.
Eg: https://play.golang.org/p/1zZvEjLSOAr
import github.com/blang/semver/v4
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
// Options availabe
v1.Compare(v2) // Compare
v1.LT(v2) // LessThan
v1.GT(v2) // GreaterThan
This depends on what you mean by bigger.
A naive approach would be:
package main
import "fmt"
import "strings"
func main() {
a := strings.Split("1.05.00.0156", ".")
b := strings.Split("1.0.221.9289", ".")
for i, s := range a {
var ai, bi int
fmt.Sscanf(s, "%d", &ai)
fmt.Sscanf(b[i], "%d", &bi)
if ai > bi {
fmt.Printf("%v is bigger than %v\n", a, b)
break
}
if bi > ai {
fmt.Printf("%v is bigger than %v\n", b, a)
break
}
}
}
http://play.golang.org/p/j0MtFcn44Z
Based on Jeremy Wall's answer:
func compareVer(a, b string) (ret int) {
as := strings.Split(a, ".")
bs := strings.Split(b, ".")
loopMax := len(bs)
if len(as) > len(bs) {
loopMax = len(as)
}
for i := 0; i < loopMax; i++ {
var x, y string
if len(as) > i {
x = as[i]
}
if len(bs) > i {
y = bs[i]
}
xi,_ := strconv.Atoi(x)
yi,_ := strconv.Atoi(y)
if xi > yi {
ret = -1
} else if xi < yi {
ret = 1
}
if ret != 0 {
break
}
}
return
}
http://play.golang.org/p/AetJqvFc3B
Striving for clarity and simplicity:
func intVer(v string) (int64, error) {
sections := strings.Split(v, ".")
intVerSection := func(v string, n int) string {
if n < len(sections) {
return fmt.Sprintf("%04s", sections[n])
} else {
return "0000"
}
}
s := ""
for i := 0; i < 4; i++ {
s += intVerSection(v, i)
}
return strconv.ParseInt(s, 10, 64)
}
func main() {
a := "3.045.98.0832"
b := "087.2345"
va, _ := intVer(a)
vb, _ := intVer(b)
fmt.Println(va<vb)
}
Comparing versions implies parsing so I believe these 2 steps should be separate to make it robust.
tested in leetcode: https://leetcode.com/problems/compare-version-numbers/
func compareVersion(version1 string, version2 string) int {
len1, len2, i, j := len(version1), len(version2), 0, 0
for i < len1 || j < len2 {
n1 := 0
for i < len1 && '0' <= version1[i] && version1[i] <= '9' {
n1 = n1 * 10 + int(version1[i] - '0')
i++
}
n2 := 0
for j < len2 && '0' <= version2[j] && version2[j] <= '9' {
n2 = n2 * 10 + int(version2[j] - '0')
j++
}
if n1 > n2 {
return 1
}
if n1 < n2 {
return -1
}
i, j = i+1, j+1
}
return 0
}
import (
"fmt"
"strconv"
"strings"
)
func main() {
j := ll("1.05.00.0156" ,"1.0.221.9289")
fmt.Println(j)
}
func ll(a,b string) int {
var length ,r,l int = 0,0,0
v1 := strings.Split(a,".")
v2 := strings.Split(b,".")
len1, len2 := len(v1), len(v2)
length = len2
if len1 > len2 {
length = len1
}
for i:= 0;i<length;i++ {
if i < len1 && i < len2 {
if v1[i] == v2[i] {
continue
}
}
r = 0
if i < len1 {
if number, err := strconv.Atoi(v1[i]); err == nil {
r = number
}
}
l = 0
if i < len2 {
if number, err := strconv.Atoi(v2[i]); err == nil {
l = number
}
}
if r < l {
return -1
}else if r> l {
return 1
}
}
return 0
}
If you can guarantee version strings have same format (i.e. SemVer), you can convert to int and compare int. Here is an implementation for sorting slices of SemVer:
versions := []string{"1.0.10", "1.0.6", "1.0.9"}
sort.Slice(versions[:], func(i, j int) bool {
as := strings.Split(versions[i], ".")
bs := strings.Split(versions[j], ".")
if len(as) != len(bs) || len(as) != 3 {
return versions[i] < versions[j]
}
ais := make([]int, len(as))
bis := make([]int, len(bs))
for i := range as {
ais[i], _ = strconv.Atoi(as[i])
bis[i], _ = strconv.Atoi(bs[i])
}
//X.Y.Z
// If X and Y are the same, compare Z
if ais[0] == bis[0] && ais[1] == bis[1] {
return ais[2] < bis[2]
}
// If X is same, compare Y
if ais[0] == bis[0] {
return ais[1] < bis[1]
}
// Compare X
return ais[0] < bis[0]
})
fmt.Println(versions)
tested in go playground
// If v1 > v2 return '>'
// If v1 < v2 return '<'
// Otherwise return '='
func CompareVersion(v1, v2 string) byte {
v1Slice := strings.Split(v1, ".")
v2Slice := strings.Split(v2, ".")
var maxSize int
{ // Make them both the same size.
if len(v1Slice) < len(v2Slice) {
maxSize = len(v2Slice)
} else {
maxSize = len(v1Slice)
}
}
v1NSlice := make([]int, maxSize)
v2NSlice := make([]int, maxSize)
{
// Convert string to the int.
for i := range v1Slice {
v1NSlice[i], _ = strconv.Atoi(v1Slice[i])
}
for i := range v2Slice {
v2NSlice[i], _ = strconv.Atoi(v2Slice[i])
}
}
var result byte
var v2Elem int
for i, v1Elem := range v1NSlice {
if result != '=' && result != 0 { // The previous comparison has got the answer already.
return result
}
v2Elem = v2NSlice[i]
if v1Elem > v2Elem {
result = '>'
} else if v1Elem < v2Elem {
result = '<'
} else {
result = '='
}
}
return result
}
Convert "1.05.00.0156" to "0001"+"0005"+"0000"+"0156", then to int64.
Convert "1.0.221.9289" to "0001"+"0000"+"0221"+"9289", then to int64.
Compare the two int64 values.
Try it on the Go playground

Resources