Skip to content

Instantly share code, notes, and snippets.

@weppos
Last active March 25, 2024 23:03
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save weppos/7843653 to your computer and use it in GitHub Desktop.
Save weppos/7843653 to your computer and use it in GitHub Desktop.
A Tour of Go Exercise: Fibonacci closure
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
f2, f1 := 0, 1
return func() int {
f := f2
f2, f1 = f1, f+f1
return f
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
@harryge00
Copy link

excellent!

@dumindu
Copy link

dumindu commented Jun 12, 2019

Thanks for sharing. I think this version can be easily understandable for any one :)

package main

import "fmt"

func fibonacci() func() int {
	x, y := 0, 1
	return func() int {
		f := x
		x, y = y, f+y

		return f
	}
}

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

@anantxx
Copy link

anantxx commented Jul 15, 2019

Here's my solutions

package main
import (
	"fmt"
	"log"
	"time"
)

func main() {
	defer timeTrack(time.Now(), "Main")
	f := fibonacci()
	for i := 0; i < 100; i++ {
		fmt.Println(f())
	}
}

func timeTrack(start time.Time, name string) {
	elapsed := time.Since(start)
	log.Printf("%s took %s", name, elapsed)
}

/*
Solution 1:
func fibonacci() func() uint {
	var v1, v2 uint = 0, 1
	return func() uint {
		v2 = v2 + v1
		v1 = v2 - v1
		return v2 - v1
	}
}
*/

/*
Solution 2:*/
func fibonacci() func() int {
	v1, v2 := 0, 1

	return func() int {
		defer func() {
			v1, v2 = v2, v1+v2
		}()

		return v1
	}
}

@citaret
Copy link

citaret commented Jul 30, 2019

My version:

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

@banothurameshnaik
Copy link

package main

import "fmt"

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

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

@ptflp
Copy link

ptflp commented Dec 13, 2019

My version:

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

it's not your solution, this solution belongs to @stvr in 2012

@dougahmann
Copy link

dougahmann commented Feb 2, 2020

func fibonacci() func() int {
	previous := 0
	last := 0
	index := 0
	
	return func() int {
		var result int
		if index == 1 {
			result = 1
		} else {
			result = last + previous	
		}
		
		previous = last;
		last = result;
		index++
		
		return int(result)
	}
}

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

This is what I came up, before searching for other's solutions. Mine doesn't modify main(), which I believe was part of the spirit of the exercise. Otherwise, very close to banothurameshnaik's solution.

In any case, I find this more readable than the first example as someone new to Go (but with 30+ years programming experience). Is the bunching of multiple assignments on a line (e.g. a, b := 1, 0) really considered "best practice"? Seems like it's being clever at the expense of readability. Probably biased by my experience with other languages. Maybe my opinion will change over time. Other than slightly less typing and fewer lines, what else would be the advantage of using the shorter notation?

Thanks in advance for any opinions.

@Thargelion
Copy link

Thargelion commented Mar 26, 2020

This starts with zero and does not modifies main()

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	a, b := 0, 1
	return func() int {
		result := a // Store the result value before translations
		c := a + b // Fibonacci
		a = b // Translation
		b = c // Translation
		return result
	}
}

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

@anuragguptagithub
Copy link


import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    a: = 0
    b: = 1
    sum: = a + b
    return func() int {
        if a == 0 {
            a = b
            return 0
        }
        a = b
        b = sum
        sum = a + b
        return a
    }
}

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

@anuragguptagithub
Copy link

anuragguptagithub commented Jul 3, 2020


import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	a, b := 1, 0
	return func() int {
		a, b = b, a+b // two assignment happens parallely, but if you enforce it sequentially, it won't work
		return a
	}
}

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

@Wuitar
Copy link

Wuitar commented Jul 14, 2020

use slice

package main

import "fmt"

func fibonacci() func() int {
	var i []int
	return func() int {
		if len(i) == 0 {
			i = append(i, 0)
		} else if len(i) == 1 {
			i = append(i, 1)
		} else {
			i = append(i, i[len(i)-2]+i[len(i)-1])
		}
		return i[len(i)-1]
	}
}

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

@is3ka1
Copy link

is3ka1 commented Feb 17, 2021

Using defer

package main

import "fmt"

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

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

@drewkiimon
Copy link

I like your answer! I can do fib numbers but a bit tricky with this problem with closures. Thank you for your answer!

@Dimedrolity
Copy link

one letter variables is evil (except loop var)

traditional

func fibonacci() func() int {
	current := 0
	next := 1

	return func() int {
		current, next = next, current+next

		return current
	}
}

with defer

func fibonacci() func() int {
	current := 1
	next := 1

	return func() int {
		defer func() {
			current, next = next, current+next
		}()

		return current
	}
}

@Rexoen
Copy link

Rexoen commented Aug 7, 2022

package main

import "fmt"

func fibonacci() func() []int {
	arr := make([]int,0)
	return func() []int {
		switch len(arr){
			case 0:
				arr = append(arr,0)
			case 1:
				arr = append(arr,1)
			default:
				arr = append(arr,arr[len(arr)-1]+ arr[len(arr)-2])
			
		}
		return arr
	}
}

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

@PradeepLR01
Copy link

PradeepLR01 commented Sep 8, 2022

Here is my solution -

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	x, y := 0, 1
	return func() int{
		x++
		y++
		return (x-1)+(y-2)
	}

}

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

@kash74
Copy link

kash74 commented Sep 14, 2022

Not as elegant but doing the job:

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	i := -1
	f1 := 0
	f2 := 1
	return func() int {
		switch i+=1; i {
		case 0:
			return 0	
		case 1:
			return 1
		default:
			f := f1 + f2
			f1 = f2
			f2 = f
			return f
		}
	}
}

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

@netmanyys
Copy link

We can omit the variable f with

package main

import "fmt"

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

func fibonacci() func() int {
	f1, f2 := 0, 1
	return func() int {
		f1, f2 = f2, f1+f2
		return f1
	}
}

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

@vojtaripa
Copy link

similar to other solutions using if statements
Hope it helps someone out there

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func(int) int {
	
	prev2 := 0
	prev1 := 1
	
	return func(x int ) int{
		
		sum:=0
		
		//SKIPPING FIRST 2 ITTERATION
		if x == 0{
			return 0
		}else if x == 1{
			return 1
		}else{
			//Staring at 2 value should still be 1
			sum = prev1 + prev2
		}
	
		//THEN MAKE PREVIOUS VALUES CURRENT FOR NEXT ITTERATION
		prev2 = prev1 
		prev1 = sum 
		
		
		//RETURN THE RESULT
		return fib
	}
	
}

func main() {
	//Assigning a function fibonacci
	f := fibonacci()
	
	//now looping through and passing i each time
	for i := 0; i < 10; i++ {
		fmt.Println(i,"->",f(i))
	}
}

@krapie
Copy link

krapie commented Dec 7, 2022

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	f1, f2 := 0, 1
	
	return func() int {
		// f is previous fibonacci number
		// f() closure actually returns
		// previous fibonacci number
		f := f1
		f1, f2 = f2, f1+f2
		
		return f
	}
}

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

@u-onder
Copy link

u-onder commented Dec 29, 2022

With defer

func fibonacci() func() int {
	var v0, v1 int = 0,1
	advance := func () {
		v0, v1 = v1, v0+v1
	}
	return func() int {
		defer advance()
		return v0
	}
}

@alkstsgv
Copy link

package main

import "fmt"

func fibonacci() func() uint64 {
	
	a := uint64(0)
	b := uint64(0)
	c := uint64(a + b)

	return func() uint64 {
		if c-a > c-b {
			c = c + (c - a)
			a = c - b
			return c
		} else if c-a < c-b {
			c = c + (c - b)
			b = c - a
			return c
		} else if c == c {
			a += 0
			b += 1
			c += 1
			return c
		}
		return c
	}
}

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

@Max95Cohen
Copy link

package main

import "fmt"

func fibonacci() func() int {
	f := [10]int{0, 1}
	i := 0

	return func() int {
		last := i
		i++

		if last == 0 || last == 1 {
			return f[last]
		}

		f[last] = f[last-1] + f[last-2]

		return f[last]
	}
}

func main() {
	f := fibonacci()

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

@jacktrusler
Copy link

jacktrusler commented Oct 8, 2023

package main

import "fmt"

func fibonacci() func() int {
	fib, temp, next := 0, 0, 1
	
	return func() int {
		fib = temp
		temp = next
		next = fib + temp
		return fib
	}
}

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

@KJ1010G
Copy link

KJ1010G commented Mar 4, 2024

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
	num := 0
	nextNum := 1
	advance := func () {
		temp := nextNum
		nextNum = num + nextNum
		num = temp
	}
	return func () int {
		defer advance()
		return num
	}
}

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

@forbidden-game
Copy link

package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
f1 := 0
f2 := 1
reFunc := func() int {
f := f1
f1 = f2
f2 = f + f1
return f
}
return reFunc
}

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

@liminspace
Copy link

package main

import "fmt"

func fibonacci() func() int {
	a, b := 1, 0
	return func() int {
		a, b = b, a + b
		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