Skip to content

Instantly share code, notes, and snippets.

@tetsuok
Created April 2, 2012 08:48
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save tetsuok/2281812 to your computer and use it in GitHub Desktop.
Save tetsuok/2281812 to your computer and use it in GitHub Desktop.
An answer of the exercise: Fibonacci closure on a tour of Go
package main
import "fmt"
// Very naive answer.
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
n := 0
a := 0
b := 1
c := a + b
return func() int {
var ret int
switch {
case n == 0:
n++
ret = 0
case n == 1:
n++
ret = 1
default:
ret = c
a = b
b = c
c = a + b
}
return ret
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
@stoptime
Copy link

stoptime commented Aug 19, 2019

The directions say: "returns successive fibonacci numbers (0, 1, 1, 2, 3, 5, ...)." Many of these answers don't do that.

Here's my solution:

package main

import "fmt"

func fibonacci() func() int {
	a, b := 0, 1
	return func() int {
		current := a
		a, b = b, a+b
		return current
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

Returns:
0
1
1
2
3
5
8
13
21
34

For a great explanation of the recursion:
https://www.youtube.com/watch?v=zg-ddPbzcKM

@SebastianGiro
Copy link

SebastianGiro commented Sep 29, 2019

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	curr := -1
	next := 0
	
	return func() int {
		if (curr < 0) {
			curr, next = next, 1
		} else {
			curr, next = next, curr + next	
		}
		
		return curr;		
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

I started on negative numbers and put an if, to fix the problem about the sequence not starting with 0 and to keep the logic inside the returning function (and not put an if with a return 0 outside the return func()

@NeoMorfeo
Copy link

@GardenCoder, with your solution doesn't start with "0", change to and that's all:

func fibonacci() func() int {
	start := 0
	next  := 1
	return func() int {
		tmp := start
		start = next + start
		next = tmp
		return next
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

@saiponethaaung
Copy link

saiponethaaung commented Dec 24, 2019

func fibonacci() func() int {
	counter := 0
	sqr5 := math.Sqrt(5)
	return func() int {
		nTerm := float64(counter)
		ret := int((math.Pow((1+sqr5)/2, nTerm) - math.Pow((1-sqr5)/2, nTerm)) / sqr5)
		counter++
		return ret
	}
}

@webberwuuu
Copy link

func fibonacci() func() int {
	fst, sec := 0, 1
	return func() int {
		fst, sec = sec, fst+sec
		return sec - fst
	}
}

@magicparty
Copy link

magicparty commented Jan 15, 2020

//simple and readable version

func fibonacci() func() int {
	a, b := 0, 1
	return func() int {
		current := a
		a, b = b, a+b
		return current
	}
}

returns 0,1,1,2,3,5...

@webberwuuu
Copy link

The directions say: "returns successive fibonacci numbers (0, 1, 1, 2, 3, 5, ...)." Many of these answers don't do that.

Here's my solution:

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	a, b := 0, 1
	if a == 0 {
            fmt.Println(a)
	}
	return func() int {
	    // this type of assignment
	    // is the magic of golang
	    a, b = b, a + b
	    return a
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
            fmt.Println(f())
	}
}

Returns:
0
1
1
2
3
5
8
13
21
34
55

For a great explanation of the recursion:
https://www.youtube.com/watch?v=zg-ddPbzcKM

I think you should put the if inside the returned func. Or as you see, you got 11 output in a 10s loop in the main. Your first call to f() print the second num "1" in the fibonacci.

@stoptime
Copy link

@webberwuuu tx for the heads up. After looking at this again I don't think any conditionals are necessary - I've updated my solution.

@olehcambel
Copy link

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func(int) int {
	return func(n int) int {
		prev, next := -1, 1

		// <=
		for i := 0; i < n; i++ {
			prev, next = next, prev+next
		}

		// return next
		return prev + next
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f(i))
	}
}

@pokgopun
Copy link

pokgopun commented May 4, 2020

Hate the growing slice but just trying to use it to represent the math fibonacci numbers

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.

func fibonacci() func() int {
	var f,n int // Fn and n
	s := []int{} // The sequence
	return func() int {
		if n > 1 { // Fn = Fn-1 + Fn-2
			f = s[n-1] + s[n-2]
		} else { // F0 = 0, F1 = 1
			f = n
		}
		s = append(s,f) // Add Fn to the sequence
		n++
		return f
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

0
1
1
2
3
5
8
13
21
34

@pokgopun
Copy link

pokgopun commented May 4, 2020

Hate the growing slice but just trying to use it to represent the math fibonacci numbers

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.

func fibonacci() func() int {
	var f,n int // Fn and n
	s := []int{} // The sequence
	return func() int {
		if n > 1 { // Fn = Fn-1 + Fn-2
			f = s[n-1] + s[n-2]
		} else { // F0 = 0, F1 = 1
			f = n
		}
		s = append(s,f) // Add Fn to the sequence
		n++
		return f
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

0
1
1
2
3
5
8
13
21
34

Here is a much shorter version using a shifting slice to calculate the number instead of the growing slice with verbose if conditions:

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.

func fibonacci() func() int {
	s := []int{0,1}
	return func() int {
		f := s[0]	
		s = s[1:]		
		s = append(s,s[0]+f)
		return f
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

0
1
1
2
3
5
8
13
21
34

@saidamir98
Copy link

saidamir98 commented Jul 6, 2020

Fibonacci closure is more fun than I thought!

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	a1 := 0
	a2 := 1
	return func() int {
		f := a1
		a1, a2 = a2, a2+f
		return f
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

@HassanYA
Copy link

@toolchainX @stvr
Impressive! very much impressed

@ranvit
Copy link

ranvit commented Jan 3, 2021

solution 1 using naked returns

func fibonacci() func() int {
	first, second := 0, 1
	return func() (ret int) {
		ret, first, second = first, second, first+second
		return
	}
}

solution 2 using defer, circumventing the need for a third ret variable

func fibonacci() func() int {
	first, second := 0, 1
	return func() int {
		defer func() { first, second = second, first+second }()
		return first
	}
}

@albertleng
Copy link

Zero-based:

func fibonacci() func() int {
    fib1 := 0
	fib2 := 1
	return func() int {
		fib1, fib2 = fib2, fib1+fib2
		return fib2-fib1
	}
}

One-based:

func fibonacci() func() int {
    fib1 := 0
	fib2 := 1
	return func() int {
		fib1, fib2 = fib2, fib1+fib2
		return fib2
	}
}

@hefedev
Copy link

hefedev commented Mar 8, 2021

I used growing slice as well but clearly there are better answers here

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    seq := 0
    var f []int
    
    return func() int {
        switch seq {
            case 0,1:
            f = append(f, seq)
            default:
            f = append(f, f[seq-2]+f[seq-1])
        }
        seq++
        return f[len(f)-1]
    }
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

@Worthy-Programmer
Copy link

func fibonacci() func() int {
	prev := -1
	now := 1

	return func() int {
		now +=  prev
		prev = now - prev
		return now
	}
}

@aibeksarsembayev
Copy link

aibeksarsembayev commented May 16, 2021

`package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int

func fibonacci() func(int) int {
sum := 0
sum1 := 0
sum2 := 1
return func(x int) int {
if x == 0 {
return sum1
} else if x == 1 {
return sum2
} else {
sum = sum1 + sum2
sum1 = sum2
sum2 = sum
return sum
}
}
}

func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f(i))
}
}`

@gmac
Copy link

gmac commented Oct 5, 2021

Feels succinct:

func fibonacci() func() int {
  var a, b int = 1, 0
  return func() int {
    a, b = b, a + b
    return a
  }
}

@bhuppal
Copy link

bhuppal commented Oct 29, 2021

Wired & fun solution


package main

import "fmt"

func fib() func(int) int {
a := 0
b := 1
return func(count int) int {
for ; count > 0; count-- {
a, b = b, a+b
}
return a
}
}

func main () {
fibCalc := fib()
fmt.Println(fibCalc(10))
}

@chingizof
Copy link

chingizof commented Feb 12, 2022

func fibonacci() func() int {
    num, back, n := 0, 1, 0
	  return func () int {
		  if n++; n == 1 {
			  return 0
		  }
		  num, back = num+back, num
		  return num
	  }
}

@ydzh
Copy link

ydzh commented Mar 23, 2022

func fibonacci() func() int {
	first := -1
	second := 1
	return func() int {
		first, second = second, first + second
		return second
	}
}

@nerewarin
Copy link

nerewarin commented May 2, 2022

func fibonacci() func() int {
	i := -1
	var fib func(i int) int
	
	fib = func(x int) int {
		switch x {
			case 0:
				return 0
			case 1:
				return 1
			default:
				return fib(x-1) + fib(x-2)
		}
	}
	
	fib2 := func() int {
		i++
		return fib(i)
	}
	return fib2
}

@NanmiCoder
Copy link

func fibonacci() func() int {
	a, b := 0, 1
	fib := func() int {
		var result int
		if a == 0 {
			result = 0
		} else {
			result = b
		}
		a, b = b, a+b
		return result
	}
	return fib
}

@niyazz
Copy link

niyazz commented May 16, 2022

func fibonacci() func() int {
	array := [2]int {-1, 1}
	return func() int{
		res := array[0] + array[1]
		array[0] = array[1]
		array[1] = res
		return res
	}
}

@QuanTT0110
Copy link

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	
	first, second := 0, 1
	
	return (func () int {
		first, second = second, first + second
		return second
		
	})

}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

anybody can explain for me about this line "first, second = second, first + second" ? please, i don't understand

@oboff
Copy link

oboff commented Nov 11, 2022

func fibonacci() func() int {
	a,b,c := 0, 0, 1
	return func() int {
		a = b
		b, c = c, b+c
		return a
	}
}

@oboff
Copy link

oboff commented Nov 11, 2022

@QuanTT0110
similar to writing:

first = second
second = first + second

@hktrib
Copy link

hktrib commented Jul 13, 2023

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	
	first, second := 0, 1
	
	return (func () int {
		first, second = second, first + second
		return second
		
	})

}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

anybody can explain for me about this line "first, second = second, first + second" ? please, i don't understand

I think you need to create a copy. Remember you are using a accumulating reference in first and second. Also think about your logic one more time

@guru-das-s
Copy link

guru-das-s commented Sep 15, 2023

I solved this using a defer function:

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	var a, b int = 0, 1

	return func() int {
		update_fn := func() {
			a, b = b, b+a
		}
		defer update_fn()
		return a
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment