panic: runtime error: index out of range [-1] - go

when I try to solve the leetcode problem of 118. Pascal's Triangle https://leetcode.com/problems/pascals-triangle/
it occured strange bug. Below the code can pass OJ.
func generate(numRows int) [][]int {
res := [][]int{}
for i := 0; i < numRows; i++ {
row := []int{}
for j := 0; j < i+1; j++ {
if j == 0 || j == i {
row = append(row, 1)
} else if i > 1 {
row = append(row, res[i-1][j-1] + res[i-1][j])
}
}
res = append(res, row)
}
return res
}
But the code I write like this and it occur panic, but the basic logic is same.
func generate(numRows int) [][]int {
res := [][]int{}
for i := 0; i < numRows; i++ {
row := []int{}
for j := 0; j < i+1; j++ {
if j == 0 || j == i {
row = append(row, 1)
}
if i > 1 {
row = append(row, res[i-1][j-1] + res[i-1][j])
}
}
res = append(res, row)
}
return res
}
I used if else if structure, it works fine, but I use 2 if condition judgment error.
In fact, their logic is the same, but why the error? I would be grateful if you could solve this problem. Good lcuk for you!

The problem is that you use 2 if conditions in the second version, while in the first version you have an if else.
but the basic logic is same
No, the logic is not the same. The result is that you try to do j-1 when j is 0.
If you have 2 if conditions like this, the program will enter both blocks individually if their respective condition is met.
if j == 0 || j == i {
row = append(row, 1)
}
// if j is 0 you still enter this block as long as i > 1
if i > 1 {
row = append(row, res[i-1][j-1] + res[i-1][j])
}
You could use continue to skip this section, if the first if is met.
if j == 0 || j == i {
row = append(row, 1)
// continue with the next iteration
continue
}
if i > 1 {
row = append(row, res[i-1][j-1] + res[i-1][j])
}
That said, using the if else in the first version of your code seems reasonable. I am not sure why you would want to change it.

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)
}

new at using for loops

All of the comments I received recommended this
package main
import (
"fmt"
)
func getWord(word string) string {
value:=[]rune(word)
for i := 0; i < len(word); i++ {
j := i + 1
fmt.Println("positions", i, j)
}
}
but when I want to subtract the values in the 2 positions
if value[i] - value[j] == 0 || value[i] - value[j] == 1 {
return value
} else {
return " "
}
these are the output instead
0 1
panic: runtime error: index out of range
goroutine 1 [running]:
https://play.golang.org/p/VAW6AhB1lev
Your second for loop runs through all iterations blocking the first until it completes.
This is why i prints 1 until j reaches 10
for (int i = 0; i < 10; i++){
printf("positions %d %d\n", i, i+1);
}

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.

generate combinations/permutation of specific length

The project is more complex but the blocking issue is: How to generate a sequence of words of specific length from a list?
I've found how to generate all the possible combinations(see below) but the issue is that I need only the combinations of specific length.
Wolfram working example (it uses permutations though, I need only combinations(order doesn't matter)) :
Permutations[{a, b, c, d}, {3}]
Example(pseudo go):
list := []string{"alice", "moon", "walks", "mars", "sings", "guitar", "bravo"}
var premutationOf3
premutationOf3 = premuate(list, 3)
// this should return a list of all premutations such
// [][]string{[]string{"alice", "walks", "moon"}, []string{"alice", "signs", "guitar"} ....}
Current code to premutate all the possible sequences (no length limit)
for _, perm := range permutations(list) {
fmt.Printf("%q\n", perm)
}
func permutations(arr []string) [][]string {
var helper func([]string, int)
res := [][]string{}
helper = func(arr []string, n int) {
if n == 1 {
tmp := make([]string, len(arr))
copy(tmp, arr)
res = append(res, tmp)
} else {
for i := 0; i < n; i++ {
helper(arr, n-1)
if n%2 == 1 {
tmp := arr[i]
arr[i] = arr[n-1]
arr[n-1] = tmp
} else {
tmp := arr[0]
arr[0] = arr[n-1]
arr[n-1] = tmp
}
}
}
}
helper(arr, len(arr))
return res
}
I implement twiddle algorithm for generating combination in Go. Here is my implementation:
package twiddle
// Twiddle type contains all information twiddle algorithm
// need between each iteration.
type Twiddle struct {
p []int
b []bool
end bool
}
// New creates new twiddle algorithm instance
func New(m int, n int) *Twiddle {
p := make([]int, n+2)
b := make([]bool, n)
// initiate p
p[0] = n + 1
var i int
for i = 1; i != n-m+1; i++ {
p[i] = 0
}
for i != n+1 {
p[i] = i + m - n
i++
}
p[n+1] = -2
if m == 0 {
p[1] = 1
}
// initiate b
for i = 0; i != n-m; i++ {
b[i] = false
}
for i != n {
b[i] = true
i++
}
return &Twiddle{
p: p,
b: b,
}
}
// Next creates next combination and return it.
// it returns nil on end of combinations
func (t *Twiddle) Next() []bool {
if t.end {
return nil
}
r := make([]bool, len(t.b))
for i := 0; i < len(t.b); i++ {
r[i] = t.b[i]
}
x, y, end := t.twiddle()
t.b[x] = true
t.b[y] = false
t.end = end
return r
}
func (t *Twiddle) twiddle() (int, int, bool) {
var i, j, k int
var x, y int
j = 1
for t.p[j] <= 0 {
j++
}
if t.p[j-1] == 0 {
for i = j - 1; i != 1; i-- {
t.p[i] = -1
}
t.p[j] = 0
x = 0
t.p[1] = 1
y = j - 1
} else {
if j > 1 {
t.p[j-1] = 0
}
j++
for t.p[j] > 0 {
j++
}
k = j - 1
i = j
for t.p[i] == 0 {
t.p[i] = -1
i++
}
if t.p[i] == -1 {
t.p[i] = t.p[k]
x = i - 1
y = k - 1
t.p[k] = -1
} else {
if i == t.p[0] {
return x, y, true
}
t.p[j] = t.p[i]
t.p[i] = 0
x = j - 1
y = i - 1
}
}
return x, y, false
}
you can use my tweedle package as follow:
tw := tweedle.New(1, 2)
for b := tw.Next(); b != nil; b = tw.Next() {
fmt.Println(b)
}

How to solve Spiral Matrix in go

https://leetcode.com/problems/spiral-matrix/
golang implement.
the result as follow:
Run Code Status: Runtime Error
Run Code Result: ×
Your input
[]
Your answer
Expected answer
[]
Show Diff
why [] is the test case ,it's just a one-dimensional slice ?
my code is :
func sprial(begin_r, begin_c, row, col int, matrix [][]int) []int {
s := make([]int, col*row, col*row+10)
k := 0
if row == 1 && col == 1 {
s[k] = matrix[begin_r][begin_c]
return s
} else if row == 1 {
return matrix[begin_r][begin_c : col-1]
} else if col == 1 {
return matrix[begin_r : row-1][begin_c]
} else {
for i := begin_c; i < col; i++ {
s[k] = matrix[begin_r][i]
k++
}
for i := begin_r + 1; i < row; i++ {
s[k] = matrix[i][col-1]
k++
}
for i := col - 2; i >= begin_c; i-- {
s[k] = matrix[row-1][i]
k++
}
for i := row - 2; i >= begin_r+1; i-- {
s[k] = matrix[i][begin_c]
k++
}
return s[:k-1]
}
}
func spiralOrder(matrix [][]int) []int {
m := len(matrix)
n := len(matrix[0])
i := 0
j := 0
// var rS []int
k := 0
//s1 := make([]int, m*n, m*n)
var s1 = []int{}
for {
if m <= 0 || n <= 0 {
break
}
s := sprial(i, j, m, n, matrix)
if k == 0 {
s1 = s
} else {
s1 = append(s1, s...)
}
i++
j++
m -= 2
n -= 2
k++
}
return s1
}
func spiralOrder(matrix [][]int) []int {
if len(matrix) == 0 || len(matrix[0]) == 0 {
return nil
}
m, n := len(matrix), len(matrix[0])
next := nextFunc(m, n)
res := make([]int, m*n)
for i := range res {
x, y := next()
res[i] = matrix[x][y]
}
return res
}
func nextFunc(m, n int) func() (int, int) {
top, down := 0, m-1
left, right := 0, n-1
x, y := 0, -1
dx, dy := 0, 1
return func() (int, int) {
x += dx
y += dy
switch {
case y+dy > right:
top++
dx, dy = 1, 0
case x+dx > down:
right--
dx, dy = 0, -1
case y+dy < left:
down--
dx, dy = -1, 0
case x+dx < top:
left++
dx, dy = 0, 1
}
return x, y
}
}
Source: https://github.com/aQuaYi/LeetCode-in-Go/blob/master/Algorithms/0054.spiral-matrix/spiral-matrix.go
This repository has most of the solutions to LeetCode problems in a very optimal manner. Please do take a look. Hope it helps.

Resources