Закрытие Фибоначчи
Я слежу за гастролями на своем официальном сайте, и меня попросили написать генератор Фибоначчи. Вот он:
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
first := 0
second := 0
return func() int{
if(first == 0) {
first = 1
second = 1
return 0
}else {
current := first
firstc := second
second = first + second
first = firstc
return current
}
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Это работает. Однако я считаю это очень уродливым, и я уверен, что должно быть лучшее решение. Я думал о публикации этого в обзоре кода, так как я прошу лучшего подхода, я думал, что это подходящее место для публикации.
Есть ли лучший способ написать этот код?
Вот задача:
Реализуйте функцию фибоначчи, которая возвращает функцию (замыкание), которая возвращает последовательные числа фибоначчи.
Ответы
Ответ 1
Мой любимый чистый способ реализовать итерацию по номерам Фибоначчи - это использовать first
как f я - 1 и second
как f i. Уравнение Фибоначчи утверждает, что:
f я + 1= f i + f я - 1
За исключением случаев, когда мы пишем это в коде, в следующем раунде мы увеличиваем i
. Итак, мы эффективно делаем:
f next i= f current i + f current я - 1
и
f next я - 1= f current я - 1
Как мне это реализовать в коде:
first, second = second, first + second
Часть first = second
соответствует обновлению f next я - 1= f current я - 1, а часть second = first + second
соответствует обновлению f next i= f current i + f current я - 1.
Тогда все, что нам осталось сделать, это вернуть прежнее значение first, поэтому мы сохраним его в переменной temp, прежде чем делать обновление. В итоге получаем:
// fibonacci returns a function that returns
// successive fibonacci numbers from each
// successive call
func fibonacci() func() int {
first, second := 0, 1
return func() int {
ret := first
first, second = second, first+second
return ret
}
}
Посмотрите в действии на Go Playground.
Ответ 2
Я бы использовал множественное назначение, уменьшал длину идентификаторов и удалял это, если statment:
func fibonacci() func() int {
var a, b int
b = 1
return func() int {
ret := a
a, b = b, a+b
return ret
}
}
Ответ 3
Другой подход
func fibonacci() func() int {
n1, n := -1, 1
return func() int {
n1, n = n, n1+n
return n
}
}
Игровая площадка Go Go
Ответ 4
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
a, b, sum := 1, 1, 0
return func() int {
a,b = b,sum
sum = a + b
return b
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Ответ 5
Помимо уже предоставленных ответов вы также можете использовать для этого функцию отсрочки:
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
secondLast := 0
last := 1
return func() int {
defer func() {
secondLast, last = last, secondLast+last
}()
return secondLast
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Go Playground
Но я думаю, что ответы от jwoodalls - самые эффективные.
Редактировать: Но если вы хотите использовать целые числа без знака (чтобы показать, сколько чисел Фибоначчи вы можете вычислить в вашей архитектуре;)), вам придется использовать либо подход с переменной, содержащей возвращаемое значение, либо функцию отсрочки.
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an uint.
func fibonacci() func() uint {
var secondLast uint
var last uint = 1
return func() uint {
defer func() {
secondLast, last = last, secondLast + last
}()
return secondLast
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Go Playground
EditEdit: Или еще лучше: используйте float64 !!!
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an float64.
func fibonacci() func() float64 {
var secondLast float64
var last float64 = 1
return func() float64 {
defer func() {
secondLast, last = last, secondLast+last
}()
return secondLast
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Go Playground
Ответ 6
Или вы можете использовать этот подход... простой и понятный, хотя и не сильно отличающийся от предыдущих ответов.
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
f1 := 0
f2 := 1
return func() int {
temp := f1+f2
temp2 := f1
f1 = f2
f2 = temp
return temp2
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Ответ 7
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
first:=0
second:=0
return func() int{
if second == 0 {
second = 1
} else if first == 0 {
first = 1
} else {
first, second = second, first + second
}
return second
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}