SICP 第二章的练习

  拖了几天,开做第二章。
  因为过春节,好久没看了,有些题已经是好几天或者十多天之前做的了,所以现在的想法和之前的想法可能不同
  第二章的难度开始慢慢加大,因为涉及到树的遍历、映射,不断的用到递归,与不借助一些数据结构,队列,栈,而是递归构造,延迟计算,相当于构造了一个数据结构。
  例如,做到2.29考虑如何遍历树什么的,分析树的结构,与2.32需要填写一个程序,理解划分子集的过程,与写程序的思路,以及map与列表与递归的一些使用,这些都花了我不少时间,大多都再代码上注释了,也说了一些子集的感悟以及思路,收益颇多,虽然以后不一定能用上…还可能忘掉..233…

#lang planet neil/sicp
(define (even? x)
  (= (remainder x 2) 0))
(define (point x y) (cons x y))
(define (x-point p) (car p))
(define (y-point p) (cdr p))

(define (print-point p)
  (newline)
  (display "(")
  (display (x-point p))
  (display ",")
  (display (y-point p))
  (display ")")
  )

(define (midpoint-segment p1 p2)
  (cons (/ (+ (x-point p1) (x-point p2)) 2)
        (/ (+ (y-point p1) (y-point p2)) 2)))

(define p1 (point 2.0 3))
(define p2 (point 3 7.0))
//(print-point (midpoint-segment p1 p2))
(newline)

(define (t-cons x y)
  (lambda (m) (m x y)))

(define (t-car tmp-cons)
  (tmp-cons (lambda (x y) x)))
(define (t-cdr tmp-cons)
  (tmp-cons (lambda (x y) y)))
(define test-cons (t-cons 3 4))

(define (last-pair l)
  (define (iter l)
    (if (null? (cdr l))
        (car l)
        (iter (cdr l))))
  (iter l))
;(last-pair (list 2 3 5 6))

(define (length l)
    (define (iter l n)
      (if (null? l)
          n
          (iter (cdr l) (inc n))))
    (iter l 0))
//注意append怎么构成的
//scheme的list相当于序对cons构成的,cons val nextCons,这样的格式,末端是nil
//也就是我们构造一个list的时候,最好按着以上格式
//错误输出格式 `(mcons (mcons (mcons 1 3) 5) 7)`
//正确输出格式 `(mcons 2 (mcons 3 (mcons 4 (mcons 5 '()))))`
(define (append src dct)
  (if (null? src)
      dct
      (cons (car src) (append (cdr src) dct))))
//下面的两个reverse
//第一个原先是打算把获取位置的值写出来,然后找一个插一个进去(忘了是list,很蠢)
//第二个直接把第一个插在前面


(define (reverse l)
  (define (pos x l)
    (define (iter n l)
      (if (= x n)
          (car l)
          (iter (inc n) (cdr l))))
    (iter 1 l))
  (define (iter n r)
    (if (= n 0)
        r
        (iter (dec n) (cons (pos n l) r))))
  (iter (length l) nil))

(define (t-reverse l)
  (define (iter r l)
    (if (null? l)
        r
        (iter (cons (car l) r) (cdr l))))
  (iter nil l))
(reverse (list 2 3 4 5))

/* 错误的写法,输出格式是翻转的,不符合列表格式
(define (same-parity x . y)
  (define (iter r n l)
    (cond ((= n 0) r)
          ((= (remainder x 2) (remainder (car l) 2)) (iter (cons r (car l)) (dec n) (cdr l)))
          (else (iter r (dec n) (cdr l)))))
  (iter x (length y) y))
*/
(define (same-parity x . y)
  (define (iter r n l)
    (cond ((= n 0) (cons r nil))
          ((= (remainder x 2) (remainder (car l) 2)) (cons r (iter (car l) (dec n) (cdr l))))
          (else (iter r (dec n) (cdr l)))))
  (iter x (length y) y))  

//(same-parity 1 2 3 5 6 8 7)
//练习2.22的问题就是输出格式问题
(define (square x)
  (* x x))
(define (square-list items)
  (if (null? items)
      nil
      (cons (square (car items)) (square-list (cdr items)))))
(define (t-square-list items)
  (map square items))

(define (for-each func contain)
  (define (iter c)
    (if (null? c)
        nil
        (cons (func (car c)) (iter (cdr c)))))
  (iter contain))

//(for-each square (list 2 3 4 5))

这里写图片描述

//2.27这道题难住我了
//我原先的思路是列表中的列表,也就是树中的子树reverse后再把其余cons组合在一起
//但是感觉我这个需要回溯,需要借助队列
//所以我花了很多时间在这,最后还是忍不住上网搜一下答案(下面的代码就是)
//所以我们写的deep遍历函数,需要做的是:
//1.判断是否为nil,nil的话是一个值,是的话无法使用car cdr去遍历,返回nil
//2.否者,则借助写的append(list1,list2),将list2添加再list1最后一个非nil值后面,也就是(cons last-val,list2)
//3.因为reverse list相当于这样展开,list(2~n)list(1),list(3~n)list(2)list(1)...
//4.所以就可以写作 append (deep-reverse (cdr src)) (deep-reverse (car src))
//5.我们还需要判断 (car src)是否是一个序对,从而来决定是否对(car src)再递归下去。

(define (deep-reverse src)
  (if (null? src)
      nil
      (append (deep-reverse (cdr src))
              (if (pair? (car src))
       s           (list (deep-reverse (car src)))
                  (list (car src))))))
 (define (m-deep-reverse src)
  (define (iter r c)
    (if (null? c)
        r
        (iter (cons (if (pair? (car c))
                        (m-deep-reverse (car c))
                        (car c)) r) (cdr c))))
  (iter nil src))
;(m-deep-reverse (list (list 1 2)))

(define (m-frange src)
  (define (iter r c)
    (if (null? c)
        r
        (iter (if (pair? (car c))
                  (iter r (car c))
                  (append r (list (car c))))
              (cdr c))))
  (iter nil src))
;(m-frange (list (list 1 2) 5 8 (list 3 4)))
(define (frange c)
  (cond ((null? c) nil)
        ((not (pair? c)) (list c))
        (else (append (frange (car c)) (frange (cdr c))))))
;(frange (list (list 1 2) (list 3 4)))

//练习2.29
//这道题花了些时间
//我自己的思路主要卡在如何判断子树平衡,然后递归上去判断一颗树是否平衡
//因为审题不够认真,除了头节点 (left right),后面都是通过make-branch来产生分支
//然后每一个分支是(lenght structure),structure可能是一个分支,可能是权重
//所以在遍历一个节点的时候,我觉得应该分头节点,和分支来遍历

(define (make-node left right)
  (list left right))

(define (make-branch length structure)
  (list length structure))

(define (left-branch node)
  (car node))
(define (right-branch node)
  (car (cdr node)))
(define (branch-length node)
  (car node))
(define (branch-structure node)
  (car (cdr node)))
//权重函数
//先判断tree是否是一个pair,然后再去判断分支的structure是否是一个pair或者说是子树
//当然,这个函数写得有问题,若(left,right)中right为空,那么这个函数会返回0
//按理说遇到这样情况,我们应该遍历left的
//所以可以添加一个函数,判断传入的树的头节点,是否有right分支,没有则传入(left-branch)
//由于懒得改了,所以这个函数是判断该树有左右孩子的情况
//可以计算出该树的重量
(define (g-total-weight node)
  (if (pair? node)
      (if (pair? (branch-structure node))         
           (+ (g-total-weight (left-branch node))
             (g-total-weight (right-branch node)))
          (branch-structure node))
      0))
//x1为一棵符合题意得平衡树,用来修改参数测试编写得函数是否正确
(define x1 (make-node
            (make-branch 2
                         (make-node
                            (make-branch 2 1)
                            (make-branch 1
                                         (make-node (make-branch 1 1) (make-branch 2 1)))))
                            (make-branch 2 3)))

//测试树x2
(define x2 (make-node (make-branch 2 5) (make-branch 2 5))) 
;(total-weight x)
;(branch-structure (left-branch x))
//计算分支的值 = 权重 X 长度
(define (branch-power node)
  (* (branch-length node) (g-total-weight node)))

//树的左右分支是否平衡函数
(define (node-blance? node)
   (if (pair? (branch-structure node))
       (= (branch-power (left-branch (branch-structure node)))
          (branch-power (right-branch (branch-structure node))))
       true))
//blance?函数是中的iter函数是判断子树是否平衡
//结合node-blance?,and子树与树的两大分支是否平衡来得出结果
//structure不是pair的,默认返回true

(define (blance? node)
  (define (iter child)
    (if (pair? (branch-structure child))
        (and (iter (left-branch (branch-structure child)))
             (iter (right-branch (branch-structure child)))
             (node-blance? child))
        true))
  (and (= (branch-power (right-branch node)) (branch-power (left-branch node))
       (iter (right-branch node)) (iter (left-branch node))))

;(node-blance? x1)
;(node-blance? (left-branch x1))
;(node-blance? (left-branch (branch-structure (left-branch x1))))

;(blance? x1)

(define (h-square-tree tree)
  (map (lambda (t)
         (if (pair? t)
              (h-square-tree t)
              (* t t)))
       tree))

;(h-square-tree x1)

(define (l-square-tree tree)
  (cond ((null? tree) nil)
        ((not (pair? tree)) (* tree tree))
        (else (cons (l-square-tree (car tree)) (l-square-tree (cdr tree))))))

;(l-square-tree x1)
(define (tree-map func tree)
  (map (lambda (t)
         (if (pair? t)
             (cx-square-tree t)
             (func t)))
       tree))
(define (cx-square-tree tree)
  (tree-map square tree))
;(cx-square-tree x1)
//这个我不会,百度了一份
//但是我们要知道map是处理列表的,并不能处理列表中包含的列表
//可以分析,第一次调用subset s的时候,rest也会调用 subset cdr s
//则rest值最后为nil,因为map返回的是列表,所以append rest (map...)没毛病
//由于subset (cdr s)把递归向后展开
//所以最后rest=nil 返回到上一层的s为(3,nil),然后返回的rest为 (nil , (3,nil))
//然后利用map函数,对每个元素处理,递归上去的时候s为(2,3,nil)
//把元素2与rest (nil ,(3, nil))的所有元素组合,再添加进rest,就得到了新的子集。
//也就是结果是((2) (2 3)),append到rest里去,以此类推,到s为(1 2 3)的时候
//我们此时的rest是( nil (3) (2) (2 3)),然后对每个元素与1 cons,然后再添加进rest,就是所有的子集
//一个集合的所有子集等于:
//f(n)代表所有子集
//递归式子大概如下。。不知道怎么形容了
//f(0)=nil
//f(n)=f(n-1)+f(n-1)中的每个集合append List[n]

(define (subset s)
  (if (null? s)
      (list nil)
      (let ((rest (subset (cdr s))))
        (append rest (map (lambda (x) (cons (car s) x)) rest)))))
(subset (list 1 2 3))

猜你喜欢

转载自blog.csdn.net/qq_21049875/article/details/79329534