这书也算是必修吧,尤其是我这种非科班人员,还是应该抽时间尽量学习一下。大致翻过一遍,习题非常多,尽力吧。
##构造过程抽象
* 为了表述认知,每种语言都提供了三种机制:基本元素;组合方式;抽象方法。
* 前缀表示法,haskell中有学过,scheme中基本都是前缀表达,这使得表达式的可读性略微降低。
* 声明变量:`(#define name value)`,和C中的宏声明一致,声明函数:`(#define (func ( para1,para2...) ())`;
* 一般性求职规则是**树形累积**,其他的被称为**特殊形式**(如`define`语句)。
* Scheme中多项式求值遵从**代换模型**,即逐步将过程调用代换为对应的过程和变量。先展开后规约的成为**正则序求值**,否则被称为**应用序求值**。在Scala中,分别对应*Call By Name* 和 *Call By Value*。和Scala一样,Lisp也是默认遵从后者。
* 条件表达式:`cond`关键字,对应现代语言中的`switch`,`if`关键字,只能在非此即彼的情况下使用(换言之,没有`else if`)。
* 逻辑运算符:`and`, `or` 和 `not`.
###练习部分:
1.3:
```lisp
(define (sumMax2 x y z)
(if (= x (larger x y))
(+ x (larger y z))
(+ y (larger x z))))
(define (larger a b)
(if (> a b) a b)) (sumMax2 1 2 3)
``` 1.5 由于第二个参数是一个endless loop,如果对其做value展开,就会死掉,换句话说:如果死机就是应用序,否则是正则序。 * 牛顿迭代法求平方根
```lisp
(define (sqrt x)
(define (isGoodEnough guess)
(< (abs (- (* guess guess) x)) 0.001))
(define (improve guess)
(average guess (/ x guess)))
(define (sqrtIter guess)
(if (isGoodEnough guess)
guess
(improve guess)))
(sqrtIter 1.0)) (define (average x y)
(/ (+ x y) 2.0)) (define (abs x)
((if (> x 0) + -) x))
```
1.6 由于lisp是应用序优先的,因此
```lisp
new-if ( good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)
``` 的计算过程是先计算 `(good-enough? guess x)`,而下一步是计算`(sqrt-iter (improve guess x))`,换句话说,递归被无条件执行了,因此程序会陷入死循环。 * 过程的形式参数被称为“约束变量”,与之对应的成为“自由变量”,所谓**约束**,过程约束了形式参数。如果像上文一样把一些过程定义在某个过程内部,这个过程的形参就在所有的过程中共享,不必再次声明,这被称为“词法作用域”。有点类似类内部的私有函数。
* 尾递归与普通递归的区别:简单来说,尾递归可以被优化成迭代,对于lisp这种没有循环语句的语言,掌握尾递归是一项必备技能。非尾递归可能造成堆栈溢出,尾递归无此后患(现代C/C++的编译器也会自动优化尾递归)。 1.9 `a+b`展开为:` ++(--a+b)`,`+`运算需要再次展开,直到a=0,因此是递归计算过程;而后者展开为`(--a)+(++b)`,不需要伸展长度,因此是尾递归|迭代。 1.10 (A 1 10)=A(0 (A 1 9))=A(0 (A 0 A(1 8)))..A(...A(1 1))=$2^{10}$ (A 2 4)=A(1 (A 2 3))=A(1 (A 1 A(2 2)))...A(...A(2 1))=$2^{16}$ (A 3 3)=A(2 A(3 2))=A(2 A(2 A(3 1)))...=$2^{16}$ 根据上面的展开规律: (f n)=2n; (g n)=$2^n$ (h n)=$2^{2^n}=4^n$ * 树形展开,即递归的展开是一棵树,这个是比较常见的情况。书中举了著名的坑爹例子”斐波那契“,这个例子是有名的不适合使用递归计算的递归式。
$$f(n)=\begin{equation}
\begin{cases}
0, &n = 0\\
1, &n=1\\
f(n-1)+f(n-2), &n > 1\\
\end{cases}
\end{equation}
$$
[$\LaTeX$公式的命令都快不记得了,去查了半天ORZ] 如果想要转为迭代,用常规命令语言的思路:
```c
if(n==0)return 0;
if(n==1)return 1;
int pre=0;
int result=1;
int temp;
while(--n>0)
{
temp=result;
result=result+pre;
pre=temp;
}
return result;
```
显然,需要两个中间变量,循环结束的条件是次数。使用尾递归实现,因为不需要中间变量交换数据,所以所需变量少一个。 ```lisp
(define (f n)
(f-iter 0 1 n) (define (f-iter pre result count)
(if (= count 0)
b
(f-iter result (+pre result) (- count 1)))
)
```
你看,其实并不难,只要你会写循环…当然,尾递归要简洁很多。如果能够跳出命令式思维,直接想到尾递归写法,这函数式编程才能算入了门(好难= =)。 * 换零钱的例子。其实这是一个组合算法,总的组合次数=一定用了某个部件的次数+一定没用某个部件的次数。按着这个规律进行规约,最终退化到边界情况,问题解决。使用这种典型的分治式思维,写出的代码非常简洁。著名的快速排序也是一句话:快排的结果应该是把比某元素小的快排结果放在其前面,把比该元素大的结果放在后面,这个haskell只要两行,常被用来做广告,哈哈。 ```haskell
qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
``` Lisp版:
```lisp
define (quicksort x)
(cond
((null? x) ‘())
(else (append
(quicksort (filter (lambda (y) (< y (car x))) (cdr x)))
(list (car x))
(quicksort (filter (lambda (y) (>= y (car x))) (cdr x)))))))
```
注:这个是从网上找的,我的lisp水平和这篇笔记的进度一致。 1.11
$$ f(n)=\begin{equation}
\begin{cases}
n,&n<3\\
f(n-1)+f(n-2)+f(n-3),&n \ge 3\\
\end{cases}
\end{equation}
$$ ```lisp
(define (f n)
(if (<= n 3)
n
(f-iter 1 2 3 n))) (define (f-iter ppre pre result count)
(if (<= count 3)
result
(f-iter pre
result
(+ (* 3 ppre) (* 2 pre) result)
(- count 1))))
```
1.12 帕斯卡三角形,把它当成一个下三角,从二维的角度来讲:
$$f(x,y)=\begin{equation}
\begin{cases}
1,& y=1 \text{ or } x=y\\
f(x-1,y-1)+f(x-1,y),&x>y \text{ and } y!=1\\
\end{cases}
\end{equation}
$$ ```lisp
(define (f x y)
(cond ((< x y) null)
((= y 1) 1)
((= x y) 1)
(else (+ (f (- x 1) (- y 1))
(f (- x 1) y)))))
```
1.13 纯数学题,这里就略过吧ORZ,我印象中上学的时候似乎证明过。 下面一部分是讲复杂度的,CLRS这里讲的很明白,略过。 * 求幂的题目。这题在面试题中倒是很常见,一个技巧
$$a^n=a^{n/2}*a^{n/2}$$
所以如果n是偶数,需要$\log{n}$次,是奇数就是$\log{n}+1$次。对应的代码段: ```lisp
(define (exp a n)
(define (even? n)
(= (remainder n 2) 0))
(cond (= (n 0) 1)
((even? n) (square (exp (/ n 2))))
(else (* a (exp a n-1)))))
```
显然,这里递归运算,下面描述对应的迭代,主要利用了公式:
$(a^{n/2})^2=(a^2)^{n/2}$,反向分解的思路:
$5^7=5^3*5^3*5=5^2*5*5^2*5*5$,显然,n是偶数,除以2,递归;n是奇数,减1,递归 ```lisp
(define (exp a n)
(define (square a) (* a a))
(define (even? n)
(= (remainder n 2) 0))
(define (exp-iter a n result)
(cond ((= n 0) result)
((even? n) (exp-iter (square a) (/ n 2) result))
(else (exp-iter a (- n 1) (* a result)))))
(exp-iter a n 1))
``` 1.17 好吧,这种题很适合做面试题,定义了乘法,倍乘和减半,实际上把上面的代码中相关的代换掉就可以了。其中`even?`需要用一些技巧,不过也不困难。 先到这里,这本书读的很慢…习题太多,每周抽一天时间学习吧。

SCIP读书笔记(1)的更多相关文章

  1. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  2. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  3. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  4. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  5. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  6. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

  7. LOMA280保险原理读书笔记

    LOMA是国际金融保险管理学院(Life Office Management Association)的英文简称.国际金融保险管理学院是一个保险和金融服务机构的国际组织,它的创建目的是为了促进信息交流 ...

  8. 《3D Math Primer for Graphics and Game Development》读书笔记2

    <3D Math Primer for Graphics and Game Development>读书笔记2 上一篇得到了"矩阵等价于变换后的基向量"这一结论. 本篇 ...

  9. 《3D Math Primer for Graphics and Game Development》读书笔记1

    <3D Math Primer for Graphics and Game Development>读书笔记1 本文是<3D Math Primer for Graphics and ...

随机推荐

  1. Migrating from IntelliJ Projects

    We might provide an automatic migration option in Android Studio in the future.   For now, to migrat ...

  2. MySQL 5.6 root密码丢失

     windows下mysql密码忘记了 第一步:netstat -nat(可以查看mysql是否启动了,如果启动了,可以用输入net stop mysql(或者通过任务管理器结束进程)) 第二步:my ...

  3. Java序列化与Hessian序列化的区别

    Java序列化: Java序列化会把要序列化的对象类的元数据和业务数据全部序列化为字节流,而且是把整个继承关系上的东西全部序列化了.它序列化出来的字节流是对那个对象结构到内容的完全描述,包含所有的信息 ...

  4. nyist 740 “炫舞家“ST(动态规划)

    dp[i][j][k]:表示第i次踩踏后两脚的位置j,k 先固定一只脚的位置j,第i次踩踏后,状态为dp[i][j][a[i]]或者dp[i][a[i]][j],其中a[i]表示第i个输入的元素,则有 ...

  5. 一起啃PRML - 1.2.3 Bayesian probabilities 贝叶斯概率

    一起啃PRML - 1.2.3 Bayesian probabilities 贝叶斯概率 @copyright 转载请注明出处 http://www.cnblogs.com/chxer/ 这一节简单讲 ...

  6. ADO.NET 增删查改小总结

    转自:http://www.cnblogs.com/ashu123/archive/2010/10/10/ado_1.html 三套路-----增删改 1 using System.Data.SqlC ...

  7. 在Code First中使用Migrations对实体类和数据库做出变更

    在Code First中使用Migrations对实体类和数据库做出变更,Mirgration包含一系列命令. 工具--库程序包管理器--程序包管理器控制台 运行命令:Enable-Migration ...

  8. visual studio 资源视图 空白 解决方案

    visual studio 资源视图打开后显示空白的解决方案步骤: 在解决方案view下,右键点击工程 1 unload projects 完成第一步后仍然在解决方案view下,右键点击工程 2 re ...

  9. PHP 获取时间的各种处理方式!

    今天写下php中,如何通过各种方法 获取当前系统时间.时间戳,并备注各种格式的含义,可灵活变通.1.获取当前时间方法date()很简单,这就是获取时间的方法,格式为:date($format, $ti ...

  10. python爬虫学习(1)__抓取煎蛋图片

    #coding=utf-8 #python_demo 爬取煎蛋妹子图在本地文件夹 import requests import threading import time import os from ...