SICP学习笔记 2.1.2 抽象屏障

  练习2.2

(define (make-point x y)
  (cons x y))
(define (x-point p)
  (car p))
(define (y-point p)
  (cdr p))
  
(define (make-segment m n)
  (cons m n))
(define (start-segment s)
  (car s))
(define (end-segment s)
  (cdr s))
  
(define (midpoint-segment s)
  (make-point (/ (+ (x-point (start-segment s))
		             (x-point (end-segment s)))
		         2.0)
	            (/ (+ (y-point (start-segment s))
		            (y-point (end-segment s)))
		         2.0)))
		 
1 ]=> (print-point (midpoint-segment 
			      (make-segment 
			         (make-point 1 3) 
				 (make-point 3 5))))

(2,4)
 

   练习2.3

;; 平面矩形的构造函数和选择函数
;; 构造函数, 使用两条线段构造平面矩形
(make-rectangle	segment1 segment2)

;; 返回平面矩形相邻两边中左边的线段 
(left-segment-rectangle rectangle)

;; 返回平面矩形相邻两边中右边的线段
(right-segment-rectangle rectangle)

;; 根据构造函数和选择函数实现计算平面矩形周长的过程
;; 首先实现计算线段长度的过程, 这里借用2.2中的关于线段和点的过程
(define (segment-length segment)
  (point-length (start-segment segment) (end-segment segment)))
(define (point-length start end)
  (sqrt (+ (square (- (x-point start) (x-point end)))
	   			 (square (- (y-point start) (y-point end))))))
	   
;; 然后实现计算平面矩形周长的过程
(define (perimeter-rectangle rectangle)
  (+ (* 2 (segment-length (left-segment-rectangle rectangle)))
     (* 2 (segment-length (right-segment-rectangle rectangle)))))
     
;; 对构造函数和选择函数做两种实现
;; 平面矩形可以由相对(不在同一条直线上)的两个长度相同的平行线段构成, 这里没有对是否平行校验
(define (make-rectangle	segment1 segment2)
  (cons segment1 segment2))
(define (left-segment-rectangle rectangle)
  (car rectangle))
(define (right-segment-rectangle rectangle)
  (make-segment (start-segment (car rectangle))
			  (start-segment (cdr rectangle))))
		
;; 验证
(perimeter-rectangle 
	(make-rectangle 
		(make-segment (make-point 0 0)
				        (make-point 3 0))
		(make-segment (make-point 3 4)
				        (make-point 6 4))))
;Value: 16

;; 平面矩形可以由相交(起点相同且不在同一条直线上)的的两条线段构成, 这里没有对十分在同一条直线校验
(define (make-rectangle	segment1 segment2)
  (cons segment1 segment2))
(define (left-segment-rectangle rectangle)
  (car rectangle))
(define (right-segment-rectangle rectangle)
  (cdr rectangle))
  
;; 验证
(perimeter-rectangle 
	(make-rectangle 
		(make-segment (make-point 0 0)
				        (make-point 3 0))
		(make-segment (make-point 0 0)
				        (make-point 3 4))))
;Value: 16

;; 对于平面矩形的面积
;; 首先实现点到直线距离的过程
;; 点(x0, y0)到直线Ax+By+C=0的距离公式为|Ax0+By0+C|/√A^2+B^2
;; 将直线方程变换为y=kx+b形式,得到距离公式为|kx0-y0+b|/√k^2+1
(define (point-to-segment point segment)
  (let ((fun (get-k-b segment)))
    (/ (abs (+ (* (car fun) (car point))
	       			 (- (cdr point))
	       			 (cdr fun)))
       (sqrt (+ (square (car fun)) 1)))))

;; k = (y1-y2)/(x1-x2)
;; b = y1-x1*k
(define (get-k-b segment)
  (let ((k (/ (- (cdr (start-segment segment))
		    (cdr (end-segment segment)))
	         (- (car (start-segment segment))
	            (car (end-segment segment))))))
    (cons k (- (cdr (start-segment segment))
	        (* k (car (start-segment segment)))))))
			 
;; 由此实现计算平面矩形面积的过程
(define (area-rectangle rectangle)
  (* (segment-length (left-segment-rectangle rectangle))
     (point-to-segment (end-segment (right-segment-rectangle rectangle))
		       			              (left-segment-rectangle rectangle))))

;; 由平行线段构造平面矩形验证计算面积的过程

(define (right-segment-rectangle rectangle)
  (make-segment (start-segment (car rectangle))
			  (start-segment (cdr rectangle))))
(area-rectangle (make-rectangle 
			  (make-segment (make-point 0 0)
					      	  (make-point 3 0))
			  (make-segment (make-point 3 4)
					      	  (make-point 6 4))))
;Value: 12

;; 由相交线段构造平面矩形验证计算面积的过程
(define (right-segment-rectangle rectangle)
  (cdr rectangle))
(area-rectangle (make-rectangle 
			  (make-segment (make-point 0 0)
					      	  (make-point 3 0))
			  (make-segment (make-point 3 0)
					      	  (make-point 6 4))))  
;Value: 12		

;; 这里将平面矩形理解成了平行四边形,-_-!,不过尝试
(area-rectangle (make-rectangle 
			  (make-segment (make-point 0 0)
					      	  (make-point 3 0))
			  (make-segment (make-point 3 0)
					      	  (make-point 3 4))))  
;; 也可以得到正确结果
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值