How to find out diagonal difference in go programming? - go

My code:
package main
import "fmt"
func main() {
var n int
fmt.Scan(&n)
s := make([][]int, n)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
fmt.Scanf("%d %d", &s[i][j])
}
}
s1 := 0
s2 := 0
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
if i == j {
s1 += s[i][j]
}
if i+j == n-1 {
s2 += s[i][j]
}
}
fmt.Println(s1 - s2)
}
}
Output:
panic: runtime error: index out of range
I tried but get panic. I want to know proper solution to this problem.

This line:
s := make([][]int, n)
Creates a slice of slices, a slice whose elements are of type []int. It creates a slice with n elements, but the elements of the outer slice are initialized with the zero value of the element type, and zero value of type []int is nil (just like for any slice type).
You get index out of range panic because any element of the outer slice s has zero length (because they are not initialized to a non-nil slice), so s[i][j] panics for any j value.
If you want to assign elements to the "inner" slices, you also have to initialize them:
for i := 0; i < n; i++ {
s[i] = make([]int, n) // YOU ARE MISSING THIS LINE
for j := 0; j < n; j++ {
fmt.Scanf("%d %d", &s[i][j])
}
}

Related

Golang for loop with 2 variables equivalent?

I am trying to understand golang's syntax in doc but some things are hard to understand even they explain it.
For example:
func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
I translated it to raw code:
func reverseString2(str string) string {
var array = []rune(str)
for i := 0; i < len(str)/2; i++ {
for j := len(str) - 1; ???? ; j-- {
// ---
}
}
return string(array)
}
my problem is that in the first one for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1, j does not seems to have a condition so in my code I dont know how to solve it.
This is another way that is easier to read and leads to the same result.
The only difference is that the scope of variable j has become different.
func Reverse(s string) string {
r := []rune(s)
j := len(r) - 1
for i := 0; i < len(r)/2; i++ {
r[i], r[j] = r[j], r[i]
j--
}
return string(r)
}

"Matrix multiplication" using goroutines and channels

I have a university project for testing time difference for matrix multiplication when I use 1 goroutine, 2 goroutines, 3 and so on. I must use channels. My problem is that doesn't matter how many go routines I add time of compilation is almost always the same. Maybe some one can tell where is the problem. Maybe that sending is very long and it gives all the time. Code is given below
package main
import (
"fmt"
"math/rand"
"time"
)
const length = 1000
var start time.Time
var rez [length][length]int
func main() {
const threadlength = 1
toCalcRow := make(chan []int)
toCalcColumn := make(chan []int)
dummy1 := make(chan int)
dummy2 := make(chan int)
var row [length + 1]int
var column [length + 1]int
var a [length][length]int
var b [length][length]int
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
a[i][j] = rand.Intn(10)
b[i][j] = rand.Intn(10)
}
}
for i := 0; i < threadlength; i++ {
go Calc(toCalcRow, toCalcColumn, dummy1, dummy2)
}
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
row[0] = i
column[0] = j
for k := 0; k < length; k++ {
row[k+1] = a[i][j]
column[k+1] = b[i][k]
}
rowSlices := make([]int, len(row))
columnSlices := make([]int, len(column))
copy(rowSlices, row[:])
copy(columnSlices, column[:])
toCalcRow <- rowSlices
toCalcColumn <- columnSlices
}
}
dummy1 <- -1
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
fmt.Print(rez[i][j])
fmt.Print(" ")
}
fmt.Println(" ")
}
<-dummy2
close(toCalcRow)
close(toCalcColumn)
close(dummy1)
}
func Calc(chin1 <-chan []int, chin2 <-chan []int, dummy <-chan int, dummy1 chan<- int) {
loop:
for {
select {
case row := <-chin1:
column := <-chin2
var sum [3]int
sum[0] = row[0]
sum[1] = column[0]
for i := 1; i < len(row); i++ {
sum[2] += row[i] * column[i]
}
rez[sum[0]][sum[1]] = sum[2]
case <-dummy:
elapsed := time.Since(start)
fmt.Println("Binomial took ", elapsed)
dummy1 <- 0
break loop
}
}
close(dummy1)
}
You don't see a difference because preparing the data to pass to the go routines is your bottleneck. It's slower or as fast as performing the calc.
Passing a copy of the rows and columns is not a good strategy. This is killing the performance.
The go routines may read data directly from the input matrix that are read only. There is no possible race condition here.
Same for output. If a go routine computes the multiplication of a row and a column, it will write the result in a distinct cell. There is also no possible race conditions here.
What to do is the following. Define a struct with two fields, one for the row and one for the column to multiply.
Fill a buffered channel with all possible combinations of row and columns to multiply from (0,0) to (n-1,m-1).
The go routines, consume the structs from the channel, perform the computation and write the result directly into the output matrix.
You then also have a done channel to signal to the main go routine that the computation is done. When a go routine has finished processing the struct (n-1,m-1) it closes the done channel.
The main go routine waits on the done channel after it has written all structs. Once the done channel is closed, it prints the elapsed time.
We can use a waiting group to wait that all go routine terminated their computation.
You can then start with one go routine and increase the number of go routines to see the impact of the processing time.
See the code:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type pair struct {
row, col int
}
const length = 1000
var start time.Time
var rez [length][length]int
func main() {
const threadlength = 1
pairs := make(chan pair, 1000)
var wg sync.WaitGroup
var a [length][length]int
var b [length][length]int
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
a[i][j] = rand.Intn(10)
b[i][j] = rand.Intn(10)
}
}
wg.Add(threadlength)
for i := 0; i < threadlength; i++ {
go Calc(pairs, &a, &b, &rez, &wg)
}
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
pairs <- pair{row: i, col: j}
}
}
close(pairs)
wg.Wait()
elapsed := time.Since(start)
fmt.Println("Binomial took ", elapsed)
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
fmt.Print(rez[i][j])
fmt.Print(" ")
}
fmt.Println(" ")
}
}
func Calc(pairs chan pair, a, b, rez *[length][length]int, wg *sync.WaitGroup) {
for {
pair, ok := <-pairs
if !ok {
break
}
rez[pair.row][pair.col] = 0
for i := 0; i < length; i++ {
rez[pair.row][pair.col] += a[pair.row][i] * b[i][pair.col]
}
}
wg.Done()
}
Your code is quite difficult to follow (calling variables dummy1/dummy2 is confusing particularly when they get different names in Calc) and adding some comments would make it more easily understood.
Firstly a bug. After sending data to be calculated you dummy1 <- -1 and I believe you expect this to wait for all calculations to be complete. However that is not necessarily the case when you have multiple goroutines. The channel will be drained by ONE of the goroutines and the timing info printed out; other goroutines will still be running (and may not have finnished their calculations).
In terms of timing I suspect that the way you are sending data to the go routines will slow things down; you send the row and then the column; because the channels are not buffered the goroutine will block while waiting for the column (switching back to the main goroutine to send the column). This back and forth will slow the rate at which your goroutines get data and may well explain why adding extra goroutines has a limited impact (it also becomes dangerous if you use buffered channels).
I have refactored your code (note there may be bugs and its far from perfect!) into something that does show a difference (on my computer 1 goroutine = 10s; 5 = 7s):
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const length = 1000
var start time.Time
var rez [length][length]int
// toMultiply will hold details of what the goroutine will be multiplying (one row and one column)
type toMultiply struct {
rowNo int
columnNo int
row []int
column []int
}
func main() {
const noOfGoRoutines = 5
// Build up a matrix of dimensions (length) x (length)
var a [length][length]int
var b [length][length]int
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
a[i][j] = rand.Intn(10)
b[i][j] = rand.Intn(10)
}
}
// Setup completed so start the clock...
start = time.Now()
// Start off threadlength go routines to multiply each row/column
toCalc := make(chan toMultiply)
var wg sync.WaitGroup
wg.Add(noOfGoRoutines)
for i := 0; i < noOfGoRoutines; i++ {
go func() {
Calc(toCalc)
wg.Done()
}()
}
// Begin the multiplication.
start = time.Now()
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
tm := toMultiply{
rowNo: i,
columnNo: j,
row: make([]int, length),
column: make([]int, length),
}
for k := 0; k < length; k++ {
tm.row[k] = a[i][j]
tm.column[k] = b[i][k]
}
toCalc <- tm
}
}
// All of the data has been sent to the chanel; now we need to wait for all of the
// goroutines to complete
close(toCalc)
wg.Wait()
fmt.Println("Binomial took ", time.Since(start))
// The full result should be in tz
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
//fmt.Print(rez[i][j])
//fmt.Print(" ")
}
//fmt.Println(" ")
}
}
// Calc - Multiply a row from one matrix with a column from another
func Calc(toCalc <-chan toMultiply) {
for tc := range toCalc {
var result int
for i := 0; i < len(tc.row); i++ {
result += tc.row[i] * tc.column[i]
}
// warning - the below should work in this case but be careful writing to global variables from goroutines
rez[tc.rowNo][tc.columnNo] = result
}
}

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

Writing next Permutation in Go using closure, what is wrong with my code

I have written a function "iterPermutation" which uses closure. I want to return array and boolean from the closure which I could not do. So tried only array but it still gives an error
cannot use func literal (type func() []int) as type []int in return
argument
I want to use iterPermutation like
a := []int{0,1,2,3,4}
nextPermutation, exists := iterPermutation(a)
for exists {
nextPermutation()
}
func iterPermutation(a []int) []int {
return func() []int {
i := len(a) - 2
for i >= 0 && a[i+1] <= a[i] {
i--
}
if i < 0 {
return a
}
j := len(a) - 1
for j >= 0 && a[j] <= a[i] {
j--
}
a[i], a[j] = a[j], a[i]
for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
a[k], a[l] = a[l], a[k]
}
return a
}
}
Golang spec for Return statements described:
The return value or values may be explicitly listed in the "return"
statement. Each expression must be single-valued and assignable to the
corresponding element of the function's result type.
The function called for permutation should contains two values in return one for the array and another for the boolean. Since you are assigning two variables from the function return:
a := []int{0,1,2,3,4}
nextPermutation, exists := iterPermutation(a) // it should return two values one for nextPermutation which is an array and other is exists which might be a boolean value.
for exists {
nextPermutation()
}
For below error:
"cannot use func literal (type func() []int) as type []int in return
argument"
you are returning func() literal enclosed inside the closure function of permutation along with boolean value, so change the return type as:
package main
func main(){
a := []int{0,1,2,3,4}
nextPermutation, _ := iterPermutation(a)
nextPermutation()
}
func iterPermutation(a []int) ((func() []int), bool) { // return both values
return func() []int {
i := len(a) - 2
for i >= 0 && a[i+1] <= a[i] {
i--
}
if i < 0 {
return a
}
j := len(a) - 1
for j >= 0 && a[j] <= a[i] {
j--
}
a[i], a[j] = a[j], a[i]
for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
a[k], a[l] = a[l], a[k]
}
return a
}, true // add boolean value to return from the function.
}
Working answer on Playground
I'm going to ignore the "permutation" logic inside your closure and focus on couple of concepts that you need to be aware of so it would work like you've planned to with your code. Correct me if I'm wrong, but you want to get array of item from your closure until exists is false, right?
First of all, to have nextPermutation, exists := iterPermutation(a) compile properly, iterPermutation needs to return two values like so:
func iterPermutation(a []int) (func() []int, bool) {
exists := true
return func() []int {
//rest of your code
if i < 0 {
exists = false
return a
}
//rest of your code
}, exists
}
Next problem you face is the fact that, with the above approach, you will have with the exists value. Since you are returning a value for exists, any change to exists will not be propagated beyond the scope of iterPermutation. You can fix this problem by returning a pointer. This is one way of implementing it:
a := []int{0,1,2,3,4}
nextPermutation, check := iterPermutation(a)
while check.Exists {
nextPermutation()
}
type Check struct {
Exists bool
}
func iterPermutation(a []int) (func() []int, *Check) {
check:= &Check{
Exists: true,
}
return func() []int {
i := len(a) - 2
for i >= 0 && a[i+1] <= a[i] {
i--
}
if i < 0 {
check.Exists = false //this is put here as an example
return a
}
j := len(a) - 1
for j >= 0 && a[j] <= a[i] {
j--
}
a[i], a[j] = a[j], a[i]
for k, l := i, len(a)-1; k < l; k, l = k+1, l-1 {
a[k], a[l] = a[l], a[k]
}
return a
}, check
}
When you return a pointer of Check type, any change to it in the iterPermutation or in your closure is visible outside of these as well, since you are accessing a memory reference.

Passing a 2D slice to a Golang function argument

I'm trying to scan a matrix from the stdin and simply print it using following code.
package main
import (
"fmt"
)
func print2D(arr [][]int) {
for i:=0; i< len(arr); i++{
for j := 0; j< len(arr[0]); j++{
fmt.Printf("%d ", arr[i][j])
}
fmt.Println()
}
}
func main() {
var arr [6][6]int
for i:= 0 ; i < 6 ;i++ {
for j := 0; j< 6; j++{
fmt.Scanf("%d", &arr[i][j])
}
}
print2D(arr[:])
}
It throws the following error
./main.go:23: cannot use arr[:] (type [][6]int) as type [][]int in
argument to print2D
Is there a way to pass a 2D slice without defining sizes in the function arguments?
Try to write the data directly to the slice and pass it later to the function. Remember array and slices are different types. Moreover, the type [3]int is also different from [4]int (size matters).
package main
import (
"fmt"
)
func print2D(arr [][]int) {
for i := 0; i < len(arr); i++ {
for j := 0; j < len(arr[0]); j++ {
fmt.Printf("%d ", arr[i][j])
}
fmt.Println()
}
}
func main() {
var arr [][]int
for i := 0; i < 6; i++ {
tmp := make([]int, 6)
for j := 0; j < 6; j++ {
fmt.Scanf("%d", &tmp[j])
}
arr = append(arr, tmp)
}
print2D(arr)
}

Resources