A tuple assignment in Go - go

From spec:
A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right-hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left-hand side must match the number of values. For instance, if f is a function returning two values, x, y = f() assigns the first value to x and the second to y. In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left: one, two, three = '一', '二', '三'
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in the left-to-right order.
Using this code ( i, n = i+2, n-1 inside for loop) :
package main
import (
"fmt"
"math"
)
func main() {
p := &Prime{}
p.Generate(1000000)
fmt.Println(p.Last()) // 15485863
}
func (p *Prime) Generate(n uint) {
p.Primes = make([]uint64, 1, n)
p.Primes[0] = 2
next:
for i := uint64(3); n > 1; i, n = i+2, n-1 {
q := uint64(math.Sqrt(float64(i)))
for _, v := range p.Primes[1:] {
if v > q {
break
}
if i%v == 0 {
continue next
}
}
p.Primes = append(p.Primes, i)
// n--
}
}
type Prime struct {
Primes []uint64
}
func (p *Prime) Last() uint64 {
return p.Primes[len(p.Primes)-1]
}
Output is:
1999993
This is not a correct result.
And this code:
func (p *Prime) Generate(n uint) {
p.Primes = make([]uint64, 1, n)
p.Primes[0] = 2
next:
for i := uint64(3); n > 1; i += 2 {
q := uint64(math.Sqrt(float64(i)))
for _, v := range p.Primes[1:] {
if v > q {
break
}
if i%v == 0 {
continue next
}
}
p.Primes = append(p.Primes, i)
n--
}
}
The output is correct:
15485863
go version go1.11.5 linux/amd64
Am I missing something on tuple Assignments in Go?
Thanks in advance.

Nope, it is not tuple assignment that gives wrong result.
There is a subtle difference between the two code, which causes the bug. In the playgound code, i,n = i+2,n-1 makes n = n-1 runs everytimes the loop is iterated, while the github code only runs n = n-1 when i is a prime (it skips n-- if continue next runs).

Related

go method - pointer receiver and returning same pointer

A go method on struct receives pointer reference, made some modifications and returning same pointer. The struct has nested reference of same struct: when append method being called with values some reason it was loosing previous values.
package main
import (
"fmt"
)
type Node struct{
next *Node
val int
}
func newNode(val int) (*Node){
n := Node{
val: val,
}
return &n
}
func (n *Node) append(val int) (*Node){
for n.next != nil {
n = n.next
}
n.next = newNode(val)
return n
}
func (n *Node)printList(){
for n != nil {
fmt.Printf("%d,", n.val)
n = n.next
}
fmt.Println()
}
func main() {
n := newNode(3)
n.printList()
n = n.append(4)
n.printList()
n = n.append(5)
n.printList()
n = n.append(6)
n.printList()
}
output:
3,
3,4,
4,5,
5,6,
I was expecting 3,4,5,6, - Probably something I totally missing something fundamentals here. appreciate if you have some inputs.
https://play.golang.org/p/-zDH98UNFLa
I was getting expected results when I modify append method not return anything.
append() returns the pointer of the next node. Therefore printList() only print the nodes starting from the next node. If you'd like to print the all nodes in the list, you should add a variable to store the pointer referenced to the starting node of this list.
func main() {
n := newNode(3)
head := n
head.printList()
n = n.append(4)
head.printList()
n = n.append(5)
head.printList()
n = n.append(6)
head.printList() // 3,4,5,6
}
This function:
func (n *Node) append(val int) (*Node){
for n.next != nil {
n = n.next
}
n.next = newNode(val)
return n
}
does not return its original argument in general. It returns the node that is next-to-last in the (assumed to be non-empty) list. Hence:
n = n.append(4)
adds a node holding 4 to the original node holding 3, then returns the original node holding 3, but:
n = n.append(5)
adds a node holding 5 to the original list, but then returns a pointer to the node holding 4. That's why you see 4,5, at this point. Subsequent calls keep repeating the last two elements for the same reason.
You could modify your append function to save the original return value and return that:
func (n *Node) append(val int) *Node {
// find current tail
t := n
for t.next != nil {
t = t.next
}
t.next = newNode(val)
return n
}
but overall this is still not a great strategy: this append does not work when given a nil-valued n, for instance. Consider constructing a list type that does handle such cases. Alternatively, as in Hsaio's answer, you can have the caller hang on to the head node directly. If you do that you could have the append function return the tail pointer:
func (n *Node) append(val int) *Node {
n.next = newNode(val)
return n.next
}
and then use it like this:
head := newNode(3)
t := append(head, 4)
t = append(t, 5)
t = append(t, 6)
head.printList()
(There's already a List implementation in the standard Go packages, container/list, that does this stuff nicely for you. Instead of pointing directly to each element in your list, you create an overall list-container instance, which allows you to insert-at-front, insert-at-back, remove-from-anywhere, and so on. It's a little awkward in that it uses interface{} for the data, so it requires a type-assertion to get each node's value.)
The variable n in main function is overrided by n in append function.

++ operator for map key loop in go

I am following the Go tutorial here https://tour.golang.org/moretypes/23 and have modified the exercise a little bit to try to dig deeper.
package main
import (
"fmt"
"strings"
)
func WordCount(s string) map[string]int {
m := make(map[string]int)
x := strings.Fields(s)
for _, e := range x {
m[e]++
}
return m
}
func main() {
phrase := "The quick brown fox"
fmt.Println(WordCount(phrase), "length:", len(WordCount(phrase)))
}
What doesn't make sense to me is how the ++ operator works in this context when adding new elements to the map.
Definition of ++ operator: Increment operator. It increases the integer value by one.
In this context, the ++ operator increasing the integer value of the LENGTH of the map and then adding the e element to the new map length?
The default value of int values in a map is 0. So, when you iterate through x and call m[e]++, the expanded version would be
m[e] = m[e] + 1
In other words:
m[e] = 0 + 1
Of course, if a field repeats, it will already be in the map (with some value > 0).
When you check the length of the map after the loop, it gives the number of unique fields in the string.

Arrays compare in golang

I need to compare 2 arrays of uint32, something like this
func in(a uint32, list []uint32) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
for n := 0 ;n < len(a); n++ {
fmt.Println(in(a[n], b))
}
// a and b []uint32
but I think it is not the most optimal way
Why not just use == if you are actually using arrays?
https://golang.org/ref/spec#Comparison_operators
Array values are comparable if values of the array element type are comparable. Two array values are equal if their corresponding elements are equal.
If you are using slices, you can use reflect.DeepEqual.
But, from your code, it seems like you should look into https://godoc.org/golang.org/x/tools/container/intsets
Then, you create your two intsets.Sparse and could then do:
func main() {
s1 := intsets.Sparse{}
s2 := intsets.Sparse{}
s1.Insert(1)
s1.Insert(2)
s1.Insert(3)
s2.Insert(1)
s2.Insert(2)
//s1:{1,2,3}
//s2:{1,2}
fmt.Println(s1.SubsetOf(&s2), s2.SubsetOf(&s1))
//false, true
}
which will ignore duplicates, but let you know if s1 is a subset of s2, meaning every element in s1 exists in s2.

What is the correct way to find the min between two integers in Go?

I imported the math library in my program, and I was trying to find the minimum of three numbers in the following way:
v1[j+1] = math.Min(v1[j]+1, math.Min(v0[j+1]+1, v0[j]+cost))
where v1 is declared as:
t := "stackoverflow"
v1 := make([]int, len(t)+1)
However, when I run my program I get the following error:
./levenshtein_distance.go:36: cannot use int(v0[j + 1] + 1) (type int) as type float64 in argument to math.Min
I thought it was weird because I have another program where I write
fmt.Println(math.Min(2,3))
and that program outputs 2 without complaining.
so I ended up casting the values as float64, so that math.Min could work:
v1[j+1] = math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost)))
With this approach, I got the following error:
./levenshtein_distance.go:36: cannot use math.Min(int(v1[j] + 1), math.Min(int(v0[j + 1] + 1), int(v0[j] + cost))) (type float64) as type int in assignment
so to get rid of the problem, I just casted the result back to int
I thought this was extremely inefficient and hard to read:
v1[j+1] = int(math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost))))
I also wrote a small minInt function, but I think this should be unnecessary because the other programs that make use of math.Min work just fine when taking integers, so I concluded this has to be a problem of my program and not the library per se.
Is there anything that I'm doing terrible wrong?
Here's a program that you can use to reproduce the issues above, line 36 specifically:
package main
import (
"math"
)
func main() {
LevenshteinDistance("stackoverflow", "stackexchange")
}
func LevenshteinDistance(s string, t string) int {
if s == t {
return 0
}
if len(s) == 0 {
return len(t)
}
if len(t) == 0 {
return len(s)
}
v0 := make([]int, len(t)+1)
v1 := make([]int, len(t)+1)
for i := 0; i < len(v0); i++ {
v0[i] = i
}
for i := 0; i < len(s); i++ {
v1[0] = i + 1
for j := 0; j < len(t); j++ {
cost := 0
if s[i] != t[j] {
cost = 1
}
v1[j+1] = int(math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost))))
}
for j := 0; j < len(v0); j++ {
v0[j] = v1[j]
}
}
return v1[len(t)]
}
Until Go 1.18 a one-off function was the standard way; for example, the stdlib's sort.go does it near the top of the file:
func min(a, b int) int {
if a < b {
return a
}
return b
}
You might still want or need to use this approach so your code works on Go versions below 1.18!
Starting with Go 1.18, you can write a generic min function which is just as efficient at run time as the hand-coded single-type version, but works with any type with < and > operators:
func min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
func main() {
fmt.Println(min(1, 2))
fmt.Println(min(1.5, 2.5))
fmt.Println(min("Hello", "世界"))
}
There's been discussion of updating the stdlib to add generic versions of existing functions, but if that happens it won't be until a later version.
math.Min(2, 3) happened to work because numeric constants in Go are untyped. Beware of treating float64s as a universal number type in general, though, since integers above 2^53 will get rounded if converted to float64.
There is no built-in min or max function for integers, but it’s simple to write your own. Thanks to support for variadic functions we can even compare more integers with just one call:
func MinOf(vars ...int) int {
min := vars[0]
for _, i := range vars {
if min > i {
min = i
}
}
return min
}
Usage:
MinOf(3, 9, 6, 2)
Similarly here is the max function:
func MaxOf(vars ...int) int {
max := vars[0]
for _, i := range vars {
if max < i {
max = i
}
}
return max
}
For example,
package main
import "fmt"
func min(x, y int) int {
if x < y {
return x
}
return y
}
func main() {
t := "stackoverflow"
v0 := make([]int, len(t)+1)
v1 := make([]int, len(t)+1)
cost := 1
j := 0
v1[j+1] = min(v1[j]+1, min(v0[j+1]+1, v0[j]+cost))
fmt.Println(v1[j+1])
}
Output:
1
Though the question is quite old, maybe my package imath can be helpful for someone who does not like reinventing a bicycle. There are few functions, finding minimal of two integers: ix.Min (for int), i8.Min (for int8), ux.Min (for uint) and so on. The package can be obtained with go get, imported in your project by URL and functions referred as typeabbreviation.FuncName, for example:
package main
import (
"fmt"
"<Full URL>/go-imath/ix"
)
func main() {
a, b := 45, -42
fmt.Println(ix.Min(a, b)) // Output: -42
}
As the accepted answer states, with the introduction of generics in go 1.18 it's now possible to write a generic function that provides min/max for different numeric types (there is not one built into the language). And with variadic arguments we can support comparing 2 elements or a longer list of elements.
func Min[T constraints.Ordered](args ...T) T {
min := args[0]
for _, x := range args {
if x < min {
min = x
}
}
return min
}
func Max[T constraints.Ordered](args ...T) T {
max := args[0]
for _, x := range args {
if x > max {
max = x
}
}
return max
}
example calls:
Max(1, 2) // 2
Max(4, 5, 3, 1, 2) // 5
Could use https://github.com/pkg/math:
import (
"fmt"
"github.com/pkg/math"
)
func main() {
a, b := 45, -42
fmt.Println(math.Min(a, b)) // Output: -42
}
Since the issue has already been resolved, I would like to add a few words. Always remember that the math package in Golang operates on float64. You can use type conversion to cast int into a float64. Keep in mind to account for type ranges. For example, you cannot fit a float64 into an int16 if the number exceeds the limit for int16 which is 32767. Last but not least, if you convert a float into an int in Golang, the decimal points get truncated without any rounding.
If you want the minimum of a set of N integers you can use (assuming N > 0):
import "sort"
func min(set []int) int {
sort.Slice(set, func(i, j int) bool {
return set[i] < set[j]
})
return set[0]
}
Where the second argument to min function is your less function, that is, the function that decides when an element i of the passed slice is less than an element j
Check it out here in Go Playground: https://go.dev/play/p/lyQYlkwKrsA

GO - switch statement in a recursive function

I have an algorithm that I'm trying to implement but currently I have absolutely no clue how to do so, from a technical perspective.
We have a slice of 5 floats:
mySlice := [float1, float2, float3, float4, float5]
And a switch statement:
aFloat := mySlice[index]
switch aFloat {
case 1:
{
//do something
}
case 2:
{
//do something
}
case 3:
{
//do something
}
case 4:
{
//do something
}
case 5:
{
//do something
}
default:
{
//somehow go back to slice, take the next smallest and run
//through the switch statement again
}
}
What I want to do is as follows:
identify the smallest element of mySlice ex: smallestFloat
run smallestFloat through the switch statement
if smallestFloat gets to default case take the next smallest float from mySlice
do step 2 again.
I've managed to do the first step with a for loop and step 2, but I'm stuck on steps 3 and 4. I don't have an idea at the moment on how I might go about re-feeding the next smallest float from mySlice to the switch statement again...
I would appreciate any light shed on my problem.
EDIT: I figured that it would be good to put my solution to the algorithm presented above.
create another slice which will be a sorted version of mySlice
create a map[int]value where the index will correspond to the position of the value in the non-sorted slice, but the items of the map will be inserted in the same order as the sorted slice.
Result: a value sorted map with the respective indexes corresponding to the position of the original non-sorted slice
Here is an implementation using a Minimum Priority Queue. The original input slice of floats is not changed. It can be run on the Go playground
Note: When dealing with recursive functions, you need to be weary of stack overflows.
Go does tail recursion optimizations only in limited cases. For more information on that,
refer to this answer.
This particular example does even better than amortized O(log N) time, because it does not have to resize the priority queue halfway through. This makes it guaranteed O(log N).
package main
import (
"fmt"
)
func main() {
slice := []float64{2, 1, 13, 4, 22, 0, 5, 7, 3}
fmt.Printf("Order before: %v\n", slice)
queue := NewMinPQ(slice)
for !queue.Empty() {
doSmallest(queue)
}
fmt.Printf("Order after: %v\n", slice)
}
func doSmallest(queue *MinPQ) {
if queue.Empty() {
return
}
v := queue.Dequeue()
switch v {
case 1:
fmt.Println("Do", v)
case 2:
fmt.Println("Do", v)
case 3:
fmt.Println("Do", v)
case 4:
fmt.Println("Do", v)
case 5:
fmt.Println("Do", v)
default:
// No hit, do it all again with the next value.
doSmallest(queue)
}
}
// MinPQ represents a Minimum priority queue.
// It is implemented as a binary heap.
//
// Values which are enqueued can be dequeued, but will be done
// in the order where the smallest item is returned first.
type MinPQ struct {
values []float64 // Original input list -- Order is never changed.
indices []int // List of indices into values slice.
index int // Current size of indices list.
}
// NewMinPQ creates a new MinPQ heap for the given input set.
func NewMinPQ(set []float64) *MinPQ {
m := new(MinPQ)
m.values = set
m.indices = make([]int, 1, len(set))
// Initialize the priority queue.
// Use the set's indices as values, instead of the floats
// themselves. As these may not be re-ordered.
for i := range set {
m.indices = append(m.indices, i)
m.index++
m.swim(m.index)
}
return m
}
// Empty returns true if the heap is empty.
func (m *MinPQ) Empty() bool { return m.index == 0 }
// Dequeue removes the smallest item and returns it.
// Returns nil if the heap is empty.
func (m *MinPQ) Dequeue() float64 {
if m.Empty() {
return 0
}
min := m.indices[1]
m.indices[1], m.indices[m.index] = m.indices[m.index], m.indices[1]
m.index--
m.sink(1)
m.indices = m.indices[:m.index+1]
return m.values[min]
}
// greater returns true if element x is greater than element y.
func (m *MinPQ) greater(x, y int) bool {
return m.values[m.indices[x]] > m.values[m.indices[y]]
}
// sink reorders the tree downwards.
func (m *MinPQ) sink(k int) {
for 2*k <= m.index {
j := 2 * k
if j < m.index && m.greater(j, j+1) {
j++
}
if m.greater(j, k) {
break
}
m.indices[k], m.indices[j] = m.indices[j], m.indices[k]
k = j
}
}
// swim reorders the tree upwards.
func (m *MinPQ) swim(k int) {
for k > 1 && m.greater(k/2, k) {
m.indices[k], m.indices[k/2] = m.indices[k/2], m.indices[k]
k /= 2
}
}

Resources