Functional programming Scheme-达到一定值的斐波那契数列表
我试图编写一个函数,创建一个斐波那契序列列表,但当列表中找到某个值时停止,然后返回该列表(我希望这是有意义的) 例如,如果我给它fib list(55),函数应该返回:Functional programming Scheme-达到一定值的斐波那契数列表,functional-programming,scheme,fibonacci,Functional Programming,Scheme,Fibonacci,我试图编写一个函数,创建一个斐波那契序列列表,但当列表中找到某个值时停止,然后返回该列表(我希望这是有意义的) 例如,如果我给它fib list(55),函数应该返回: (11 2 3 5 8 13 21 34 55) 所以这不是我想要的第55个斐波那契数,它的值是55 到目前为止,我用于返回列表的代码如下所示: ; Create a list of the fibonacci sequence up to n. (define (fib-list n) ; n = n, f2 = 1, f
(11 2 3 5 8 13 21 34 55)
所以这不是我想要的第55个斐波那契数,它的值是55
到目前为止,我用于返回列表的代码如下所示:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((equal? n (car fs)) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
(display (fib-list 55))
我的主要问题是查找列表中是否有一个元素,因为此时我在尝试编写((equal?
语句)的行上遇到了一个错误
错误显示:
mcar: contract violation
expected: mpair?
given: '()
我对Scheme还是非常陌生,所以我对语言的整体理解不是很好。所以请温和地告诉我为什么我的代码很糟糕/没有意义。汽车的功能出了什么问题?
car
函数获取列表的第一个元素,但如果列表为空,则没有第一个元素。fs
列表开始时为空。当您尝试获取空列表的第一个元素时,会收到以下错误消息:
> (car (list))
mcar: contract violation
expected: mpair?
given: ()
如果列表不是空的,那么它有第一个元素,这很好:
> (car (list 4 5 6))
4
按照你在评论中的意思
然而,您的评论“检查n是否在列表中”使我相信(equal?n(car fs))
不是您想要的。用于确定元素是否在列表中的函数被调用
因此,将(equal?n(car fs))
测试替换为(member n fs)
,您的代码如下所示:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((member n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(10946 6765 4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1)
这不是你想要的答案;你想要的是(1112355813213455)
为什么列表超过了55
?
其中一个问题是n
被隐藏,其方式与此表达式中的方式相同:
> (let ([n 5])
(let ([n 10])
n))
10
正文中的n
指的是10
,而不是5
结果超过了55
,因为循环内部n
被阴影覆盖,变成了一个不同的数字。我猜在你关于“检查n是否在列表中”的评论中,你的意思是“检查原始n是否在列表中”。为此,你必须重命名n
s中的一个:
> (let ([orig-n 5])
(let ([n 10])
orig-n))
5
在代码的上下文中:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return list.
((member orig-n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(55 34 21 13 8 5 3 2 1 1)
颠倒
这更接近,但它是相反的。您有两个基本情况,即(zero?n)
情况和(member orig-n fs)
情况。在其中一个情况下,它是相反的,而在其中一个情况下,它不是。将它们都更改为调用reverse可以修复它:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
小数目
这在像55
这样的大斐波那契数上是正确的,但在小数上它仍然会做一些奇怪的事情:
> (fib-list 2)
(1 1)
> (fib-list 3)
(1 1 2)
如果您只希望它在到达orig-n
时停止,那么可能不需要递减n
参数,实际上使它停止得太早。删除它(并删除其零检查)会使成员检查唯一停止的情况
这是很危险的,因为如果你给它一个非斐波那契数作为输入,它可能会进入一个无限循环。但是,它修复了一些小数字示例:
; Create a list of the fibonacci sequence up to n.
; The `orig-n` MUST be a fibonacci number to begin with,
; otherwise this loops forever.
(define (fib-list orig-n)
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 2)
(1 1 2)
> (fib-list 3)
(1 1 2 3)
最后,考虑一下发生了什么事情,如果你给它一个数字,比如<代码> 56 /代码>。
> (fib-list 56)
;infinite loop
这是一个您尚未在问题中指定的设计决策,但有两种方法可以解决它
更新:orig-n
或更高版本
我应该指定我需要检查是否有一个大于或等于orig-n
的数字。我仍然可以使用member
功能检查这个数字,还是需要使用其他数字
您必须使用不同的东西。文档中member
的正上方是函数(您也可以在本例中使用)。mem
是member的缩写,p
是“predicate”的缩写。它确定列表中的任何成员是否与某个谓词匹配
> (if (memp positive? (list -4 -2 -3 5 -1))
"one of them is positive"
"go fish")
"one of them is positive"
> (if (memp positive? (list -4 -2 -3 -5 -1))
"one of them is positive"
"go fish")
"go fish"
> (define (five-or-greater? n)
(>= n 5))
> (if (memp five-or-greater? (list -4 -2 -3 6 -1))
"one of them is equal to 5 or greater"
"go fish")
"one of them is equal to 5 or greater"
> (if (memp five-or-greater? (list -4 -2 -3 4 -1))
"one of them is equal to 5 or greater"
"go fish")
"go fish"
要将其用于“orig-n或更高版本”,必须定义如下函数:
(define (orig-n-or-greater? n)
(>= n orig-n))
作为主函数中的本地函数,以便它可以引用orig-n
。然后可以像(memp orig-n-or-more?fs)
一样使用它
汽车
功能出了什么问题?
car
函数获取列表的第一个元素,但如果列表为空,则没有第一个元素。fs
列表开始时为空。当您尝试获取空列表的第一个元素时,会收到以下错误消息:
> (car (list))
mcar: contract violation
expected: mpair?
given: ()
如果列表不是空的,那么它有第一个元素,这很好:
> (car (list 4 5 6))
4
按照你在评论中的意思
然而,您的评论“检查n是否在列表中”使我相信(equal?n(car fs))
不是您想要的。用于确定元素是否在列表中的函数被调用
因此,将(equal?n(car fs))
测试替换为(member n fs)
,您的代码如下所示:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((member n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(10946 6765 4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1)
这不是你想要的答案;你想要的是(1112355813213455)
为什么列表超过了55
?
其中一个问题是n
被隐藏,其方式与此表达式中的方式相同:
> (let ([n 5])
(let ([n 10])
n))
10
正文中的n
指的是10
,而不是5
结果超过了55
,因为循环内部n
被阴影覆盖,变成了一个不同的数字。我猜在你关于“检查n是否在列表中”的评论中,你的意思是“检查原始n是否在列表中”。为此,你必须重命名n
s中的一个:
> (let ([orig-n 5])
(let ([n 10])
orig-n))
5
在代码的上下文中:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return list.
((member orig-n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(55 34 21 13 8 5 3 2 1 1)
颠倒
这更接近,但它是相反的。您有两个基本情况,即(zero?n)
情况和(member orig-n fs)
情况。在其中一个情况下,它是相反的,而在其中一个情况下,它不是。将它们都更改为调用reverse可以修复它:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
小麻木