Написание чередующейся серии шашек в ракетке - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь создать программу, которая определяет, чередуется ли введенный список со знаком.Например, моя программа возвратила бы 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 голосов
/ 11 февраля 2019

Хитрость заключается в одновременном сравнении пар элементов (первой и второй в списке), пока список не будет исчерпан.Ошибка, которую вы получаете, заключается в том, что вы забыли обработать случай с пустым списком, и для этой проблемы, в частности, нам также нужно обработать случай, когда в списке остается один элемент.

Прежде чем продолжить,полезно реализовать процедуру same-sign?, это легко, если мы используем процедуру sgn (которая возвращает знак числа), и если мы предположим, что 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
...