找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 4109|回复: 32

[转贴]:和尚与馒头问题

[复制链接]
发表于 2005-9-30 11:08:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一个庙,100个和尚,100个馒头,大和尚一人吃3个、中和尚一人吃2个、小和尚3人吃一个,请问大、中、小和尚编制分别多少个?

探讨:用lisp求解、运行的方法和速度。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
 楼主| 发表于 2005-9-30 15:18:22 | 显示全部楼层
程序运行结果:
命令: test
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6673个

财富等级: 富甲天下

发表于 2005-9-30 15:21:10 | 显示全部楼层
20,8,72
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-9-30 15:34:27 | 显示全部楼层
这个是不定方程吧
result = ((0 40 60) (5 32 63) (10 24 66) (15 16 69) (20 8 72) (25 0
75))

[php]
(defun c:test()
(setq x 0 result nil)
(repeat 100
(setq y 0)
(repeat 100
(setq z 0)
(repeat 33
(setq temp (+ x y z))
(setq temp1 (+ (* 3 x) (* 2 y) (* 3 z)))
(if (and (= (+ x y z) 100) (= (+ (* 3 x) (* 2 y) (/ z 3)) 100 ))
(setq result (append result (list (list x y z)))))
(setq z (+ z 3))
)
(setq y (1+ y))
)
(setq x (1+ x))
)
(princ "\n          result = ") (princ result);Erase_DV
(getstring "\nPress Enter to continue...");Erase_DV
)
[/php]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-30 16:35:24 | 显示全部楼层
最初由 snoopychen 发布
[B]这个是不定方程吧
result = ((0 40 60) (5 32 63) (10 24 66) (15 16 69) (20 8 72) (25 0
75))

[php]
(defun c:test()
(setq x 0 result nil)
(repeat 100
(setq y 0)
(repeat 100
(setq z 0)
(repeat... [/B]


这儿用repeat,速度较慢,并且有等待的感觉。
测试结果:
Command: test2
          result = ((0 40 60) (5 32 63) (10 24 66) (15 16 69) (20 8 72) (25 0
75))
用时 : 0 小时0 分2.80 秒

直接用while的方法(测试):
  1. [FONT=courier new]
  2. ;;;一个庙,100个和尚,100个馒头,大和尚一人吃3个、中和尚一人吃2个、小和尚3人吃一个,请问大、中、小和尚分别多少个?
  3. (defun c:test ()
  4.   (setq t1 (rtos(getvar"cdate")2 16))
  5.   (setq x 0)
  6.   (while (<= x 100)
  7.     (setq y 0)
  8.     (while (<= y (- 100 x))
  9.       (setq z 0)
  10.       (while (<= z (- 100 x y))
  11.         (if (and (= (+ (* 3 x) (* 2 y) (/ z 3.0)) 100.0)
  12.                  (= (+ x y z) 100))
  13.             (princ (strcat "\n大和尚=" (rtos x 2 0) " ; " "中和尚=" (rtos y 2 0) " ; " "小和尚=" (rtos z 2 0))))
  14.         (setq z (1+ z)))
  15.       (setq y (1+ y)))
  16.     (setq x (1+ x)))
  17.     (setq   t2 (rtos(getvar"cdate")2 16)
  18.         h  (rtos (- (atof(substr t2 10 2)) (atof(substr t1 10 2))) 2 0)
  19.         m  (rtos (- (atof(substr t2 12 2)) (atof(substr t1 12 2))) 2 0)
  20.         s  (rtos (/(- (atof(substr t2 14 4)) (atof(substr t1 14 4)))100) 2 2)
  21.         )  
  22.   (princ (strcat "\n用时 : " h " 小时" m" 分"s " 秒"))
  23.   (princ)
  24. )
  25. [/FONT]

测试:
Command: test
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分1.31 秒
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-1 06:50:14 | 显示全部楼层
;; 给while再加点条件。还可以快一倍有余哦

  1. (defun c:tt ()
  2.   (setq t1 (rtos(getvar"cdate")2 16))
  3.   (setq x 0 y 0 z 0)
  4.   (while (<= (/ x 3) 100)
  5.     (setq y 0)
  6.     (while (and (<= y (- 100 x))(< (setq b (+ (* 3 x)(* 2 y))) 100))
  7.       (setq z 0)
  8.       (while (<= z (- 100 x y))
  9.         (if (and (= (+ b (/ z 3.0)) 100)
  10.                  (= (+ x y z) 100))
  11.             (princ (strcat "\n大和尚=" (rtos x 2 0) " ; " "中和尚=" (rtos y 2 0) " ; " "小和尚=" (rtos z 2 0))))
  12.         (setq z (1+ z)))
  13.       (setq y (1+ y)))
  14.     (setq x (1+ x)))
  15.     (setq   t2 (rtos(getvar"cdate")2 16)
  16.         h  (rtos (- (atof(substr t2 10 2)) (atof(substr t1 10 2))) 2 0)
  17.         m  (rtos (- (atof(substr t2 12 2)) (atof(substr t1 12 2))) 2 0)
  18.         s  (rtos (/(- (atof(substr t2 14 4)) (atof(substr t1 14 4)))100) 2 2)
  19.         )  
  20.   (princ (strcat "\n用时 : " h " 小时" m" 分"s " 秒"))
  21.   (princ)
  22. )

命令:
命令: test
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分1.59 秒

命令:
命令: tt
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分0.56 秒
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 9842个

财富等级: 富甲天下

发表于 2005-10-1 21:11:52 | 显示全部楼层
[php]
(defun c:yy()
(setq t1 (rtos (getvar "cdate") 2 16))
(SETVAR "CMDECHO" 0)
(setq x 0 y 0 z 0)
(repeat 33
  (repeat 50
   (repeat 33
    (if (= (+ X X X Y Y (/ z 3)) (+ X Y Z) 100) (PROGN
     (PRINC "\n大和尚=") (PRINC X)
     (PRINC ";中和尚=") (PRINC Y)
     (PRINC ";小和尚=") (PRINC Z)
    ))
    (setq z (+ z 3))
   )
   (SETQ Z 0 y (1+ y))
  )
  (SETQ Y 0 x (1+ x))
)
(SETQ T2 (RTOS (GETVAR "CDATE") 2 16)
       H (RTOS (- (ATOF (SUBSTR T2 10 2)) (ATOF(SUBSTR T1 10 2))) 2 0)
       M (RTOS (- (ATOF (SUBSTR T2 12 2)) (ATOF (SUBSTR T1 12 2))) 2 0)
       S (RTOS (/ (- (ATOF (SUBSTR T2 14 4)) (ATOF(SUBSTR T1 14 4))) 100) 2 2))
(PRINC (STRCAT "\n用时:" H " 小时" M " 分" S " 秒"))
(SETVAR "CMDECHO" 1)
(princ)
)
[/php]
大和尚=0;中和尚=40;小和尚=60
大和尚=5;中和尚=32;小和尚=63
大和尚=10;中和尚=24;小和尚=66
大和尚=15;中和尚=16;小和尚=69
大和尚=20;中和尚=8;小和尚=72
大和尚=25;中和尚=0;小和尚=75
用时:0小时 0分 0.26秒
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-1 22:36:10 | 显示全部楼层
呵呵,真能较劲。看来要出绝招了,霍霍。看招!

  1. (defun c:xx (/ t1 x y z b d t2 h m s)
  2.   (setq t1 (rtos(getvar"cdate")2 16))
  3.   (setq x 0)
  4.   (while (<= x 33)
  5.     (setq y 0)
  6.     (while (< (setq b (+ x x x y y)) 100)
  7.       (setq z (- 100 x y))
  8.       (if (and (= 0 (rem z 3))
  9.                (= 100 (+ b (/ z 3))))
  10.           (mapcar 'princ (list "\n大和尚=" x " ; " "中和尚=" y " ; " "小和尚=" z))
  11.       )
  12.       (setq y (1+ y)))
  13.     (setq x (1+ x)))
  14.     (setq   t2 (rtos(getvar"cdate")2 16)
  15.         h  (rtos (- (atof(substr t2 10 2)) (atof(substr t1 10 2))) 2 0)
  16.         m  (rtos (- (atof(substr t2 12 2)) (atof(substr t1 12 2))) 2 0)
  17.         s  (rtos (/(- (atof(substr t2 14 4)) (atof(substr t1 14 4)))100) 2 2)
  18.         )  
  19.   (princ (strcat "\n用时 : " h " 小时" m" 分"s " 秒"))
  20.   (princ)
  21. )

测试结果比较:
命令: yy

大和尚=0;中和尚=40;小和尚=60
大和尚=5;中和尚=32;小和尚=63
大和尚=10;中和尚=24;小和尚=66
大和尚=15;中和尚=16;小和尚=69
大和尚=20;中和尚=8;小和尚=72
大和尚=25;中和尚=0;小和尚=75
用时:0 小时0 分0.37 秒

命令:
命令: xx

大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分0.02 秒
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-10 11:22:23 | 显示全部楼层
高手真多,一题有这么多解答,精彩精彩...
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 9842个

财富等级: 富甲天下

发表于 2005-10-10 14:11:50 | 显示全部楼层
在狂刀长老的基础上再改一下:
[php]
(defun c:xx (/ t1 x y z b d t2 h m s)
(setq t1 (rtos(getvar"cdate")2 16) x 0)
(while (<= x 33)
  (setq y 0)
  (while (< (setq b (+ x x x y y)) 100)
   (setq z (- 100 x y))
   (if (and (= (rem z 3) 0) (= (+ (/ z 3) b) 100))
    (mapcar 'princ (list "\n大和尚=" x " ; 中和尚=" y " ; 小和尚=" z))
   )
   (setq y (1+ y))
  )
  (setq x (1+ x))
)
(setq t2 (rtos(getvar"cdate")2 16)
        h (rtos (- (atof(substr t2 10 2)) (atof(substr t1 10 2))) 2 0)
        m (rtos (- (atof(substr t2 12 2)) (atof(substr t1 12 2))) 2 0)
        s (rtos (/(- (atof(substr t2 14 4)) (atof(substr t1 14 4)))100) 2 2)
)  
(princ (strcat "\n用时 : " h " 小时" m" 分"s " 秒"))
(princ)
)
[/php]
命令: xx

大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分0.01 秒[/COLOR]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-10 17:06:52 | 显示全部楼层
有没有夸张点,我看的眼花瞭乱的.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-10 20:01:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
其实到了0.0x 的份,已经很难界定哪个快了,我用我的代码和zxq的代码,都测试出过0.00的结果,这时候主要看电脑的速度,还有测试的环境(有没有在运行别的程序)
命令:
XX2
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分0.01 秒

命令:
命令:
XX2
大和尚=0 ; 中和尚=40 ; 小和尚=60
大和尚=5 ; 中和尚=32 ; 小和尚=63
大和尚=10 ; 中和尚=24 ; 小和尚=66
大和尚=15 ; 中和尚=16 ; 小和尚=69
大和尚=20 ; 中和尚=8 ; 小和尚=72
大和尚=25 ; 中和尚=0 ; 小和尚=75
用时 : 0 小时0 分0.00 秒
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 488个

财富等级: 日进斗金

发表于 2005-10-11 00:44:38 | 显示全部楼层

  1. (defun c:test( / x y z)
  2. (setq x 0)
  3. (repeat 33   ;大和尚
  4.   (setq y 0)
  5.   (repeat (/(- 100(* 3 x))2);中和尚
  6.     (if(and(setq z(- 100 x x x y y)) ;小和尚的馒头
  7.            (= 100(+ x y(* z 3)))
  8.         )
  9.        (mapcar 'princ(list "\n大中小分别是: " x "; " y "; "(* z 3)))
  10.     )
  11.     (setq y(1+ y))
  12.   )(setq x(1+ x))
  13. )
  14. (princ)  
  15. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 488个

财富等级: 日进斗金

发表于 2005-10-11 01:17:23 | 显示全部楼层
;;开始以为是中和尚放前面快,其实不然.
;;次数很可观呀
;;按4楼可想有多少次!

  1. (defun c:test( / x y z lst)
  2. (setq x 0)
  3. (repeat 33   ;大和尚
  4.   (setq y 0)
  5.   (setq lst(cons (/(- 100(* 3 x))2) lst))
  6.   (repeat (/(- 100(* 3 x))2);中和尚
  7.     (if(and(setq z(- 100 x x x y y)) ;小和尚的馒头
  8.            (= 100(+ x y(* z 3)))
  9.         )
  10.        (mapcar 'princ(list "\n大中小分别是: " x "; " y "; "(* z 3)))
  11.     )
  12.     (setq y(1+ y))
  13.   )(setq x(1+ x))
  14. )
  15. (princ(strcat "\n共计算:"(rtos(apply '*(cons 33.(vl-remove 0 lst)))2 0)))
  16. (princ)  
  17. )
  18. ;;次数6e44

  19. (defun c:test( / x y z lst)
  20. (setq y 0)
  21. (repeat 50   ;中和尚
  22.   (setq x 0)
  23.   (setq lst(cons (/(- 100(* 2 y))3) lst))
  24.   (repeat (/(- 100(* 2 y))3);大和尚
  25.     (if(and(setq z(- 100 x x x y y)) ;小和尚的馒头
  26.            (= 100(+ x y(* z 3)))
  27.         )
  28.        (mapcar 'princ(list "\n大中小分别是: " x "; " y "; "(* z 3)))
  29.     )
  30.     (setq x(1+ x))
  31.   )(setq y(1+ y))
  32. )
  33. (princ(strcat "\n共计算:"(rtos(apply '*(cons 50.(vl-remove 0 lst)))2 0)))
  34. (princ)  
  35. )
  36. ;;次数6e56
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-10-11 14:52:20 | 显示全部楼层
代数方法求,速度又提高n个数量级,呵呵。


[问题的提出]

问题: 一个庙,100个和尚,100个馒头,大和尚一人吃3个、中和尚一人吃2个、小和尚3人吃一个,请问大、中、小和尚编制分别多少个?

探讨:用lisp求解、运行的方法和速度。



前面偶在8楼首先提出用二层循环替代三层循环的办法后,程序运行时间已经从xx秒精简到0.0x秒,原因是什么?循环少了,计算量将大大减少。不是一点点,而是呈n个数量级的减少,这个可以从aeo提出的计算量统计方法得出。那么还有没有更快的办法?我不禁问自己。

于是,新的解决方案在我脑海中蠢蠢欲动,终于忍不住浮出水面,破壳而出。(待续,先去买包烟...)



要大大提高运行效率,仅仅改变对程序函数的选用(如repeat,while,foreach,mapcar等)是不够的,关键在于改变程序的结构,如何使得经过一层循环就能得出我们想要的结果呢?aeo提出了一个问题,程序循环结构中:从中和尚开始循环比从大和尚开始循环要慢,那么,从小和尚开始呢?(请大家思考20秒钟…)

现在,我们已经得出了三个好的问题:

1.       能否一层循环就解决问题?

2.       从小和尚开始循环是否会更快?

3.       已知小和尚的数目,中和尚,大和尚的数目是确定的么?



有人说,提出一个好的问题胜于解决一个难的问题。(如果没有人承认说过,那就算是我说的啦,哈哈,不好意思J)



[解决方案]

经过简单的思考,我得出以下结论:

1.       小和尚必然是3的倍数,而且不可能太少(否则100个馒头不够分的)

2.       小和尚的数目确定了,中和尚大和尚的数目也确定了,由如下两个方程式可求解:

a+b+c=100

3a+2b+c/3=100

(注:a=大和尚数目,b=中和尚数目,c=小和尚数目)

3.       从小和尚循环,可以一层循环就得出结果,循环可以从1开始至100,但是有很多是不可能的,可以通过计算求出小和尚可能的数目范围。通过如下公式:

(1)    a+c=100 ; 3a+c/3=100

(2)    b+c=100 ; 2b+c/3=100

两个公式即求出小和尚可能的数目范围,本题为60~75。又,中、大和尚数目不可能为0且小和尚数目只能以3递增,所以实际范围为:63~72。



[编程解析]

经过以上分析,通过一层循环求解是可能的。程序如下:



  1. ;| 和尚分饼-----by 狂刀 2005.10.11

  2. 问题: 一个庙,100个和尚,100个馒头,大和尚一人吃3个、中和尚一人吃2个、小和尚3人吃一个,请问大、中、小和尚编制分别多少个?

  3. 探讨:用lisp求解、运行的方法和速度。

  4. |;

  5. (defun c:tt (/ n1 n2 a b c i)

  6.   (setq n1 (/(- (* 2 3 100)(* 3 100))(1- (* 2 3)));;=60

  7.        n2 (/(- (* 3 3 100)(* 3 100))(1- (* 3 3)));;=75

  8.        c n1);;求n1,n2可简化,在此按公式代入方便理解。

  9.   (repeat (setq I (1-(/(- n2 n1) 3)));;循环次数减1

  10.     (setq c (+ 3 c);;每次加3,因3个小和尚才分1个饼

  11.           a (-(/(* 5 c)3)100);;根据代数公式得出,推导过程详附录1

  12.          b (- 100 a c);;不用解释了吧?

  13.          )

  14.     (mapcar 'princ (list "\n大和尚: " a "   中和尚: " b "   小和尚: "c  "   共分饼: " (+(* 3 a)(* 2 b)(/ c 3))));;检测是否正确

  15.   )

  16. (princ "\n本次共计算")(princ I )(princ " 个单元")

  17. (princ)

  18. )





;;测试结果:

命令: tt

大和尚: 5   中和尚: 32   小和尚: 63   共分饼: 100

大和尚: 10   中和尚: 24   小和尚: 66   共分饼: 100

大和尚: 15   中和尚: 16   小和尚: 69   共分饼: 100

大和尚: 20   中和尚: 8   小和尚: 72   共分饼: 100

本次共计算 4 个单元



[测试速度]

二层循环已经将速度提高到0.0x数量级,甚至测出0.00的运算时间,一层循环就看不出结果了。将程序运行1000次才能看出结果。

比对测试程序:



  1. (defun c:ttt ()

  2.   (setq *x!-time (getvar "cdate"))

  3.   (repeat 1000 (c:tt))

  4.   (setq    tm  (- (getvar "cdate") *x!-time)

  5.        tm$ (rtos tm 2 8)

  6.   )

  7.   (mapcar '(lambda(x y / a)(princ (strcat  (setq a (substr tm$ x 2)) y)) a) '(3 5 7 9)  '("时" "分" "." "秒"))

  8.   (princ)

  9. )

  10. ;; 用时: 00分03.13秒



以13楼aeo的程序(c:test)为例测试:



  1. (defun c:tests  ()

  2.   (setq *x!-time (getvar "cdate"))

  3.   (repeat 1000 (c:test))

  4.   (setq    tm  (- (getvar "cdate") *x!-time)

  5.        tm$ (rtos tm 2 8)

  6.   )

  7.   (mapcar '(lambda(x y / a)(princ (strcat  (setq a (substr tm$ x 2)) y)) a) '(3 5 7 9)  '("时" "分" "." "秒"))

  8.   (princ)

  9. )

  10. ;; 用时:  00分46.16秒



可见速度从46.16提升至3.13,是原来二层循环结构速度的0.0678 倍。

将(c:tt)和(c:test)程序中过程princ的显示部分屏蔽掉(行首加; ,aeo的要在;前加T),再测试

命令: ttt

00时00分00.03秒

命令: tests

00时00分03.95秒

排除计算机用于显示结果(princ,print)的过程,实际计算过程速度提高为:

命令: cal

>> 表达式: 3/395

0.00759494

即运行效率为原二层循环的0.00759494 倍。



[小结]

1. 初学lisp的朋友,经常注重函数的运用,而忽视了程序结构的设计,是大错特错的。

好的程序结构,可以使得效率大大提高,编程的乐趣也在于此,这就是所谓的“和别人的思路不一样”,思路不一样,程序的结构必然不同。(用不同的语言,lisp,vba,arx的效率也大相迳庭,从慢到快,在此不讨论)

2.批量依次处理一堆数据,常用的autolisp函数有:repeat,while,mapcar,foreach;(应用于vlisp的还有vlax-for,vlax-map-collection,暂不讨论)。其中repeat,while,mapcar,foreach函数本身的效率比对可参考eachy版主的相关帖子。在此特别指出while函数,在循环中有特别的用途,while有一个判断条件(而repeat,mapcar,foreach是无条件循环),当有一个测试数据条件不符合,即刻跳出循环、返回结果,这在处理大的数据、进行判断的时候是非常有用的,效率提高也是显而易见的。而当测试数据都满足while条件的时候,这几个函数效率上也有所的差别,但对比程序结构效率的提升,改变相对是很小的。从前面几个帖子也得出此结论。

3.本论题(不是本帖),建议已经入门的,有一定基础的lisp编程爱好者好好看看,其中各个帖子对函数的应用、程序的结构及解决问题的过程等等对提高编程水平是很有帮助的。



[附录1] 推表达式的过程:

a b c

a=0

;; n1

2*x+y/3=100

x+y=100

;

6x+y=3x+3y

3x=2y

5y=300

y=60

;

2*3*(100 - y)+y=3*100

(2*3*100-3*100)/(2*3-1)=y

;; n2

3*x+y/3=100

x+y=100

;

9x+y=3x+3y

6x=2y

8y=600

y=75

;;已知c,求a b

a+b+c=100

3a+2b+c/3=100

;

3a+2(100-c-a)+c/3=100

a=100-c/3-200+2c

a=(5c/3)-100





注:

1.       本文作者: 狂刀  

2.       相关索引:  

原帖:  http://www.xdcad.net/forum/showt ... 2282653#post2282653

3.       本帖已经发到教学中心:

现提供word文件打包下载

4.  你可以转贴转载,但请保留作者信息及保持文章的完整性。.



时间: 2005.10.11
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-5-7 12:54 , Processed in 0.576082 second(s), 62 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表