三分 的个人资料3fen's Notebook照片日志列表更多 工具 帮助

日志


3月28日

2.76 答案

;2.76
;2008/3/28
;经常加入新类型的系统,消息传递比较好。因为加入一个新类型时只需给新类型定义已有的操作,而不用更改已定义好的类型和操作。不过有个小不足(注释114 只能有一个操作数)。

;经常加入新操作的系统,如果采用消息传递的话需要给以前写好的每一个类型都加入一个操作判断语句。而数据导向方式的话,虽然也要对每个原有类型都put一个新操作,不过由于修改比较形式化,较好一点。

;这里我有个疑问,就像数据导向方式是显示分派方式的优化,数据导向是不是也同样是消息传递的优化?感觉消息传递与显示分派区别只在一个是类型一个是操作。

2.75 答案

;2.75
;2008/3/28
(define (make-from-mag-ang mag ang)
  (define (dispatch op)
    (cond ((eq? op 'real-part) (* mag (cos ang)))
          ((eq? op 'imag-part) (* mag (sin ang)))
          ((eq? op 'magnitude) mag)
          ((eq? op 'angle) ang)
          (else "UNKNOWN op")))
  dispatch)
(define (apply-generic op arg) (arg op))

2.74 答案

待续,需要想一个题目中说的总部--子公司的结构

2.73 答案

a) 由于number? same-variable?两者没有operator
b)j
(put  'deriv  '+  (lambda(exp var) (make-sum (deriv (addend exp) var)
                                          (deriv (augend exp) var))))
(put  'deriv  '*  (lambda(exp var) (make-sum (make-product (deriv (multiplier exp) var)
                                                        (multiplicand exp))
                                          (make-product (multiplier exp)
                                                        (deriv (multiplicand exp) var)))))
;addend/augend之类的过程没写到table里面
c)  (put 'deriv  '** (lambda(exp var) (make-product (make-product (exponent exp)
                                                             (make-exp (base exp) (make-sum (exponent exp)
                                                                                            -1)))
                                                 (deriv (base exp) var))))
d) 把put里面的'deriv和'+交换即可

3月27日

2.72.5 put get

2.73以后的习题要用到put和get过程,而这些既不是基本过程,而且自己还不会实现。所以找了下别人的源码,粘贴过来。
;;----------------------------------------------------------

(define (make-table)
  (let ((local-table (list '*table*)))
    (define (lookup key-1 key-2)
      (let ((subtable (assoc key-1 (cdr local-table))))
        (if subtable
            (let ((record (assoc key-2 (cdr subtable))))
              (if record
                  (cdr record)
                  false))
            false)))
    (define (insert! key-1 key-2 value)
      (let ((subtable (assoc key-1 (cdr local-table))))
        (if subtable
            (let ((record (assoc key-2 (cdr subtable))))
              (if record
                  (set-cdr! record value)
                  (set-cdr! subtable
                            (cons (cons key-2 value)
                                  (cdr subtable)))))
            (set-cdr! local-table
                      (cons (list key-1
                                  (cons key-2 value))
                            (cdr local-table)))))
      'ok)   
    (define (dispatch m)
      (cond ((eq? m 'lookup-proc) lookup)
            ((eq? m 'insert-proc!) insert!)
            (else (error "Unknown operation -- TABLE" m))))
    dispatch))

(define operation-table (make-table))
(define get (operation-table 'lookup-proc))
(define put (operation-table 'insert-proc!))
(define false #f)
(define true #t)
;;----------------------------------------------------------

题外话 读sicp的用处

每本书讲的都是一个“抽象层(不是很深的概念,望文生义即可)”内的东西,比如介绍windows日常使用的,是操作系统提供的界面这一层;C语言,是从脑中的对一个问题的解决方案到C这种高级语言这层;编译,从高级语言到汇编语言;汇编,从汇编语言到机器指令;机器指令下面还有微指令,而它们物理上又真的是由一个个电子元件组成的0、1的基本电路组成。而正如sicp中所说,这些电子元件又被几个物理公式所描述,而这些公式又可以用计算机来模拟.....
扯远了有点,想表达的一个意思就是这些时候“打破砂锅纹到底”是不现实的,干好本职工作即可,不要拿不是一个层的东西来指责这本书。

sicp的内容处在哪一层呢?我认为,这本书讲的东西处于问题和解决方案之间,就是说它告诉你怎样解决一个扑面而来的问题。为了表示解决方案的思路,作者用了Scheme这种函数式语言。这东西确实比C要省心的多,可以比较自然的表达自己的思路,而不用因为考虑什么内存、指针而作人肉编译器。
书中开始的例子都很简单且有趣,因为简单,我想很多人会自然的用些老办法来解决问题——比如C中的for、while之类的循环语句,而不是书中的思路。这使我想到当时小学学刚开始学方程的时候,我对列方程不屑一顾,觉得本来一个算式就出结果的问题,却偏要写一段“设XX为x”的话然后列方程解方程,麻烦的很。当然我们后来都用了方程解题,因为后来的应用题以我脑内的空间不够直接写出一个能算结果的算式。

我估计即使学完这东西,老师问你Java、.net方面开发的知识,仍然迷茫依旧,甚至像我某时想的那样“废人还是废人,此书太虚”。不过如果恰好某天有位教离散的或者教算法的老师一脸玄妙的问了某些问题时,你可以用SICP里吸收到的东西同样玄妙或者——更牛一点——平易近人的回答他时,我估计你就会有冲动去抱住那两位可爱的作者,去说谢谢。“代码城堡”、”计算王国“——在水木上看到的两个词。估计干这行的早晚都有或高或矮的自己的代码城堡,而SICP——我认为——是帮助建造计算王国的。

刚看了不到两章,胡言乱语,不敢发到ocaml上,先留在自己这吧。


3月25日

能做研究生了

这段时间的找导师、机试、面试搞得焦头烂额。今天晚上六点半晕晕忽忽的穿过人群看到通知表格里我的名字和我报的导师的名字连在同一行,我就不晕乎了。然后大声对电话那边的老妈叫道“录了!”。
可能是由于通知比规定的晚了四十多分钟,看到通知后竟然没之前想的那么激动。相比之下更符合电视剧剧情的是上午面完以后,竟然哭了。明白了Niga当时小组得了斗剧冠军以后脸抽成那样子,跟自己的主观没多大关系,就像上马哲课犯困一样自然。感谢老爹老妈,感谢宿舍哥们,感谢大使,感谢国辉同学,感谢计院的老师们,当然还有SICP。


3月15日

2.72 答案

;2.72
;2008/3/15
;由于我在2.68中写的encode是先检查左树,所以最频繁的符号所需步数就是(memq item left)的步数+1,O(n)
;最不频繁的搜索次数:(n-1)+(n-2)+....1=n*(n-1)/2, 步数O(n^2)

2.71 答案

;2.71
;2008/3/15
;形状很简单  大概是:(((((a) b) c) d) e)    abcde分别是1 2 4 8 16
;最频繁的需要1bit,最不频繁的需要n bit

2.70 答案

;scheme匹配时是区分大小写的,我用的都是小写,不知有没有让其忽视大小写的解决方案
(define rock-pairs '((a 2) (boom 1) (na 16) (sha 3) (get 2) (yip 9) (job 2) (wah 1)))
(define rock-tree (generate-huffman-tree rock-pairs))
(define rock-lrc '(get a job
                       sha na na na na na na na na
                       get a job
                       sha na na na na na na na na
                       wah yip yip yip yip yip yip yip yip yip
                       sha boom))
(define rock-bits (encode rock-lrc rock-tree))
;> (length rock-bits)
;84
;> (length rock-lrc)
;36
;所以如果用定长编码,需要3个bit  那么36个单词 至少需要108位

2.69 答案

;2.69
;2008/3/15
(define (generate-huffman-tree pairs)
  (successive-merge (make-leaf-set pairs)))
(define (successive-merge queue)
  (cond ((null? queue) '())
        ((null? (cdr queue))
         (car queue))
        (else (successive-merge (adjoin-set (make-code-tree
                                            (car queue)
                                            (cadr queue))
                                           (cddr queue))))))
;由于adjoin-set已经排好的顺序,只要把前两项合并就好
;这里adjoin-set有了通用效果,可以插入leaf也可以插入code-tree,因为symbols和weight

;花絮:写这题时候s-m的cond少写了个else,结果找bug找了半天..

2.68 答案

;2.68
;2008/3/15
(define (encode message tree)
  (if (null? message)
      '()
      (append (encode-symbol (car message) tree)
              (encode (cdr message) tree))))
(define (encode-symbol item tree)
  (if (leaf? tree)
      '()
      (cond ((memq item (symbols (left-branch tree)))
             (cons 0
                   (encode-symbol item
                                  (left-branch tree))))
            ((memq item (symbols (right-branch tree)))
             (cons 1
                   (encode-symbol item
                                  (right-branch tree))))
            (else 'Error))))

2.67 答案

;2.67
;2008/3/15
;---------------result--------------
;> (decode sample-message sample-tree)
;(a d a b b c a)
;---------------------------------

2.66 答案

;2.66
;2008/3/13
;lookup-tree
(define (lookup given-key tree)
  (cond ((null? tree) #f)
        ((= given-key (key (entry tree)))
         (entry tree))
        ((< given-key (key (entry tree)))
         (lookup given-key (left-branch tree)))
        ((> given-key (key (entry tree)))
         (lookup given-key (right-branch tree)))))

2.65 答案

;2.65
;2008/3/13
;intersection-set大体相同
(define (union-tree tree1 tree2)
  (list->tree (union-set (tree->list tree1) (tree->list tree2))))

2.64 答案

;2.64
;2008/3/13
;list--->tree  平衡树
;把elements分成三部分:前((n-1)/2)作为left-tree,后一个作为this-entry,其余的作为right-tree,再分别调用partial-tree转换为平衡树。
;f(n)~2*(f(n/2))  推测步数增长是O(n)
3月10日

2.63 答案

;结果一样...至少对2-16这三棵树是一样的
;暂时没看出这两个算法的步数有什么差别   正确性待验证
;-------------test_example-----------
(define t1 '(7 (3 (1 () ()) (5 () ())) (9 () (11 () ()))))
(define t2 '(3 (1 () ()) (7 (5 () ()) (9 () (11 () ())))))
(define t3 '(5 (3 (1 () ()) ()) (9 (7 () ()) (11 () ()))))

;result:
;> (tree->list-1 t1)
;(1 3 5 7 9 11)
;> (tree->list-2 t1)
;(1 3 5 7 9 11)
;> (tree->list-1 t2)
;(1 3 5 7 9 11)
;> (tree->list-2 t2)
;(1 3 5 7 9 11)
;> (tree->list-1 t3)
;(1 3 5 7 9 11)
;> (tree->list-2 t3)
;(1 3 5 7 9 11)

2.62 答案

;2.62
;顺序集合的并集union-set
(define (union-set set1 set2)
  (let ((x1 (if (null? set1)
                '()
                (car set1)))
        (x2 (if (null? set2)
                '()
                (car set2))))
    (cond ((null? set1) set2)
          ((null? set2) set1)
          ((= x1 x2) (cons x1
                           (union-set (cdr set1)
                                      (cdr set2))))
          ((> x1 x2) (cons x2
                           (union-set set1
                                      (cdr set2))))
          (else (cons x1
                      (union-set (cdr set1)
                                 set2))))))

2.61 答案

;2.61
;顺序集合的adjoin-set

(define (adjoin-set x set)
  (cond ((null? set) (list x))
        ((= x (car set)) set)
        ((< x (car set)) (cons x set))
        ((> x (car set)) (cons (car set)
                               (adjoin-set x (cdr set))))))

2.60 答案

;2.60
;可重复乱序集合
(define (element-of-set? x set)
  (cond ((null? set) #f)
        ((equal? x (car set)) #t)
        (else (element-of-set? x (cdr set)))))
(define (adjoin-set x set)
  (cons x set))
(define (union-set set1 set2)
  (append set1 set2))
(define (intersection-set set1 set2)
  (cond ((or (null? set1) (null? set2))
         '())
        ((element-of-set? (car set1) set2)
         (cons (car set1)
               (intersection-set (cdr set1) set2)))
        (else (intersection-set (cdr set1) set2))))
;肯定很多场合用到这种表示...不过一时想不到有什么代表性的。
;比如要统计两组人的兴趣爱好种类,统计时肯定一个个人依次录入,其中不免有重复的,然后比较两组人兴趣的种类时候就要用到集合的概念了。