I'm trying to add the slice sofar to a new row in matrix after each iteration.
func combinations(sofar []int, rest []int, n int, matrix [][]int, count int) {
if n == 0 {
//Next two lines problematic
matrix[count] = append(matrix[count], sofar[0], sofar[1], sofar[2])
count++
fmt.Println(sofar)
} else {
for i := range rest[:len(rest)] {
concat := sofar
concat = append(concat, rest[i])
combinations(concat, rest[i+1:], n-1, matrix, count)
}
}
}
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * factorial(x-1)
}
Driver program
func triangleNumber() int {
sofar := []int{}
rest := []int{1,2,3,4}
matrixSize := factorial(4)/(factorial(1)*factorial(3))
matrix := make([][]int, matrixSize)
count := 0
fmt.Println(matrixSize)
combinations(sofar, rest, 3, matrix, count)
return 0
}
triangleNumber()
I want matrix to be;
[1 2 3]
[1 2 4]
[1 3 4]
[2 3 4]
But instead it's all going in the first row. Also is there a way I can get rid of count, and just add the slice sofar to the next row?
Actually, there are a couple of things I note with your program:
Append adds to the existing slice at its end (after length), so if you are using append for matrix, you need not allocate a slice of that size (see main in the code below)
After you are adding elements to the matrix, it is simply being dumped in your current program. The combinations function needs to return it back so that when future elements (slice of ints) are added, they are actually all there.
I've added some debugs and remodeled your program a bit, see if it makes sense:
package main
import (
"fmt"
)
func main() {
triangleNumber()
}
func combinations(sofar []int, rest []int, n int, matrix [][]int, count int) [][]int {
fmt.Println("Entered with matrix", matrix)
if n == 0 {
fmt.Println("Entered with count", count)
//Next two lines problematic
matrix = append(matrix, sofar)
count++
fmt.Println(sofar)
fmt.Println("Printing matrix\n***", matrix, "\n***")
return matrix
} else {
for i := range rest[:len(rest)] {
concat := sofar
concat = append(concat, rest[i])
matrix = combinations(concat, rest[i+1:], n-1, matrix, count)
fmt.Println("Sending with count", count)
}
}
return matrix
}
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * factorial(x-1)
}
func triangleNumber() int {
sofar := []int{}
rest := []int{1, 2, 3, 4}
matrixSize := factorial(4) / (factorial(1) * factorial(3))
matrix := make([][]int, 0)
count := 0
fmt.Println(matrixSize)
combinations(sofar, rest, 3, matrix, count)
return 0
}
And as you can see, you can pretty much get rid of count too with this approach (look at the output). There's still some scope for improvement left though, but I guess this addresses what you were asking.
On playground: https://play.golang.org/p/rnCdPcaIG3N
Hope this helps.
You're adding all to the first row, and you need to add to the next row, see:
Try this (with minimum change to your code: made count a pointer):
package main
import (
"fmt"
)
func main() {
triangleNumber()
}
func triangleNumber() int {
sofar := []int{}
rest := []int{1, 2, 3, 4}
matrixSize := factorial(4) / (factorial(1) * factorial(3))
matrix := make([][]int, matrixSize)
count := 0
fmt.Println(matrixSize)
combinations(sofar, rest, 3, matrix, &count)
fmt.Println(matrix)
return 0
}
func combinations(sofar []int, rest []int, n int, matrix [][]int, count *int) {
if n == 0 {
//Next two lines problematic
matrix[*count] = append(matrix[*count], sofar[0], sofar[1], sofar[2])
*count++
// fmt.Println(count, sofar)
} else {
for i := range rest[:len(rest)] {
concat := sofar
concat = append(concat, rest[i])
combinations(concat, rest[i+1:], n-1, matrix, count)
}
}
}
func factorial(x uint) uint {
if x == 0 {
return 1
}
return x * factorial(x-1)
}
output:
4
[[1 2 3] [1 2 4] [1 3 4] [2 3 4]]
Also for your special case, this works too:
matrix[*count] = []int{sofar[0], sofar[1], sofar[2]}
instead of:
matrix[*count] = append(matrix[*count], sofar[0], sofar[1], sofar[2])
Related
I'm coding on leetcode 973.
func kClosest(points [][]int, k int) [][]int {
sort.Slice(points, func(i, j int) bool {
if hypot(points[i]) > hypot(points[j]){
return false
}else{
return true
}
})
return points[:k]
}
func hypot(point []int) int {
ans := 0
for _, n := range point{
ans+=n*n
}
return ans
}
this is one of the answer. But this resolution involves redundant computation of distance, so i want to create a slice to restore the distance. and i'm trying to sort slice points using this foreign data like
func kClosest(points [][]int, k int) [][]int {
dist := make([]int, len(points))
for i:=0; i< len(points); i++{
dist[i] = hypot(points[i])
}
sort.Slice(points, func(i, j int) bool {
if dist[i] > dist[j]{
dist[i], dist[j] = dist[j], dist[i]
return false
}else{
return true
}
})
return points[:k]
}
func hypot(point []int) int {
ans := 0
for _, n := range point{
ans+=n*n
}
return ans
}
But in this case only slice dist is sorted while the slice points doesn't change.
I'm trying to refer to the source code but they seem to be wrapped.
Thanks if anyone could explain it to me or tell me where i can find the answer.
The purpose and responsibility of less() function you pass to sort.Slice() is to tell the is-less relation of 2 elements of the sortable slice. It should not perform changes on the slice, and it should be idempotent. Your less function is not idempotent: if you call it twice with the same i and j, it may return different result even if the slice is not modified between the calls.
Genesis: your original solution
Your original, improved solution is this:
func kClosest(points [][]int, k int) [][]int {
sort.Slice(points, func(i, j int) bool {
return hypot(points[i]) < hypot(points[j])
})
return points[:k]
}
Using an indices slice
One way of sorting a slice based on another is to create a slice holding the indices, sort this indices slice (based on the reference slice), and once we have the final index order, assemble the result.
Here's how it could look like:
func kClosest2(points [][]int, k int) [][]int {
dist := make([]int, len(points))
indices := make([]int, len(points))
for i := range dist {
indices[i] = i
dist[i] = hypot(points[i])
}
sort.Slice(indices, func(i, j int) bool {
return dist[indices[i]] <= dist[indices[j]]
})
result := make([][]int, k)
for i := range result {
result[i] = points[indices[i]]
}
return result
}
Creating sortable pairs
Another approach is to create pairs from the points and their distances, and sort the pairs.
Here's how it could be done:
func kClosest3(points [][]int, k int) [][]int {
type pair struct {
dist int
point []int
}
pairs := make([]pair, len(points))
for i := range pairs {
pairs[i].dist = hypot(points[i])
pairs[i].point = points[i]
}
sort.Slice(pairs, func(i, j int) bool {
return pairs[i].dist <= pairs[j].dist
})
result := make([][]int, k)
for i := range result {
result[i] = pairs[i].point
}
return result
}
Implementing sort.Interface and using a swap() method that swaps in both slices
Title says it all. We implement sort.Interface ourselves whose less() method will report based on the distance slice, but the swap() function will perform swapping on both slices:
type mySorter struct {
dist []int
points [][]int
}
func (m mySorter) Len() int { return len(m.dist) }
func (m mySorter) Swap(i, j int) {
m.dist[i], m.dist[j] = m.dist[j], m.dist[i]
m.points[i], m.points[j] = m.points[j], m.points[i]
}
func (m mySorter) Less(i, j int) bool { return m.dist[i] < m.dist[j] }
func kClosest4(points [][]int, k int) [][]int {
dist := make([]int, len(points))
for i := range dist {
dist[i] = hypot(points[i])
}
ms := mySorter{dist, points}
sort.Sort(ms)
return points[:k]
}
Testing the solutions
Here's a test code for all the above solutions:
solutions := []func(points [][]int, k int) [][]int{
kClosest, kClosest2, kClosest3, kClosest4,
}
for _, solution := range solutions {
points := [][]int{
{3, 5},
{0, 5},
{0, 0},
{1, 2},
{6, 0},
}
fmt.Println(solution(points, len(points)))
}
Which will output (try it on the Go Playground)
[[0 0] [1 2] [0 5] [3 5] [6 0]]
[[0 0] [1 2] [0 5] [3 5] [6 0]]
[[0 0] [1 2] [0 5] [3 5] [6 0]]
[[0 0] [1 2] [0 5] [3 5] [6 0]]
This is a LeetCode problem: 189. Rotate Array:
Given an array, rotate the array to the right by k steps, where k is
non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
And here is my solution:
func rotate(nums []int, k int) {
k = k % len(nums)
nums = append(nums[k:],nums[0:k]...)
fmt.Println(nums)
}
It is a straight forward algorithm but it does not work.
I am new to Go. I suppose nums is passed by value and changes to nums won't affect the real nums.
How can I get this right?
In Go, all arguments are passed by value.
A Go slice is represented at runtime by a slice descriptor:
type slice struct {
array unsafe.Pointer
len int
cap int
}
If you change any of the slice descriptor values in a function then communicate the change, typically by returning the changed slice descriptor.
Your rotate function changes the values of the slice num pointer to the underlying array and the slice capacity, so return num.
For example, after I fixed the bugs in your rotate algorithm,
package main
import "fmt"
func rotate(nums []int, k int) []int {
if k < 0 || len(nums) == 0 {
return nums
}
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
r := len(nums) - k%len(nums)
nums = append(nums[r:], nums[:r]...)
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
return nums
}
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7}
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
nums = rotate(nums, 3)
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
}
Output:
nums 0xc00000a080 array 0xc00001a1c0 len 7 cap 7 slice [1 2 3 4 5 6 7]
nums 0xc00000a0c0 array 0xc00001a1c0 len 7 cap 7 slice [1 2 3 4 5 6 7]
nums 0xc00000a0c0 array 0xc00001a240 len 7 cap 8 slice [5 6 7 1 2 3 4]
nums 0xc00000a080 array 0xc00001a240 len 7 cap 8 slice [5 6 7 1 2 3 4]
Reference: The Go Blog: Go Slices: usage and internals
Here's a way do rotate a float 32 slice, you can change it for another type.
//RotateF32Slice positive n rotate to the left, negative to right
func RotateF32Slice(slice []float32, n int) (rotateSlice []float32) {
var begin []float32
var end []float32
size := len(slice)
rotateSlice = make([]float32, size)
nAbs := math.Abs(float64(n))
if int(nAbs) > size {
remainder, _ := QuotientAndRemainderF32(float32(n), float32(size))
n = int(remainder)
}
if n != 0 {
if n > 0 {
index := size - n
begin = slice[index:]
end = slice[0:index]
copy(rotateSlice, begin)
copy(rotateSlice[n:], end)
} else {
n = int(nAbs)
index := size - n
begin = slice[n:]
end = slice[0:n]
copy(rotateSlice, begin)
copy(rotateSlice[index:], end)
}
} else {
copy(rotateSlice, slice)
}
return rotateSlice
}
//QuotientAndRemainderF32 Computes the integer quotient and the remainder of the inputs. This function rounds floor(x/y) to the nearest integer towards -inf.
func QuotientAndRemainderF32(x, y float32) (Remainder, Quotient float32) {
Quotient = float32(math.Floor(float64(x / y)))
Remainder = x - y*Quotient
return Remainder, Quotient
}
Solutions
Solution 1 :
func rotate(ar []int,d,n int) []int{
var newArray []int
for i:=0;i<d;i++{
newArray = ar[1:n]
newArray = append(newArray,ar[0])
ar = newArray
}
return ar
}
Solution 2 :
func rotateR(ar []int,d,n int) []int{
ar = append(ar[d:n],ar[0:d]...)
return ar
}
func rotate(nums []int, k int) {
k = k % len(nums)
result := append(nums[len(nums)-k:], nums[:len(nums)-k]...)
for i := 0; i < len(nums); i++ {
nums[i] = result[i]
}
}
Answering this late as i came across this while reading the book "The Go Programming language". It presents a quite elegant algo to use the reverse function and apply it thrice to achieve the desired rotation by k elems. Something like this
// function to rotate array by k elems (3 reverse method)
func rotate(arr []int, k int) {
reverse(arr[:k])
reverse(arr[k:])
reverse(arr)
}
Please note, you will have to write a reverse function. Go does not provide one. This is an O(n) solution and takes O(1) space.
This is my solution to the same hackerrank problem
func rotateLeft(d int32, arr []int32) []int32 {
for ; d > 0 ; d-- {
left := arr[0]
arr = arr[1:]
arr = append(arr, left)
}
return arr
}
for me this worked for many of array rotating but not for hundreds nums[].
func rotate(nums []int, k int) {
for count:=k; count>0; count--{
if len(nums) >= 1 && len(nums) <= 10^5 {
for i:=len(nums)-1; i>0; i--{
nums[i], nums[i-1] = nums[i-1], nums[i]
}
}
}
}
Given an array, rotate the array to the right by k steps, where k is
non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3 Output: [5,6,7,1,2,3,4]
Blockquote
First, for k=3, shouldn't be the output [4,5,6,7,1,2,3] ?
For most array operations, it is always simplier to add elements to a newly created array rather than change the source array. If the array is not really large (takes Gigs of memory / billions of items, etc..), you can use a function that adds elements to the newly created array in the order you require and returns new one:
// GO 1.18
func rot[T any](slice []T, k int) (newSlice []T){
l := len(slice)
for i := range slice {
newSlice = append(newSlice, slice[(k+i) % l])
}
return
}
fmt.Printf("Slice %v after rotation %v\n", []int{1,2,3,4,5,6,7}, rot[int]([]int{1,2,3,4,5,6,7}, 3))
//Slice [1 2 3 4 5 6 7] after rotation [4 5 6 7 1 2 3]
If you insist on using "slicing", the code looks like this:
func rotationBySlicing[T any](slice []T, k int) (newSlice []T) {
if len(slice) == 0 {
return slice
}
return append(slice[(k%len(slice)):],slice[0:k%len(slice)]...)
}
fmt.Printf("Array %v after rotation %v\n", []string{}, rotationBySlicing[string]([]string{},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a"}, rotationBySlicing[string]([]string{"a"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a","b"}, rotationBySlicing[string]([]string{"a","b"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a","b","c"}, rotationBySlicing[string]([]string{"a","b","c"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a", "b", "c", "d"}, rotationBySlicing[string]([]string{"a", "b", "c", "d"},1))
fmt.Printf("Slice %v after rotation %v\n", []int{1,2,3,4,5,6,7}, rotationBySlicing[int]([]int{1,2,3,4,5,6,7}, 3))
Array [] after rotation []
Array [a] after rotation [a]
Array [a b] after rotation [b a]
Array [a b c] after rotation [b c a]
Array [a b c d] after rotation [b c d a]
Array [1 2 3 4 5 6 7] after rotation [4 5 6 7 1 2 3]
Also instruction says:
where k is non-negative
, for completeness the code should handle case when k is less than 0
In my case, I preferred this algorithm below because I wanted to keep slice capacity the same:
// Rotation by keeping the capacity same
func Rotate(nums []int, k int) {
k %= len(nums)
new_array := make([]int, len(nums))
copy(new_array[:k], nums[len(nums)-k:])
copy(new_array[k:], nums[:len(nums)-k])
copy(nums, new_array)
}
Also, I tested it in Leet code and it looks good :)
You can also add a condition at the top of your function to make it ready for negative shifts (rotates),
Whole code again:
func Rotate(nums []int, k int) {
k %= len(nums)
// Condition below is added.
if k < 0 {
k += len(nums)
}
new_array := make([]int, len(nums))
copy(new_array[:k], nums[len(nums)-k:])
copy(new_array[k:], nums[:len(nums)-k])
copy(nums, new_array)
}
This doesn't work because []byte is a slice which is sort of a "pointer to an array". Doing:
func f(v []T) {
v = ... //
}
won't have any observable effect for the caller. Assuming your append way is correct (didn't really check it) you could do something like this:
func rotate(nums []int, k int) {
k = k % len(nums)
temp := append(nums[k:], nums[0:k]...)
copy(nums, temp) // this actually writes to where nums points to
}
func main() {
nums := []int{1,2,3,4,5,6,7}
rotate(nums ,3)
fmt.Println(nums)
}
I am trying to learn Go, so here is my very simple function for removing adjacent duplicates from slice for exercise from the book by Donovan & Kernighan.
Here is the code: https://play.golang.org/p/avHc1ixfck
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
removeDup(a)
fmt.Println(a)
}
func removeDup(s []int) {
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
j := 1
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
j++
}
}
s = s[:len(tmp)]
copy(s, tmp)
}
It should print out [0 1 3] - and I checked, actually tmp at the end of the function it has desired form. However, the result is [0 1 3 3 3 3]. I guess there is something with copy function.
Can I somehow replace input slice s with the temp or trim it to desired length?
Option 1
Return a new slice as suggested by #zerkms.
https://play.golang.org/p/uGJiD3WApS
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
a = removeDup(a)
fmt.Println(a)
}
func removeDup(s []int) []int {
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
}
}
return tmp
}
Option 2
Use pointers for pass-by-reference.
The same thing in effect as that of option1.
https://play.golang.org/p/80bE5Qkuuj
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
removeDup(&a)
fmt.Println(a)
}
func removeDup(sp *[]int) {
s := *sp
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
}
}
*sp = tmp
}
Also, refer to following SO thread:
Does Go have no real way to shrink a slice? Is that an issue?
Here's two more slightly different ways to achieve what you want using sets and named types. The cool thing about named types is that you can create interfaces around them and can help with the readability of lots of code.
package main
import "fmt"
func main() {
// returning a list
a := []int{0, 1, 1, 3, 3, 3}
clean := removeDup(a)
fmt.Println(clean)
// creating and using a named type
nA := &newArrType{0, 1, 1, 3, 3, 3}
nA.removeDup2()
fmt.Println(nA)
// or... casting your orginal array to the named type
nB := newArrType(a)
nB.removeDup2()
fmt.Println(nB)
}
// using a set
// order is not kept, but a set is returned
func removeDup(s []int) (newArr []int) {
set := make(map[int]struct{})
for _, n := range s {
set[n] = struct{}{}
}
newArr = make([]int, 0, len(set))
for k := range set {
newArr = append(newArr, k)
}
return
}
// using named a typed
type newArrType []int
func (a *newArrType) removeDup2() {
x := *a
for i := range x {
f := i + 1
if f < len(x) {
if x[i] == x[f] {
x = x[:f+copy(x[f:], x[f+1:])]
}
}
}
// check the last 2 indexes
if x[len(x)-2] == x[len(x)-1] {
x = x[:len(x)-1+copy(x[len(x)-1:], x[len(x)-1+1:])]
}
*a = x
}
Can anyone comment on whether this is a reasonable and idiomatic way of implementing circular shift of integer arrays in Go? (I deliberately chose not to use bitwise operations.)
How could it be improved?
package main
import "fmt"
func main() {
a := []int{1,2,3,4,5,6,7,8,9,10}
fmt.Println(a)
rotateR(a, 5)
fmt.Println(a)
rotateL(a, 5)
fmt.Println(a)
}
func rotateL(a []int, i int) {
for count := 1; count <= i; count++ {
tmp := a[0]
for n := 1;n < len(a);n++ {
a[n-1] = a[n]
}
a[len(a)-1] = tmp
}
}
func rotateR(a []int, i int) {
for count := 1; count <= i; count++ {
tmp := a[len(a)-1]
for n := len(a)-2;n >=0 ;n-- {
a[n+1] = a[n]
}
a[0] = tmp
}
}
Rotating the slice one position at a time, and repeating to get the total desired rotation means it will take time proportional to rotation distance × length of slice. By moving each element directly into its final position you can do this in time proportional to just the length of the slice.
The code for this is a little more tricky than you have, and you’ll need a GCD function to determine how many times to go through the slice:
func gcd(a, b int) int {
for b != 0 {
a, b = b, a % b
}
return a
}
func rotateL(a []int, i int) {
// Ensure the shift amount is less than the length of the array,
// and that it is positive.
i = i % len(a)
if i < 0 {
i += len(a)
}
for c := 0; c < gcd(i, len(a)); c++ {
t := a[c]
j := c
for {
k := j + i
// loop around if we go past the end of the slice
if k >= len(a) {
k -= len(a)
}
// end when we get to where we started
if k == c {
break
}
// move the element directly into its final position
a[j] = a[k]
j = k
}
a[j] = t
}
}
Rotating a slice of size l right by p positions is equivalent to rotating it left by l − p positions, so you can simplify your rotateR function by using rotateL:
func rotateR(a []int, i int) {
rotateL(a, len(a) - i)
}
Your code is fine for in-place modification.
Don't clearly understand what you mean by bitwise operations. Maybe this
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(a)
rotateR(&a, 4)
fmt.Println(a)
rotateL(&a, 4)
fmt.Println(a)
}
func rotateL(a *[]int, i int) {
x, b := (*a)[:i], (*a)[i:]
*a = append(b, x...)
}
func rotateR(a *[]int, i int) {
x, b := (*a)[:(len(*a)-i)], (*a)[(len(*a)-i):]
*a = append(b, x...)
}
Code works https://play.golang.org/p/0VtiRFQVl7
It's called reslicing in Go vocabulary. Tradeoff is coping and looping in your snippet vs dynamic allocation in this. It's your choice, but in case of shifting 10000 elements array by one position reslicing looks much cheaper.
I like Uvelichitel solution but if you would like modular arithmetic which would be O(n) complexity
package main
func main(){
s := []string{"1", "2", "3"}
rot := 5
fmt.Println("Before RotL", s)
fmt.Println("After RotL", rotL(rot, s))
fmt.Println("Before RotR", s)
fmt.Println("After RotR", rotR(rot,s))
}
func rotL(m int, arr []string) []string{
newArr := make([]string, len(arr))
for i, k := range arr{
newPos := (((i - m) % len(arr)) + len(arr)) % len(arr)
newArr[newPos] = k
}
return newArr
}
func rotR(m int, arr []string) []string{
newArr := make([]string, len(arr))
for i, k := range arr{
newPos := (i + m) % len(arr)
newArr[newPos] = k
}
return newArr
}
If you need to enter multiple values, whatever you want (upd code Uvelichitel)
package main
import "fmt"
func main() {
var N, n int
fmt.Scan(&N)
a := make([]int, N)
for i := 0; i < N; i++ {
fmt.Scan(&a[i])
}
fmt.Scan(&n)
if n > 0 {
rotateR(&a, n%len(a))
} else {
rotateL(&a, (n*-1)%len(a))
}
for _, elem := range a {
fmt.Print(elem, " ")
}
}
func rotateL(a *[]int, i int) {
x, b := (*a)[:i], (*a)[i:]
*a = append(b, x...)
}
func rotateR(a *[]int, i int) {
x, b := (*a)[:(len(*a)-i)], (*a)[(len(*a)-i):]
*a = append(b, x...)
}
I'm writing a function that returns a sequence of numbers of variable length:
func fib(n int) ??? {
retval := ???
a, b := 0, 1
for ; n > 0; n-- {
??? // append a onto retval here
c := a + b
a = b
b = c
}
}
It can be observed that the final length of the returned sequence will be n. How and what should fib return to achieve idiomatic Go? If the length was not known in advance, how would the return value, and usage differ? How do I insert values into retval?
Here, we know how many numbers; we want n Fibonacci numbers.
package main
import "fmt"
func fib(n int) (f []int) {
if n < 0 {
n = 0
}
f = make([]int, n)
a, b := 0, 1
for i := 0; i < len(f); i++ {
f[i] = a
a, b = b, a+b
}
return
}
func main() {
f := fib(7)
fmt.Println(len(f), f)
}
Output: 7 [0 1 1 2 3 5 8]
Here, we don't know how many numbers; we want all the Fibonacci numbers less than or equal to n.
package main
import "fmt"
func fibMax(n int) (f []int) {
a, b := 0, 1
for a <= n {
f = append(f, a)
a, b = b, a+b
}
return
}
func main() {
f := fibMax(42)
fmt.Println(len(f), f)
}
Output: 10 [0 1 1 2 3 5 8 13 21 34]
You could also use IntVector from the Go vector package. Note that type IntVector []int.
Don't use Vectors, use slices. Here are some mapping of various vector operations to idiomatic slice operations.