Compare bits in two arrays - go

I've got stuck with ex4.1 for the book which says:
Write a function that counts the number of bits that are different in two SHA256 hashes.
The partial solution I came up with is pasted below, but it's wrong - it counts number of different bytes not bits.
Could you please point me in the right direction?
package main
import (
"crypto/sha256"
"fmt"
)
var s1 string = "unodostresquatro"
var s2 string = "UNODOSTRESQUATRO"
var h1 = sha256.Sum256([]byte(s1))
var h2 = sha256.Sum256([]byte(s2))
func main() {
fmt.Printf("s1: %s h1: %X h1 type: %T\n", s1, h1, h1)
fmt.Printf("s2: %s h2: %X h2 type: %T\n", s2, h2, h2)
fmt.Printf("Number of different bits: %d\n", 8 * DifferentBits(h1, h2))
}
func DifferentBits(c1 [32]uint8, c2 [32]uint8) int {
var counter int
for x := range c1 {
if c1[x] != c2[x] {
counter += 1
}
}
return counter
}

The Go Programming Language
Alan A. A. Donovan · Brian W.Kernighan
Exercise 4.1: Write a function that counts the number of bits that
are different in two SHA256 hashes.
The C Programming Language
Brian W.Kernighan · Dennis M. Ritchie
Exercise 2-9. In a two's complement number system, x &= (x-1) deletes
the rightmost 1-bit in x. Use this observation to write a faster
version of bitcount.
Bit Twiddling Hacks
Sean Eron Anderson
Counting bits set, Brian Kernighan's way
unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
For exercise 4.1, you are counting the number of bytes that are different. Count the number of bits that are different. For example,
package main
import (
"crypto/sha256"
"fmt"
)
func BitsDifference(h1, h2 *[sha256.Size]byte) int {
n := 0
for i := range h1 {
for b := h1[i] ^ h2[i]; b != 0; b &= b - 1 {
n++
}
}
return n
}
func main() {
s1 := "unodostresquatro"
s2 := "UNODOSTRESQUATRO"
h1 := sha256.Sum256([]byte(s1))
h2 := sha256.Sum256([]byte(s2))
fmt.Println(BitsDifference(&h1, &h2))
}
Output:
139

Here is how I would do it
package main
import (
"crypto/sha256"
"fmt"
)
var (
s1 string = "unodostresquatro"
s2 string = "UNODOSTRESQUATRO"
h1 = sha256.Sum256([]byte(s1))
h2 = sha256.Sum256([]byte(s2))
)
func main() {
fmt.Printf("s1: %s h1: %X h1 type: %T\n", s1, h1, h1)
fmt.Printf("s2: %s h2: %X h2 type: %T\n", s2, h2, h2)
fmt.Printf("Number of different bits: %d\n", DifferentBits(h1, h2))
}
// bitCount counts the number of bits set in x
func bitCount(x uint8) int {
count := 0
for x != 0 {
x &= x - 1
count++
}
return count
}
func DifferentBits(c1 [32]uint8, c2 [32]uint8) int {
var counter int
for x := range c1 {
counter += bitCount(c1[x] ^ c2[x])
}
return counter
}
Playground

Related

int vs int32 return value

I am running into an issue, which seems to be related to int32 vs int data type. My program is returning different values on different environments.
For example, on go playground, I notice the value returned is -4 (which is expected value). But the same on Leetcode with same input returns a value of 4294967292. While it returned this value, when I print it, I get -4 (see output added later).
I tried casting to int32(res) but didn't help. Also didn't find any directly related in textbook. Please help me understand why this is different on go playground vs Leetcode.
https://play.golang.org/p/qXMd9frlhbe
package main
import (
"fmt"
)
func main() {
fmt.Printf("%v", singleNumber([]int{-2,-2,1,1,-3,1,-3,-3,-4,-2}))
}
func singleNumber(nums []int) int {
sum := make([]int, 32)
for _, v := range nums {
for i := 0; i < 32; i++ {
if sum[i] != 0 {
sum[i] += 1 & (v >> uint32(i))
} else {
sum[i] = 1 & (v >> uint32(i))
}
}
}
res := 0
for k, v := range sum {
if (v%3) != 0 {
res |= (v%3) << uint32(k)
}
}
fmt.Printf("res %+v\n", res)
return res
}
Same on Leetcode gives the output:
Input:
[-2,-2,1,1,-3,1,-3,-3,-4,-2]
Output:
4294967292
Expected:
-4
Stdout:
res -4
The textbook you are looking for is
The Go Programming Language Specification
Numeric types
A numeric type represents sets of integer or floating-point values.
The predeclared architecture-independent numeric types are:
uint32 set of all unsigned 32-bit integers (0 to 4294967295)
uint64 set of all unsigned 64-bit integers (0 to 18446744073709551615)
int32 set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
There is also a set of predeclared numeric types with
implementation-specific sizes:
uint either 32 or 64 bits
int same size as uint
Check the size of type int. On the Go Playground it's 4 bytes or 32 bits.
package main
import (
"fmt"
"runtime"
"unsafe"
)
func main() {
fmt.Println("arch", runtime.GOARCH)
fmt.Println("int", unsafe.Sizeof(int(0)))
}
Playground: https://play.golang.org/p/2A6ODvhb1Dx
Output (Playground):
arch amd64p32
int 4
Run the program in your (LeetCode) environment. It's likely 8 bytes or 64 bits.
For example, in my environment,
Output (Local):
arch amd64
int 8
Here are some fixes to your code,
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.GOARCH)
fmt.Printf("%v\n", singleNumber([]int{-2, -2, 1, 1, -3, 1, -3, -3, -4, -2}))
}
func singleNumber(nums []int) int {
sum := make([]int, 64)
for _, v := range nums {
for i := range sum {
sum[i] += 1 & (v >> uint(i))
}
}
res := 0
for k, v := range sum {
if (v % 3) != 0 {
res |= (v % 3) << uint(k)
}
}
fmt.Printf("res %+v\n", res)
return res
}
Playground: https://play.golang.org/p/kaoSuesu2Oj
Output (Playground):
amd64p32
res -4
-4
Output (Local):
amd64
res -4
-4

Too many results in a loop for Project Euler #145

I am trying to create a solution for Project Euler #145. I am writing in Go. When I run my program I get a result of 125. The expected result is 120. I have 2 different ways I have tried to write the code but both come up with the same answer. Any help pointing out my error would be appreciated.
Code option #1 using strings:
package main
import (
"fmt"
"strconv"
)
//checks to see if all the digits in the number are odd
func is_Odd(sum int) bool {
intString := strconv.Itoa(sum)
for x := len(intString); x > 0; x-- {
newString := intString[x-1]
if newString%2 == 0 {
return false
}
}
return true
}
//reverse the number passed
func reverse_int(value int) int {
intString := strconv.Itoa(value)
newString := ""
for x := len(intString); x > 0; x-- {
newString += string(intString[x-1])
}
newInt, err := strconv.Atoi(newString)
if err != nil {
fmt.Println("Error converting string to int")
}
return newInt
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
func main() {
//functions test code
/*y := 35
x := reverse_int(y)
z := add(x,y)
fmt.Println(is_Odd(z))*/
counter := 1
for i := 1; i < 1000; i++ {
flipped := reverse_int(i)
sum := add(flipped, i)
oddCheck := is_Odd(sum)
if oddCheck {
fmt.Println(counter, ":", i, "+", flipped, "=", sum)
counter++
}
}
counter--
fmt.Println("total = ", counter)
}
Code option #2 using only ints:
package main
import (
"fmt"
)
var counter int
//breaks down an int number by number and checks to see if
//all the numbers in the int are odd
func is_Odd(n int) bool {
for n > 0 {
remainder := n % 10
if remainder%2 == 0 {
return false
}
n /= 10
}
return true
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
//reverses the int passed to it and returns an int
func reverse_int(n int) int {
var new_int int
for n > 0 {
remainder := n % 10
new_int *= 10
new_int += remainder
n /= 10
}
return new_int
}
func main() {
//functions test code
/*y := 35
x := reverse_int(y)
z := add(x,y)
fmt.Println(is_Odd(z))*/
counter = 1
for i := 1; i < 1000; i++ {
flipped := reverse_int(i)
sum := add(flipped, i)
oddCheck := is_Odd(sum)
if oddCheck {
//fmt.Println(counter,":",i,"+",flipped,"=",sum)
counter++
}
}
counter--
fmt.Println(counter)
}
Leading zeroes are not allowed in either n or reverse(n) so in reverse(n int) int remove Leading zeroes like so:
remainder := n % 10
if first {
if remainder == 0 {
return 0
}
first = false
}
try this:
package main
import (
"fmt"
)
//breaks down an int number by number and checks to see if
//all the numbers in the int are odd
func isOdd(n int) bool {
if n <= 0 {
return false
}
for n > 0 {
remainder := n % 10
if remainder%2 == 0 {
return false
}
n /= 10
}
return true
}
//adds 2 int's passed to it and returns an int
func add(x int, y int) int {
return x + y
}
//reverses the int passed to it and returns an int
func reverse(n int) int {
first := true
t := 0
for n > 0 {
remainder := n % 10
if first {
if remainder == 0 {
return 0
}
first = false
}
t *= 10
t += remainder
n /= 10
}
return t
}
func main() {
counter := 0
for i := 0; i < 1000; i++ {
flipped := reverse(i)
if flipped == 0 {
continue
}
sum := add(flipped, i)
if isOdd(sum) {
counter++
//fmt.Println(counter, ":", i, "+", flipped, "=", sum)
}
}
fmt.Println(counter)
}
output:
120
You're ignoring this part of the criteria:
Leading zeroes are not allowed in either n or reverse(n).
Five of the numbers you count as reversible end in 0. (That means their reverse has a leading zero.) Stop counting those as reversible and you're done.
Some positive integers n have the property that the sum [ n +
reverse(n) ] consists entirely of odd (decimal) digits. For instance,
36 + 63 = 99 and 409 + 904 = 1313. We will call such numbers
reversible; so 36, 63, 409, and 904 are reversible. Leading zeroes are
not allowed in either n or reverse(n).
All digits of the sum must all be odd.
Try this one: https://play.golang.org/p/aUlvKrb9SB

Generate combinations from a given range

I'm trying to create a program capable to generate combinations from a given range.
I started editing this code below that generates combinations:
package main
import "fmt"
func nextPassword(n int, c string) func() string {
r := []rune(c)
p := make([]rune, n)
x := make([]int, len(p))
return func() string {
p := p[:len(x)]
for i, xi := range x {
p[i] = r[xi]
}
for i := len(x) - 1; i >= 0; i-- {
x[i]++
if x[i] < len(r) {
break
}
x[i] = 0
if i <= 0 {
x = x[0:0]
break
}
}
return string(p)
}
}
func main() {
np := nextPassword(2, "ABCDE")
for {
pwd := np()
if len(pwd) == 0 {
break
}
fmt.Println(pwd)
}
}
This is the Output of the code:
AA
AB
AC
AD
AE
BA
BB
BC
BD
BE
CA
CB
CC
CD
CE
DA
DB
DC
DD
DE
EA
EB
EC
ED
EE
And this is the code I edited:
package main
import "fmt"
const (
Min = 5
Max = 10
)
func nextPassword(n int, c string) func() string {
r := []rune(c)
p := make([]rune, n)
x := make([]int, len(p))
return func() string {
p := p[:len(x)]
for i, xi := range x {
p[i] = r[xi]
}
for i := len(x) - 1; i >= 0; i-- {
x[i]++
if x[i] < len(r) {
break
}
x[i] = 0
if i <= 0 {
x = x[0:0]
break
}
}
return string(p)
}
}
func main() {
cont := 0
np := nextPassword(2, "ABCDE")
for {
pwd := np()
if len(pwd) == 0 {
break
}
if cont >= Min && cont <= Max{
fmt.Println(pwd)
} else if cont > Max{
break
}
cont += 1
}
}
Output:
BA
BB
BC
BD
BE
CA
My code works, but if I increase the length of the combination and my range starts from the middle, the program will generate even the combinations that I don't want (and of course that will take a lot of time).
How can I solve this problem?
I really didn't like how nextPassword was written, so I made a variation. Rather than starting at 0 and repeatedly returning the next value, this one takes an integer and converts it to the corresponding "password." E.g. toPassword(0, 2, []rune("ABCDE")) is AA, and toPassword(5, ...) is BA.
From there, it's easy to loop over whatever range you want. But I also wrote a nextPassword wrapper around it that behaves similarly to the one in the original code. This one uses toPassword under the cover and takes a starting n.
Runnable version here: https://play.golang.org/p/fBo6mx4Mji
Code below:
package main
import (
"fmt"
)
func toPassword(n, length int, alphabet []rune) string {
base := len(alphabet)
// This will be our output
result := make([]rune, length)
// Start filling from the right
i := length - 1
// This is essentially a conversion to base-b, where b is
// the number of possible letters (5 in the case of "ABCDE")
for n > 0 {
// Filling from the right, put the right digit mod b
result[i] = alphabet[n%base]
// Divide the number by the base so we're ready for
// the next digit
n /= base
// Move to the left
i -= 1
}
// Fill anything that's left with "zeros" (first letter of
// the alphabet)
for i >= 0 {
result[i] = alphabet[0]
i -= 1
}
return string(result)
}
// Convenience function that just returns successive values from
// toPassword starting at start
func nextPassword(start, length int, alphabet []rune) func() string {
n := start
return func() string {
result := toPassword(n, length, alphabet)
n += 1
return result
}
}
func main() {
for i := 5; i < 11; i++ {
fmt.Println(toPassword(i, 2, []rune("ABCDE")))
} // BA, BB, BC, BD, BE, CA
// Now do the same thing using nextPassword
np := nextPassword(5, 2, []rune("ABCDE"))
for i := 0; i < 6; i++ {
fmt.Println(np())
} // BA, BB, BC, BD, BE, CA
}

Detect signed int overflow in Go

I'm building a Lisp, and I want 32 bit integers to automatically switch to 64 bit integers if a computation would cause them to otherwise overflow. And likewise, for 64 bit overflows, switch to arbitrarily sized integers.
The problem I have is that I don't know what the "correct" way is to detect an integer overflow.
a, b := 2147483647, 2147483647
c := a + b
How can I efficiently check if c overflowed?
I have considered always converting to 64 bit values to do the calculation, then down-sizing again afterwards when possible, but that seems expensive and memory wasteful for something that is as primitive and core to the language as basic arithmetic.
For example, to detect 32-bit integer overflow for addition,
package main
import (
"errors"
"fmt"
"math"
)
var ErrOverflow = errors.New("integer overflow")
func Add32(left, right int32) (int32, error) {
if right > 0 {
if left > math.MaxInt32-right {
return 0, ErrOverflow
}
} else {
if left < math.MinInt32-right {
return 0, ErrOverflow
}
}
return left + right, nil
}
func main() {
var a, b int32 = 2147483327, 2147483327
c, err := Add32(a, b)
if err != nil {
// handle overflow
fmt.Println(err, a, b, c)
}
}
Output:
integer overflow 2147483327 2147483327 0
For 32 bit integers, the standard way is as you said, to cast to 64 bit, then down size again [1]:
package main
func add32(x, y int32) (int32, int32) {
sum64 := int64(x) + int64(y)
return x + y, int32(sum64 >> 31)
}
func main() {
{
s, c := add32(2147483646, 1)
println(s == 2147483647, c == 0)
}
{
s, c := add32(2147483647, 1)
println(s == -2147483648, c == 1)
}
}
However if you don't like that, you can use some bit operations [2]:
func add32(x, y int32) (int32, int32) {
sum := x + y
return sum, x & y | (x | y) &^ sum >> 30
}
https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L368-L373
https://github.com/golang/go/blob/go1.16.3/src/math/bits/bits.go#L380-L387

Convert rune to int?

In the following code, I iterate over a string rune by rune, but I'll actually need an int to perform some checksum calculation. Do I really need to encode the rune into a []byte, then convert it to a string and then use Atoi to get an int out of the rune? Is this the idiomatic way to do it?
// The string `s` only contains digits.
var factor int
for i, c := range s[:12] {
if i % 2 == 0 {
factor = 1
} else {
factor = 3
}
buf := make([]byte, 1)
_ = utf8.EncodeRune(buf, c)
value, _ := strconv.Atoi(string(buf))
sum += value * factor
}
On the playground: http://play.golang.org/p/noWDYjn5rJ
The problem is simpler than it looks. You convert a rune value to an int value with int(r). But your code implies you want the integer value out of the ASCII (or UTF-8) representation of the digit, which you can trivially get with r - '0' as a rune, or int(r - '0') as an int. Be aware that out-of-range runes will corrupt that logic.
For example, sum += (int(c) - '0') * factor,
package main
import (
"fmt"
"strconv"
"unicode/utf8"
)
func main() {
s := "9780486653556"
var factor, sum1, sum2 int
for i, c := range s[:12] {
if i%2 == 0 {
factor = 1
} else {
factor = 3
}
buf := make([]byte, 1)
_ = utf8.EncodeRune(buf, c)
value, _ := strconv.Atoi(string(buf))
sum1 += value * factor
sum2 += (int(c) - '0') * factor
}
fmt.Println(sum1, sum2)
}
Output:
124 124
why don't you do only "string(rune)".
s:="12345678910"
var factor,sum int
for i,x:=range s{
if i%2==0{
factor=1
}else{
factor=3
}
xstr:=string(x) //x is rune converted to string
xint,_:=strconv.Atoi(xstr)
sum+=xint*factor
}
fmt.Println(sum)
val, _ := strconv.Atoi(string(v))
Where v is a rune
More concise but same idea as above

Resources