返回第二列表中相应值所定义的第一列表中每个元素的计划函数

时间:2018-12-28 16:10:30

标签: scheme racket

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

例如:

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

如何解决此问题?

3 个答案:

答案 0 :(得分:3)

您遇到许多问题。

  1. 您正在使用列表作为参数调用数字比较函数positive?<>。您想比较列表的长度,而不是列表本身。然后您要测试列表中的 是否为正。

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

  3. 您正在呼叫make-string。但是要求不是一个包含list元素多个副本的字符串,重复项应该是结果中的单独元素。

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

答案 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))))))