我目前正在尝试创建一个名为反向计数的函数,该函数以相反的顺序返回字符列表,这些字符重复多次,由第二个数字列表的相应元素指定。
例如:
(reverse-with-count '(a b c) '(1 2 3)) => (c c c b b a)
(reverse-with-count '(d c b a) '(3 0 0 1)) => (a d d d)
我相信我的 else 子句是正确的,但我在我设置的条件的代码中出现错误,它在哪里期望真实?
这是我到目前为止所做的:
(define reverse-with-count
(lambda (ls1 ls2)
(cond
((null? ls2) ls1)
((positive? ls2) (error "Please enter a positive number!"))
((> ls1 ls2)(error "Please ensure the lists are the same size."))
((< ls1 ls2)(error "Please ensure the lists are the same size."))
(else
(cons (reverse (make-string (car ls2)(ls1))
(reverse-with-count (cdr ls2)(cdr ls1))))))))
如何解决此问题?
你有很多问题。
-
您正在调用数字比较函数
positive?
、<
和>
以列表作为参数。您希望比较列表的长度,而不是列表本身。并且您要测试列表中的元素是否为正数。 -
当计数列表的元素为正时,您不应该报告错误,而应该在它为负数时抱怨。
-
你在打电话给
make-string
.但要求不是包含列表元素的多个副本的字符串,重复项应该是结果中的单独元素。 -
您需要在所有递归之后反转最终结果,而不是反转对单个元素的操作。
它还有助于使用比 ls1
和 ls2
更有意义的变量名称。
(define reverse-with-count
(lambda (symbols counts)
(let ((recurse
(lambda (symbols counts)
(cond
((null? counts) symbols)
((negative? (car counts))
(error "Please enter a positive number!"))
((not (= (length symbols) (length counts)))
(error "Please ensure the lists are the same size."))
((= 0 (car counts))
;; Skip element when count is 0
(reverse-with-count (rest symbols) (rest counts)))
(else
;; Recurse with a decremented count for the first element
(cons (car symbols)
(reverse-with-count
symbols
(cons (- (car counts) 1) (rest counts)))))))))
(reverse (recurse symbols counts)))))
<</div>
div class="one_answers"> 这是另一个使用 match*
的尾部递归解决方案 -
#lang racket
(define (reverse-with-count xs ys (acc null))
(match* (xs ys)
;; zero case
[((list _ xs ...) (list 0 ys ...))
(reverse-with-count xs ys acc)]
;; non-zero case
[((list x _ ...) (list y ys ...))
(reverse-with-count xs
(cons (- y 1) ys) ;; decrement y
(cons x acc))] ;; cons onto acc
;; any other case
[(_ _)
acc]))
按预期工作 -
(reverse-with-count '(a b c) '(1 2 3))
;; '(c c c b b a)
(reverse-with-count '(d c b a) '(3 0 0 1))
;; '(a d d d)
尾递归解决方案
由于基于累加器的尾递归解决方案通常通过重复使用cons
产生相反的结果,因此它很自然地适合这里的问题:
(define (reverse-with-count symbols counts (acc '()))
(cond ((and (null? symbols) (null? counts)) acc)
((or (null? symbols) (null? counts))
(error "Please ensure the lists are of same length."))
((<= (car counts) 0) ; treat negative numbers as zero
(reverse-with-count (cdr symbols) (cdr counts) acc))
(else
(reverse-with-count symbols
(cons (- (car counts) 1) (cdr counts))
(cons (car symbols) acc)))))
旧答案是:
(define (reverse-with-count symbols counts (acc '()))
(let ((sym-len (length symbols)))
(cond ((not (= sym-len (length counts)))
(error "Please ensure the lists are the same size."))
((zero? sym-len) acc)
((< (car counts) 0)
(error "Please enter a positive number!"))
((= (car counts) 0)
(reverse-with-count (cdr symbols) (cdr counts) acc))
(else
(reverse-with-count symbols
(cons (- (car counts) 1) (cdr counts))
(cons (car symbols) acc))))))