您的算法失败的更简单情况:(f '((1 2) 3)) 应该导致 '((1 2 3)),但您的会导致错误。
我们将首先定义一些术语:
“元素”是常规元素,如1 或'a。
-
“普通列表”只是没有嵌套列表的“元素”列表。
例如,'(1 2 3) 是一个普通列表。 '((1 2) 3) 不是一个简单的列表。
“简单列表”是:
-
empty 列表
- 一个“元素”和下一个“普通列表”的
cons
-
“跳跃对列表”是偶数长度的列表,其中奇数索引有一个“普通列表”,偶数索引有一个元素。例如,'((1) 2 (a) 4) 是“跳跃对列表”。 “跳跃对列表”是:
-
empty 列表
-
cons 的
- 一个“简单的列表”
- 一个“元素”和下一个“跳跃对列表”的
cons
我们已经完成了术语。在编写函数之前,让我们从一些例子开始:
(f '()) equivalent to (f empty)
should output '()
equivalent to empty
(f '((1 2) 3)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
empty)))
should output '((1 2 3))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
empty)
(f '((1 2) 3 (4) a)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
(cons (cons 4 empty)
(cons 'a
empty)))))
should output '((1 2 3) (4 a))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
(cons (cons 4 (cons 'a empty))
empty))
所以,f 是一个函数,它使用“跳跃对列表”并返回“普通列表”列表。
现在我们将编写函数f:
(define (f lst)
???)
注意lst的类型是“跳对列表”,所以我们直接对其进行案例分析:
(define (f lst)
(cond
[(empty? lst) ???] ;; the empty list case
[else ??? ;; the cons case has
(first lst) ;; the "plain list",
(first (rest lst)) ;; the "element", and
(rest (rest lst)) ;; the next "list of jumping pairs"
???])) ;; that are available for us to use
从例子:
(f '()) equivalent to (f empty)
should output '()
equivalent to empty
我们知道空的情况应该返回一个空列表,所以让我们相应地填补这个漏洞:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ??? ;; the cons case has
(first lst) ;; the "plain list",
(first (rest lst)) ;; the "element", and
(rest (rest lst)) ;; the next "list of jumping pairs"
???])) ;; that are available for us to use
从例子:
(f '((1 2) 3)) equivalent to (f (cons (cons 1 (cons 2 empty))
(cons 3
empty)))
should output '((1 2 3))
equivalent to (cons (cons 1 (cons 2 (cons 3 empty)))
empty)
我们知道我们肯定要把“元素”放到“普通列表”的后面,得到我们想要的结果“普通列表”:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case has:
???
;; the resulting "plain list" that we want
(append (first lst) (cons (first (rest lst)) empty))
;; the next "list of jumping pairs"
(rest (rest lst))
;; that are available for us to use
???]))
我们还需要处理下一个“跳跃对列表”,但我们已经有办法处理它:f!
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case has:
???
;; the resulting "plain list" that we want
(append (first lst) (cons (first (rest lst)) empty))
;; the list of "plain list"
(f (rest (rest lst)))
;; that are available for us to use
???]))
然后我们可以返回答案:
(define (f lst)
(cond
[(empty? lst) empty] ;; the empty list case
[else ;; the cons case returns
;; the resulting list of "plain list" that we want
(cons (append (first lst) (cons (first (rest lst)) empty))
(f (rest (rest lst))))]))