P17 (*) Split a list into two parts; the length of the first part is given.

问题描述

Do not use any predefined predicates(functions).

sash> (split '(a b c d e f g h i k) 3)
sash> ((a b c) (d e f g h i k))

题目要求“自己动手,丰衣足食“。

解法

  • 尾递归实现
    (define split
      (lambda (ls n)
        (let f ([i 1]
                [ls1 '()]
                [ls2 ls])
          (cond
            [(> i n) (list (reverse ls1) ls2)]
            [else (f (+ i 1) (cons (car ls2) ls1) (cdr ls2))]))))

    上面用到了reverse,貌似不满足题目要求。

  • 普通递归实现

    将上面ls1的累积过程改成普通递归形式。在一次遍历实现,需要借助复杂的控制才能实现。如果两次遍历,第一次遍历得到前n个元素的列表,第二次得到其余元素的列表,两次结果cons得到最终结果。

    目前没想到满意的方案,暂为空
  • CPS实现

    ls1累积前n个元素,ls2累积其余的元素。

    (define split-2
      (lambda (ls n k)
        (let f ([i 1]
                [s ls]
                [k k])
          (cond
           [(null? s) (k '() '())]
           [(<= i n) (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k (cons (car s) ls1) ls2)))]
           [else (f (+ i 1) (cdr s) (lambda (ls1 ls2) (k ls1 (cons (car s) ls2))))]))))
    (define return
      (lambda (ls1 ls2)
        (list ls1 ls2)))
    
    (define split
      (lambda (ls n)
        (split-2 ls n return)))

    CPS方式特别适合在函数中收集多个中间结果的情况,这里收集了ls1ls2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值