Есть несколько проблем с размещенным кодом. Во втором предложении cond
нет тестового выражения; вокруг if
и его пунктов слишком много скобок. Возможно, наиболее существенной проблемой является то, что код пытается создать неубывающий список, который должен быть cons
отредактирован до результата (nondecreaselist (cdr s))
, но когда неубывающая последовательность имеет длину более одного числа, это начинается снова слишком рано в списке ввода, вернувшись обратно к (cdr s)
.
Исправление кода операции
Лог c можно очистить. ОП-код уже возвращает пустой список, когда ввод является пустым списком. Вместо проверки (null? (cadr s))
(когда (cdr s)
равен '()
, cadr
не будет работать на s
), можно протестировать (null? (cdr s))
до того, как код попытается (cadr s)
. Но еще лучше перенести эту логику; если входной список содержит один элемент, просто верните список, содержащий входной список: ((null? (cdr s)) (list s))
.
Вместо (and (not (> ;...
логика c может быть прояснена путем тестирования на >
и выполнения соответствующее действие. В этом случае, когда (> (car s) (cadr s))
должен быть запущен новый подсписок, и cons
добавляется в список подсписков, который является результатом, возвращаемым из nondecreaselist
.
В противном случае, (car s)
следует добавить к первый подсписок в результате вернулся с nondecreaselist
. Чтобы выполнить sh, нам нужно построить список возврата путем cons
ввода s
в первый подсписок и затем cons
, переместив этот новый подсписок обратно в cdr
списка подсписков, который является результат, возвращаемый из nondecreaselist
.
Вот некоторый пересмотренный код:
(define (nondecreaselist s)
(cond ((null? s) '())
((null? (cdr s)) (list s))
((> (car s) (cadr s))
(cons (list (car s))
(nondecreaselist (cdr s))))
(else
(let ((next (nondecreaselist (cdr s))))
(cons (cons (car s)
(car next))
(cdr next))))))
Использование вспомогательной функции
Другой подход заключается в определении вспомогательной функции, которая принимает список ввода и список накопления в качестве аргументов, возвращая список списков. Вспомогательная функция будет брать числа из передней части списка ввода и либо добавлять их в накопитель, создавая неубывающий список, либо получит cons
накопленный неубывающий список в результате работы с остальной частью input.
Если вход lst
для вспомогательной функции ndl-helper
пуст, то должен быть возвращен список, содержащий накопленный неубывающий список sublst
. Обратите внимание, что sublst
необходимо будет изменить до его возвращения из-за способа его построения, как описано ниже.
Если аккумулятор sublst
пуст или если следующий номер в списке ввода больше или равно наибольшему числу в sublst
, тогда следующее число должно быть просто добавлено к sublst
. При cons
введении числа в начало sublst
необходимо проверить только car
из sublst
, поскольку это всегда будет наибольшее (или равное наибольшему) значение в sublst
. Но, поскольку sublst
находится в обратном порядке, перед добавлением его в растущий список списков его необходимо перевернуть.
В противном случае lst
не пусто, а sublst
не пусто, и следующий номер в списке ввода меньше самого большого числа в sublst
. Таким образом, новый подсписок должен быть запущен, поэтому старый sublst
переворачивается и cons
обращается к результату оставшегося вычисления, выполненного путем вызова вспомогательной функции для оставшихся lst
с пустым аккумулятором sublst
:
(define (nondecreaselist-2 lst)
(define (ndl-helper lst sublst)
(cond ((null? lst) (list (reverse sublst)))
((or (null? sublst)
(>= (car lst) (car sublst)))
(ndl-helper (cdr lst) (cons (car lst) sublst)))
(else
(cons (reverse sublst) (ndl-helper lst '())))))
(ndl-helper lst '()))
Обе функции работают:
> (nondecreaselist '(1 2 3 4 1 2 3 4 1 1 1 2 1 1 0 4 3 2 1))
((1 2 3 4) (1 2 3 4) (1 1 1 2) (1 1) (0 4) (3) (2) (1))
> (nondecreaselist-2 '(1 2 3 4 1 2 3 4 1 1 1 2 1 1 0 4 3 2 1))
((1 2 3 4) (1 2 3 4) (1 1 1 2) (1 1) (0 4) (3) (2) (1))