Scheme 如何在DrRacket ISL/Lambda中编写一个函数,将某些项目的出现移动到列表的末尾?

Scheme 如何在DrRacket ISL/Lambda中编写一个函数,将某些项目的出现移动到列表的末尾?,scheme,racket,Scheme,Racket,我正在努力学习如何做到这一点,我知道这涉及堆栈,但除非我看到一个函数在起作用,否则我无法对它进行思考。我们已经得到了这个要创建的函数示例,我需要一些帮助。这是: ;leafpile takes a list and returns the result of pushing all ;occurrences of the symbol 'leaf to the end of the list > (leafpile '(rock grass leaf l

我正在努力学习如何做到这一点,我知道这涉及堆栈,但除非我看到一个函数在起作用,否则我无法对它进行思考。我们已经得到了这个要创建的函数示例,我需要一些帮助。这是:

;leafpile takes a   list    and returns the result  of  pushing all 
;occurrences    of  the symbol  'leaf   to  the end of  the list

> (leafpile '(rock grass leaf leaf acorn leaf))
(list 'rock 'grass 'acorn 'leaf 'leaf 'leaf)
我们可以使用helper函数,但该函数需要以最小化递归过程的方式编写

更新(以下是我目前得到的信息)

好的,我有这个:

(define (helper lsh)
  (cond
    [(empty? lsh) '()]
    [(not(equal? (first lsh) 'leaf))
     (cons (first lsh) (helper (rest lsh)))]
    [else (helper (rest lsh))]))

(define (count-leaf ls)
  (cond
    [(empty? ls) 0]
    [(not (equal? 'leaf (first ls))) (count-leaf (rest ls))]
    [else (add1 (count-leaf (rest ls)))]))

(define (leafpile ls)
  (append (helper ls) (make-list (count-leaf ls) 'leaf)))

但我需要在一个简单的函数中使用尽可能少的递归过程。

以下是我提出的解决方案:

(define (leafpile lst)
  (for/fold ([pile (filter (lambda (leaf?) (not (equal? leaf? 'leaf))) lst)])
            ([i (build-list (for/fold ([leaves 0])
                                      ([leaf? lst])
                              (if (equal? leaf? 'leaf)
                                  (add1 leaves)
                                  leaves)) values)])
    (append pile '(leaf))))
工作原理:
for/fold
循环在一个列表上迭代,该列表的长度为存在的叶数,“collection value”是
lst
中所有元素的列表,这些元素不是符号
'leaf
(通过
过滤器实现)。
输入/输出示例:

>(树叶堆(岩石草叶橡子叶))
"(岩草橡子叶)


做到这一点非常简单的方法:

(define (leaf? v) 
  (eq? v 'leaf)) 

(define (leafpile lst)      
  (append (filter (compose not leaf?) lst)
          (filter leaf? lst)))
除非您遇到性能问题,否则它真的不需要更多,我通常不支持小列表。我倾向于认为元素少于一百万的列表很小。明显的递归可能不会更快:

(define (leafpile lst)
  (local [(define (leafpile lst n) ; screaming for a named let here!
          (cond
            ((null? lst) (make-list n 'leaf))
            ((leaf? (car lst)) (leafpile (cdr lst) (add1 n)))
            (else (cons (car lst) (leafpile (cdr lst) n)))))]
    (leafpile lst 0)))
累积非叶值、计算叶值并使用srfi/1
append reverse生成最终结果:

(require srfi/1)

(define (leafpile lst)
  (local [(define (leafpile lst acc n) ; I'm still screaming 
        (cond
          ((null? lst) (append-reverse! acc (make-list n 'leaf)))
          ((leaf? (car lst)) (leafpile (cdr lst) acc (add1 n)))
          (else (leafpile (cdr lst) (cons (car lst) acc) n))))]
    (leafpile lst '() 0)))

你好欢迎来到堆栈溢出。这似乎是一个家庭作业问题。家庭作业问题不一定是关于堆栈溢出的离题,但我们需要一个最低限度的演示,证明您已经尝试自己解决问题,以便我们可以帮助您朝着正确的方向前进。请发布您迄今为止尝试过的内容以及您遇到的问题,我们不会为您做家庭作业。我有我尝试实现的助手,但我遇到了一个错误。这不是家庭作业问题。实际上,我们在课堂上把它作为一个挑战,但我不知道剩下的是什么。你不需要一堆。只需在助手中设置一个变量,计算跳过的
叶的数量,并使用
(制作列表n'叶)
作为尾部。最简单的方法是利用您的想法使用
过滤器
,方法是将使用
过滤器
的结果附加两次,其中一个谓词对每个非叶都是真的,另一个谓词对每个叶都是真的。不是很花哨,但适合小列表。为什么要优化?Sylvester你能用代码写出来吗?我想我跳过的“叶子”的计数数是一个“累加器”,对吗?
(require srfi/1)

(define (leafpile lst)
  (local [(define (leafpile lst acc n) ; I'm still screaming 
        (cond
          ((null? lst) (append-reverse! acc (make-list n 'leaf)))
          ((leaf? (car lst)) (leafpile (cdr lst) acc (add1 n)))
          (else (leafpile (cdr lst) (cons (car lst) acc) n))))]
    (leafpile lst '() 0)))