返回由第二个列表中的相应值定义的第一个列表的每个元素的方案函数



我目前正在尝试创建一个名为反向计数的函数,该函数以相反的顺序返回字符列表,这些字符重复多次,由第二个数字列表的相应元素指定。

例如:

(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))))))))

如何解决此问题?

你有很多问题。

  1. 您正在调用数字比较函数 positive?<> 以列表作为参数。您希望比较列表的长度,而不是列表本身。并且您要测试列表中的元素是否为正数。

  2. 当计数列表的元素为正时,您不应该报告错误,而应该在它为负数时抱怨。

  3. 你在打电话给make-string.但要求不是包含列表元素的多个副本的字符串,重复项应该是结果中的单独元素。

  4. 您需要在所有递归之后反转最终结果,而不是反转对单个元素的操作。

它还有助于使用比 ls1ls2 更有意义的变量名称。

(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))))))

最新更新