我正在尝试编写一个函数来检查给定列表是否呈螺旋状(数字从负数变为正数,而数字的绝对值严格增加)
EX:
(check-expect
(spiraling? (cons 1 (cons -10 (cons 100 empty))))
true)
我甚至不确定我的错误在哪里,所以我在我的写作中做了一些调整,没有做任何事情。
(define (spiraling? list-of-int)
(cond
[(empty? list-of-int) true]
[(and (number? (first list-of-int))
(empty? (rest list-of-int))) true]
[(and (< (abs (first list-of-int))
(abs (first (rest (first list-of-int)))))
(cond
[(and (> 0 (first list-of-int))
(< 0 (first (rest (first list-of-int)))))true]
[(and (< 0 (first list-of-int))
(> 0 (first (rest (first list-of-int)))))true]
[else false]))
(cond
[(empty? list-of-int) true]
[else (spiraling? (rest list-of-int))])]))
(check-expect
(spiraling? (cons 1 (cons -10 (cons 100 empty))))
true)
(check-expect
(spiraling? (cons -1 (cons 2 (cons -3 (cons 4 empty)))))
true)
(check-expect
(spiraling? (cons 99 (cons -100 (cons 100 empty))))
false)
(check-expect
(spiraling? (cons 0 (cons -10 (cons 100 empty))))
false)
但它反过来说:
:: rest: expects a non-empty list; given: ()
你的程序有许多不连贯性。
首先,函数的参数应该是整数列表,但有时您将它用作列表列表,例如当您编写时:
(abs (first (rest (first list-of-int)))))
实际上(first list-of-int)
应该返回一个整数(列表的第一个元素),但是你应用它rest
,这是一个应用于非空列表的运算符返回没有第一个元素的列表。这就是错误消息的原因(“休息期望非空列表但收到1”)。
如果你想要列表的第二个元素,你可以做(first (rest list))
,或者更好的(second list)
。这些是该语言的基本操作符。
其次,在cond
的第二个分支中,您检查列表的第一个元素是否是数字,但是在第三个分支中不会重复此检查,即使您同时使用第一个和第二个元素作为数字。因此测试是无用的,因为它仅在某些情况下应用于列表的某些元素。您应该适用于所有元素或不应该元素,以保持一致。
第三,在cond的最后一个分支中,在最后两行中,你再次检查列表是否为空,但是在程序的这一点上,列表肯定不是空的,因为你已经测试了至少两个元素!
这是一个可能的解决方案(不检查所有元素是否都是数字):
(define (spiraling? list-of-int)
(if (or (empty? list-of-int) (empty? (rest list-of-int)))
true
(let ((first-element (first list-of-int))
(second-element (second list-of-int)))
(if (or (< first-element 0 second-element)
(> first-element 0 second-element))
(spiraling? (rest list-of-int))
false))))