在球拍中编写交替的系列检查器

时间:2019-02-11 04:10:15

标签: recursion math scheme racket

我正在尝试制作一个程序,该程序确定输入的列表是否用符号替代。例如,如果给出以下列表,则我的程序将返回true:[-1、5,-10]或[5,-17、25]。如果给出以下列表,则程序将返回false:[-1,-5、6]或[1,-2,-6]。

我尝试过做一个简单的cond语句,该语句检查列表中第一个数字的符号,然后在检查列表中的第二个数字以确保第一个数字为正,第二个数字为负或第一个数字是负数,第二个数字是正数。

(define (alternating-signs-in-list? lst)
  (cond 
        [(> (first lst) 0)
         (cond [(< (first (rest lst)) 0) (alternating-signs-in-list? (rest lst))])]
        [(< (first lst) 0)
         (cond [(> (first (rest lst)) 0) (alternating-signs-in-list? (rest lst))])]
        [else false]))

我希望所提供的代码能够正常工作,但遇到错误,指出:

first:需要一个非空列表;给定:空

我进行以下检查时发生了此错误:

(check-expect (alternating-signs-in-list? (cons 1 (cons -5 (cons 50 empty)))) true).

为什么会发生以下错误,我是否可以通过简单的方法使代码开始工作。谢谢。

1 个答案:

答案 0 :(得分:2)

技巧是同时比较成对的元素(列表的第一和第二个),直到列表用完为止。您收到的错误是因为您忘记处理空列表的情况,尤其是对于此问题,当列表仅剩一个元素时,我们还需要处理这种情况。

在继续之前,实现same-sign?过程非常有用,如果我们利用sgn过程(返回数字的 sign ),并且假设0是肯定的:

(define (same-sign? n1 n2)
  ; they have the same sign if their `sgn` value is the same
  (= (if (zero? n1) 1 (sgn n1))
     (if (zero? n2) 1 (sgn n2))))

主要过程如下:

(define (alternating-signs-in-list? lst)
  (cond ((or (empty? lst) (empty? (rest lst))) #t) ; empty list / single element case
        ((same-sign? (first lst) (second lst)) #f) ; they are NOT alternating
        (else (alternating-signs-in-list? (rest lst))))) ; advance recursion

或者,我们也可以只使用布尔连接器来编写上面的代码:

(define (alternating-signs-in-list? lst)
  (or (empty? lst)
      (empty? (rest lst))
      (and (not (same-sign? (first lst) (second lst)))
           (alternating-signs-in-list? (rest lst)))))

无论哪种方式,它都能按预期工作:

(alternating-signs-in-list? '(-1 5 -10))
=> #t
(alternating-signs-in-list? '(5 -17 25))
=> #t
(alternating-signs-in-list? '(-1 -5 6))
=> #f
(alternating-signs-in-list? '(1 -2 -6))
=> #f