Функция Scheme, которая возвращает каждый элемент первого списка, определенный значением соответствующего кода во втором списке - PullRequest
0 голосов
/ 28 декабря 2018

В настоящее время я пытаюсь создать функцию под названием reverse-with-count, которая возвращает список символов в обратном порядке, которые повторяются несколько раз, как указано соответствующим элементом второго списка чисел.

Например:

(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 голосов
/ 29 декабря 2018

Хвостово-рекурсивное решение

Поскольку хвостовые рекурсивные решения на основе аккумулятора обычно дают свои результаты уже в обратном порядке при повторном использовании 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))))))
0 голосов
/ 29 декабря 2018

Вот еще одно хвостовое рекурсивное решение с использованием 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)
0 голосов
/ 28 декабря 2018

У вас есть ряд проблем.

  1. Вы вызываете функции числового сравнения positive?, < и > со списками в качестве аргументов.Вы хотите сравнить длины списков, а не сами списки.И вы хотите проверить, является ли элемент списков положительным.

  2. Вы не должны сообщать об ошибке, когда элемент списка подсчета является положительным, выдолжен жаловаться, когда он отрицательный.

  3. Вы звоните make-string.Но требование не является строкой с несколькими копиями элемента списка, дубликаты должны быть отдельными элементами в результате.

  4. Вам необходимо полностью изменить окончательный результат после всех рекурсий,не отменять операцию для одного элемента.

Также помогает использовать более значимые имена переменных, чем 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)))))
...