明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 16512|回复: 37

lisp应用递归算法10题

    [复制链接]
发表于 2010-8-29 11:57 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2010-8-30 22:57:39 编辑

以下题目您只能应用lisp基础表项操作函数:比如car cdr cons list , if cond , + - =等,不能使用length apply mapcar repeat while 等批量操作和循环函数,应用递归算法写出余下部分代码。
题目1:编写等同于nth功能的递归函数
  1. (defun my-nth (n lst)
  2. ;;写出您的解决代码
  3. )
题目2:编写一个等同于length功能的递归函数
  1. (defun my-length(lst)
  2. ;;写出您的解决代码
  3. )
题目3:编写一个等同于append的递归函数
  1. (defun my-append (p q)
  2. ;;写出您的解决代码
  3. )
题目4:编写一个remove-nth递归函数,即删除nth对应表项返回新表
  1. (defun remove-nth (n lst)
  2. ;;写出您的解决代码
  3. )
题目5:编写一个递归函数找到第1个大于0的元素
  1. ;;;(setq lst (list -5 -4 -3 -2 -1 0 1 2 3 4 5))
  2. (defun first-pos (lst)
  3.   ;;写出您的解决代码
  4. )
题目6:编写一个函数等同于reverse功能的递归函数,这里您可以使用先前编写过的my-append函数
  1. (defun my-reverse(lst)
  2. ;;写出您的解决代码
  3. )
题目7:编写一个递归函数,功能:列出表中元素所有组合,返回组合表需按原表先后顺序
如(1 2 3)->((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) nil)
  1. (defun powerset (lst)
  2. ;;写出您的解决代码
  3. )
题目7a:编写一个递归函数,功能同题目7,但返回结果可以是无序的,要求算法用时要比原来减少半
  1. (defun faster-powerset(lst)
  2. ;;写出您的解决代码
  3. )
题目8:编写一个递归函数,判断给出数n是否为素数
  1. (defun is-prime(n)
  2. ;;写出您的解决代码
  3. )
题目9:编写一个递归函数,用新元素new替换表lst中第i项元素,这里i = 0 1 2 3 ...
  1. (defun ch-lst (new i lst)
  2. ;;写出您的解决代码
  3. )
题目10:编写一个递归函数,找出表中通过测试函数test的第1组点对;如(1 2 3 4 5 6 7 1) test为=返回(1 . 1)
  1. (defun find-matching-pair(test lst)
  2. ;;写出您的解决代码
  3. )


评分

参与人数 1威望 +1 明经币 +2 金钱 +20 贡献 +5 激情 +5 收起 理由
mccad + 1 + 2 + 20 + 5 + 5 【精华】表扬一下 好题目

查看全部评分

本帖被以下淘专辑推荐:

  • · 实用|主题: 9, 订阅: 1
发表于 2022-12-2 19:37 | 显示全部楼层
本帖最后由 qjchen 于 2022-12-2 19:51 编辑
hnfsf 发表于 2014-5-4 22:54
出个题目:
数表由很多根pl线的顶点坐标组成的
一条pl线每段的两个坐标一个元素,第1段和第2段有关系,第 ...

对于单根PL线的,可以如此

(setq a (list (list 1 2) (list 2 3) (list 3 4) (list 4 5)))

(mapcar '(lambda (x y) (list x y)) (reverse (cdr (reverse a))) (cdr a))

不过估计我可能不太看得懂题意
发表于 2022-11-17 20:05 | 显示全部楼层
强大的递归
 楼主| 发表于 2010-8-29 11:59 | 显示全部楼层
因为没有逻辑算法专题,就贴在几何算法这里了
发表于 2010-8-29 20:09 | 显示全部楼层
  1. (defun my-nth (n lst / tt k)
  2.   (setq k -1)
  3.   (defun tt (ll)
  4.     (setq k (1+ k))
  5.     (if (= k n)
  6.       (car ll)
  7.       (progn
  8. (setq ll (cdr ll))
  9. (tt ll)
  10.       ) ;_ progn
  11.     ) ;_ if
  12.   ) ;_ defun
  13.   (tt lst)
  14. )
发表于 2010-8-29 20:18 | 显示全部楼层
  1. (defun my-length (lst / k tt)
  2.   (setq k 0)
  3.   (defun tt(ll)
  4.     (if ll
  5.       (progn
  6. (setq k (1+ k)
  7.        ll (cdr ll)
  8.        )
  9. (tt ll)
  10. )
  11.       k)
  12.    
  13.     )
  14.     (tt lst)
  15.   )
 楼主| 发表于 2010-8-29 20:34 | 显示全部楼层
Gu_xl兄,这里不允许使用局部变量,所以不能有k,您可以直接定义局部函数,但不能添加局部变量
发表于 2010-8-30 09:54 | 显示全部楼层
本帖最后由 作者 于 2010-8-30 10:37:49 编辑

chlh_jd发表于2010-8-29 20:34:00Gu_xl兄,这里不允许使用局部变量,所以不能有k,您可以直接定义局部函数,但不能添加局部变量
呵呵,能不能把要求一下全部说清楚呀,比如说repeat命令可不可以用啊?
先发一个改好的!
  1. (defun my-length (lst /  tt)
  2.   (defun tt (ll)
  3.     (if ll
  4.       (progn
  5. (setq ll (cdr ll))
  6. (1+ (tt ll))
  7.       ) ;_ progn
  8.       0
  9.     ) ;_ if
  10.   ) ;_ defun
  11.   (tt lst)
  12. )
l使用了repeat,算法不是递归算法了!
  1. (defun my-nth (n lst / tt k)
  2.     (repeat n
  3.       
  4.     (setq lst (cdr lst))
  5.       )
  6.   (car lst)
  7. )
发表于 2010-8-30 17:57 | 显示全部楼层

[原创] 个人的第一个F# JIG代码——截断线绘制

本帖最后由 作者 于 2010-8-31 16:54:43 编辑

:) 挺有趣的题目

刚出差回来,先上几个,占个位置,慢慢来完成,写的挺不精简的,也没有什么容错,应付某些特殊情况亦会出错,等下次再来缩写

(1) my-nth
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;by qjchen@gmail.com
  3. (defun my-nth (n lst)
  4. (cond
  5.        ((< n 0) nil)
  6.        ((= n 0) (car lst))
  7.        (T (setq lst (cdr lst) n (1- n) ) (my-nth n lst))
  8. )
  9. )
  10. (setq lst '(1 2 3))
  11. (my-nth 2 lst)

(2) my-length
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;by qjchen@gmail.com
  3. (defun my-length(lst)
  4. (cond
  5.        ((= (car lst) nil) 0)
  6.        (T (setq lst (cdr lst)) (1+ (my-length lst)))
  7. )
  8. )
  9. (setq lst '(1 2 3))
  10. (my-length lst)

(3) my-append
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;by qjchen@gmail.com
  3. (defun my-append (p q)
  4.   (cond
  5.        ((= (car p) nil) q)
  6.        (T (setq q (cons (last p) q) p (reverse (cdr (reverse p))) ) (my-append p q))
  7. )
  8. )
  9. (setq lst '(1 2 3) lst1 '(3 4 5))
  10. (my-append lst lst1)
  11. ;;;;或者是如下更简单形式
  12. (defun my-append(p q)
  13. (if p (cons (car p) (my-append1 (cdr p) q))
  14.      q
  15. )
  16. )

(4) remove-nth
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;by qjchen@gmail.com
  3. (defun remove-nth(n lst)
  4. (cond
  5.     ((= n 0) (cdr lst))
  6.     ((> n 0) (cons (car lst) (remove-nth (setq n (1- n)) (setq lst (cdr lst)))))
  7. )
  8. )
  9. (setq lst '(1 2 3 4 5))
  10. (remove-nth 4 lst)

(5)编写一个递归函数找到第1个大于0的元素
  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;by qjchen@gmail.com
  3. (defun first-pos (lst)
  4.   (cond
  5.     ((> (car lst) 0) (car lst))
  6.     (T (first-pos (setq lst (cdr lst))))
  7. )
  8. )
  9. (setq lst (list -5 -4 -3 -2 -1 0 1 2 3 4 5))
  10. (first-pos lst)

(6)题目6:编写一个函数等同于reverse功能的递归函数,这里您可以使用先前编写过的my-append函数

  1. ;;;;题目6:编写一个函数等同于reverse功能的递归函数,这里您可以使用先前编写过的my-append函数
  2. (defun my-append1(p q)
  3. (if p (cons (car p) (my-append1 (cdr p) q))
  4.      q
  5. )
  6. )
  7. (defun my-reverse(lst)
  8. (if lst (my-append1 (my-reverse (cdr lst)) (list (car lst))))
  9. )
  10. (setq lst (list -5 -4 -3 -2 -1 0 1 2 3 4 5))
  11. (my-reverse lst)


(9) ;;;;;题目9:编写一个递归函数,用新元素new替换表lst中第i项元素,这里i = 0 1 2 3 ...
  1. ;;;;;题目9:编写一个递归函数,用新元素new替换表lst中第i项元素,这里i = 0 1 2 3 ...
  2. (defun ch-lst (new i lst)
  3. (cond
  4.     ((= i 0) (cons new (cdr lst)))
  5.     ((> i 0) (cons (car lst) (ch-lst new (1- i) (cdr lst))))
  6.     (T lst)
  7. )
  8. )
  9. (setq lst '(1 2 3 4 5))
  10. (ch-lst 8 2 lst)


以下几道题是后作的,主要是排列组合花了较多时间,还是没有写的很好,如何顺利输出一个漂亮的列表,大概只靠递归还有点麻烦,加一个排序函数会好些,其中都是加入了一些子函数,如用递归定义了mapcar(说明,并不能完全和lisp的mapcar相同,因为autolisp里面的mapcar可以多个参数,而我定义的mymapcar是不行的,这一点也是我一直比较疑惑的地方,在纯lisp里面,带不定参数的函数,其参量可以用. 来隔开,这个在许多新兴语言,如actionscript里面都可以看到,但autolisp还不行)。

而需要说明的是素数测试,这里面的递归主要体现在find-2,由于用递归法算素数其实很不好,这里也就将就用+1法的递归,勉勉强强来完成了。

以前对递归一直没有很仔细的学习,总是有点依赖心理,这次仔细做了一遍,还是很有收获的,谢谢楼主的题目

其实还有许许多多的lisp递归题目,有空我也放几个上来 :)


(7) 排列组合:此题我的写法还比较土了些,导致结果没有什么规律,但结果应该是全的,速度方面暂时不是很清楚
题目7a:编写一个递归函数,功能同题目7,但返回结果可以是无序的,要求算法用时要比原来减少半
  1. ;;;题目7a:编写一个递归函数,功能同题目7,但返回结果可以是无序的,要求算法用时要比原来减少半
  2. ;;; by qjchen@gmail.com
  3. (defun powerset (lst)
  4.   (defun mymapcar(fun lst)
  5.      (cond ((not (null lst)) (cons ((eval fun) (car lst)) (mymapcar fun (cdr lst))))
  6.            (T nil)
  7.      )
  8.   )
  9.   (defun com2(a lst)
  10.     (append lst (com1 a lst))
  11.   )
  12.   (defun com1(c lst)
  13.    (defun mycons(b)
  14.     (if (listp b) (if b (cons c b) c) (list c b))
  15.    )
  16.    (mymapcar 'mycons lst)
  17.   )
  18.   (cond
  19.        ((and (car lst) (not (cdr lst))) (list (car lst) nil))
  20.        (T
  21.        (com2 (car lst) (powerset (cdr lst))))
  22.   )
  23. )
  24. (powerset '(1 2 3 4 5))

(10) 题目10:编写一个递归函数,找出表中通过测试函数test的第1组点对;如(1 2 3 4 5 6 7 1) test为=返回(1 . 1)
  1. ;;;;题目10:编写一个递归函数,找出表中通过测试函数test的第1组点对;如(1 2 3 4 5 6 7 1) test为=返回(1 . 1)
  2. ;;;; by qjchen@gmail.com
  3. (defun find-matching-pair(lst)
  4.   (cond ((find-1 (car lst) (cdr lst)) (find-1 (car lst) (cdr lst)))
  5.        ((null lst) nil)
  6.        (T (find-matching-pair (cdr lst)))
  7.   )
  8. )
  9. (defun find-1(a lst)
  10. (cond ((test a (car lst)) (cons a (car lst)))
  11.        ((null lst) nil)
  12.        (T (find-1 a (cdr lst)))
  13. )
  14. )
  15. (defun test(a b)
  16.   (= a b)
  17. )
  18. (find-matching-pair (list 2 3 4 5 1 6 5))


(8) ;;;;题目8:编写一个递归函数,判断给出数n是否为素数
  1. ;;;;题目8:编写一个递归函数,判断给出数n是否为素数
  2. ;;;by qjchen@gmail.com
  3. (defun is-prime(n)
  4. (defun smalldivisor (n)
  5.   (find-2 n 2))
  6. (defun find-2 (n i)
  7.   (cond ((> (* i i) n) n)
  8.         ((= (rem n i) 0) i)
  9.         (T (find-2 n (1+ i)))
  10.   )
  11. )
  12. (cond ((and (= (type n) 'INT) (> n 1)) (= (smalldivisor n) n))
  13.        (T nil))
  14. )

评分

参与人数 2威望 +1 明经币 +2 金钱 +60 贡献 +30 激情 +30 收起 理由
chlh_jd + 1 + 30
highflybir + 1 + 1 + 30 + 30 + 30 【好评】好程序

查看全部评分

 楼主| 发表于 2010-8-30 22:45 | 显示全部楼层

QJ-CHEN老师,除了第7、7a、8、10道给出了全部答案了,强悍!

GU_xl兄,这里要求是用递归函数,递归就意味着过程需要调用自身函数。

发表于 2010-8-31 16:58 | 显示全部楼层

[原创] 个人的第一个F# JIG代码——截断线绘制

:)

 

勉勉强强都做完了,许多函数可以优化的,等慢慢来改进。

 

排列组合的题目比较有趣,值得深究。谢谢楼主

 

欢迎多出题目,Highflybird兄是算法高手,对于递归,分治等等有深入研究

 楼主| 发表于 2010-8-31 21:54 | 显示全部楼层
因为递归在LISP中实质就是car 与cdr的组合,不使用递归采用while并定义一些局部变量效率相差不多,多次测试结果说明递归在lisp效率一般;比如下面这2个函数:
功能:判断表中元素是否均相同;运行10万次递归函数时间仅略少0.02s左右
(1)使用while
  1. ;;;判断表中子项是否均相同
  2. ;;;by GSLS(SS)
  3. (defun apply-eq (lst / i a mid)
  4.     (setq i 0
  5.    a (if (cadr lst) T nil)
  6.     )
  7.     (while (and a (setq mid (nth (1+ i) lst)))
  8.       (if (equal mid (nth i lst))
  9. nil
  10. (setq a nil)
  11.       )
  12.       (setq i (1+ i))
  13.     )
  14.     a
  15.   )
(2)使用递归
  1. ;;;by GSLS(SS)
  2. (defun apply-eq (lst)
  3.   (if (null lst)
  4.     (*error* "No list")
  5.     (cond ((null (caddr lst)) (equal (car lst) (cadr lst)))
  6.    ((equal (car lst) (cadr lst))
  7.     (apply-eq (cdr lst))
  8.    )
  9.    (t nil)
  10.     )
  11.   )
  12. )
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-20 12:32 , Processed in 5.967122 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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