Recursion 方案扩展函数

Recursion 方案扩展函数,recursion,scheme,Recursion,Scheme,我已经试着解决这个问题好几个小时了。 函数expand,它获取元素和频率的列表,并将它们扩展为一个简单的列表。例如,(expand’(a(3b)(3a)b(2c)(3a))的结果应该是(abbcaa) 以下是我的解决方案: 辅助功能: (define (expandHelper n value) (if (= 0 n) '() (cons (append (cons value '()))(expandHelper (- n 1) value)))) 扩展函

我已经试着解决这个问题好几个小时了。 函数expand,它获取元素和频率的列表,并将它们扩展为一个简单的列表。例如,(expand’(a(3b)(3a)b(2c)(3a))的结果应该是(abbcaa)

以下是我的解决方案:


辅助功能:

(define (expandHelper n value)
  (if (= 0 n) 
      '()
      (cons (append (cons value '()))(expandHelper (- n 1) value)))) 

扩展函数

(define (expand lst) 
  (cond ((null? lst) '())
    (else (expandHelper (car lst) (cadr lst)))))

但是,它没有达到我期望的效果。当列表只有一个元素作为值时,它会查找整数。例如,(expand'(a(2 b))。因为只有一个a的副本,所以表达式中没有(1 a)。我是Scheme的新手。如果您能帮我,我将非常感谢

谢谢

这是一个更新版本:但它仍然不正确。如果有人能帮助我修改代码以获得正确的结果,我将非常感激

;; helper function
(define (expandHelper value)
  (if (= 0 value) 
      '()
      (cons (append (cons (car sublist) '()))(expandHelper (- (car sublist) 1) (car sublist)))))  

;; the expand function
(define (expand lst) 
  (cond ((null? lst) '())
        (else (list? (car lst)) (expandHelper (car lst)) (expand (cadr lst)))))

这里有两件事你应该考虑。第一件是你提到的一件事——你可以有
a
(1a)
,两者的意思都是一样的。你可能想把它移到
expandHelper
,所以它看起来更像
(expandHelper值)
,然后您应该打开它是列表还是符号

第二个问题是如何调用
expandHelper
。如果您输入一个类似
'(a(3b)(3a)b(2c)(3a))
expand
,它当前将调用
(expandHelper a(3b))
,这可能不是您想要的。相反,您希望确保对列表的每个元素调用
expandHelper
,并将结果一起调用
cons
。您可以通过对列表的第一个元素调用
expandHelper
,然后对列表的其余元素递归调用
expand
名单

我还没有检查是否编译,这只是一般的想法:

(define (expandHelper value)
    (if (list? value) ;; means value is something like (2 a)

        (if (= 0 (car value)) ;; then (car value) is 2
            '() ;; if it's zero, we complete the list and return!
            (cons (cadr value) ;;otherwise, we append (cadr value) = a to...
                  (expandHelper (cons (- (car value) 1) (cadr value))))))
                  ;; the result of expand helper on (- (car value) 1) = 1 
                  ;; and (cadr value) = a

         (cons value '()))) ;; if it's not a list, we should just return the value.
所以…
term expander
(5 a)
->
(a a)
追加展开
将最新的术语(如果它是一对展开的术语)追加到我们正在进行的答案中。只需将其折叠到列表中即可

我希望你已经有一个
foldl
,但这是我的以防万一

(define (foldl op seq init)
  (define (iter acc rest)
    (if (null? rest)
      acc
      (iter (op acc (car rest)) (cdr rest))))
  (iter init seq))

编辑 后来意识到,这可以通过
foldr
而不是
foldl
更自然地完成(需要以不同的方式编写
append expand
)你为什么不看看你是否能找到它呢?基本上是相同的想法,但它会从后面到前面在列表上运行,并且更自然地适用于
cons
结构


这是我做它没有折叠,但它的工作方式相同,我真的不喜欢它

(define (term-expander p partial)
  (if (zero? (car p))
    partial
    (term-expander (cons (- (car p) 1) (cdr p)) (cons (cadr p) partial))))

(define (expand l)
  (define (expand-rec l partial)
    (if (null? l)
      partial
      (let ((t 
        (if (pair? (car l))
             (term-expander (car l) '())
             (list (car l)))))
      (expand-rec (cdr l) (append partial t)))))
  (expand-rec l '()))

> (expand '(a (3 b) (3 a) b (2 c) (3 a)))
(a b bb a a a b c c a a a)
如果您愿意的话,
(If(pair?…
部分可以改为
术语扩展器,然后您可以全面调用它。我稍微喜欢这种方式,但它都是相同的
 (define (expand l)
   (cond ((null? l) '())
         ((not (pair? (car l))) (cons (car a) (expand (cdr l)))
         ((< (caar l) 1) (expand (cdr l)))
         (else (cons (cadar l)) (expand (cons (cons (- (caar l) 1) (cdar l))
                                                (cdr l))))))
(cond((null?l)“”()) ((非(对)(左车))(反(a车)(展开(左车))) (<(caar l)1)(扩展(cdr l))) (其他(cons(cadar l))扩展(cons(cons(-(caar l)1)(cdar l)) (cdr l(()()))
这将是我的解决方案,没有任何辅助函数,在子列表上递归(即,(3 a)变成(cons a(expand'(2 a)):


您可以将其表示为右折叠,并避免开发自定义递归函数。如果下一个元素是类似于
(3 a)
的列表,请展开并在其前面加上前缀。如果是符号,只需
cons
即可

(define (expand xs)
  (fold-right
   (lambda (x result)
     (if (list? x)
     (append (apply make-list x) result)
         (cons x result)))
   '()
   xs))

也许我只是有点难,但是什么是
a
b
c
?它们是标识符吗?只是代表你讨论中的整数文本?你想让它们被引用并用作字符吗?显然,这个函数不能完全像你那样调用describe@jon_darkstar:它们是符号。@jon_darkstar:它们是符号,并且它们的使用方式没有问题。你错过了这句话吗?@dfan:yep=P他的函数调用很好,显然,我在下面的回答中一字不差地使用了它。对不起,普伽默,你读过了吗?很难对递归给出一个简明但易懂的描述,这本书做得非常好。这就是我所说的我也在想,但是,我不知道如何实现它。我对Scheme还不熟悉,也有点困惑。我不知道如何更改expandHelper。有没有不使用高阶函数的方法可以做到这一点?当然,但你实际上只是在做等效的事情。如果你选择这样做,如果你这样做,它可能会变得更自然
(如果(配对?…
填充到
术语扩展器中
实际上可以将其划掉。我只会在配对中调用它,以开始感谢您的帮助。有没有办法修改expandHelper以获得相同的结果?可能有几个函数?可能我只是有点困惑。我正在尝试使用一个助手函数来扩展每个列表。这不是
术语扩展器吗
?我发布了一个新的,没有使用
折叠
,但我并不特别关心它,我也不认为有任何方法可以显著改变它(只是一些肤浅的选择,如let vs if之类),当然还有方向(向前/向后,即iter/rec),这相当于在foldr和Foldl之间进行选择。这太优雅了,我仔细考虑了一下。我喜欢使用列表。
#lang racket

(define (expand lst)
  (cond
    ((null? lst) '())
    ((list? (car lst))
     (let ((cnt (caar lst)) (chr (cadar lst)))
       (if (= cnt 0)
           (expand (cdr lst))
           (cons chr (expand (cons (list (- cnt 1) chr) (cdr lst)))))))
    (else (cons (car lst) (expand (cdr lst))))))
(define (expand xs)
  (fold-right
   (lambda (x result)
     (if (list? x)
     (append (apply make-list x) result)
         (cons x result)))
   '()
   xs))