我目前正在尝试创建一个称为反向计数的函数,该函数以相反的顺序返回一个字符列表,这些字符按照第二个数字列表的相应元素所指定的次数重复执行。
例如:
(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子句是正确的,但是我在设定的条件下(期望 real )在代码中遇到错误?
这是我到目前为止所做的:
(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))))))))
如何解决此问题?
答案 0 :(得分:3)
您遇到许多问题。
您正在使用列表作为参数调用数字比较函数positive?
,<
和>
。您想比较列表的长度,而不是列表本身。然后您要测试列表中的 是否为正。
当计数列表的元素为正时,您不应报告错误;当计数列表的元素为负时,您不应抱怨。
您正在呼叫make-string
。但是要求不是一个包含list元素多个副本的字符串,重复项应该是结果中的单独元素。
您需要在所有递归之后反转最终结果,而不是反转单个元素上的操作。
与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)))))
答案 1 :(得分:2)
这是另一个使用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)
答案 2 :(得分:1)
尾递归解决方案
由于基于累加器的尾部递归解通常会通过重复使用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))))))