免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 15127 | 回复: 12
打印 上一主题 下一主题

Sieve of Eratosthenes 的 Haskell/Scheme 实现 [复制链接]

论坛徽章:
0
1 [报告]
发表于 2008-09-21 01:20 |显示全部楼层
lazy scheme


  1. (define (integers n)
  2.   (cons n (integers (+ n 1))))

  3. (define (sieve seq)
  4.   (let ((p (car seq)))
  5.   (cons p (sieve
  6.            (filter (lambda (x) (not (= 0 (modulo x p)))) (cdr seq))))))
  7.            
  8. (define primes (sieve (integers 2)))
复制代码

> (list-ref primes 50)
233

论坛徽章:
0
2 [报告]
发表于 2008-09-21 10:15 |显示全部楼层
一个带平方优化的版本


  1. (define odd
  2.   (letrec ((f (lambda (n)
  3.              (cons n (f (+ n 2))))))
  4.     (f 3)))

  5. (define primes
  6.   (cons 2 (filter primes? odd)))

  7. (define (primes? n)
  8.   (define (f ps)
  9.     (let ((p (car ps)))
  10.       (cond ((> (* p p) n) #t)
  11.             ((= (modulo n p) 0) #f)
  12.             (else (f (cdr ps))))))
  13.   (f primes))
复制代码

论坛徽章:
0
3 [报告]
发表于 2008-09-21 10:17 |显示全部楼层
原帖由 MMMIX 于 2008-9-21 01:59 发表
我觉着 integers 的定义可以优化下
PLT Scheme 实现

#lang lazy

(define (integers n)
  (cons n (integers (+ n 2))))

(define (sieve seq)
  (let ((p (car seq)))
  (cons p (sieve
         ...


说得对,用奇数列相当于在选材上先 filter 了一次。

那个 #lang lazy 在 mzscheme 中好用吗?我这里试了不行。

[ 本帖最后由 win_hate 于 2008-9-21 10:34 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2008-09-21 11:21 |显示全部楼层
谢谢!


用模块之后可以了,但对整个体系还是很模糊。要找个时间把 PLT 的文档好好看一看才行。


  1. (module nth (lib "lazy.ss" "lazy")
  2.   
  3.   (define odd
  4.     (letrec ((f (lambda (n)
  5.                   (cons n (f (+ n 2))))))
  6.       (f 3)))
  7.   
  8.   (define primes
  9.     (cons 2 (filter primes? odd)))
  10.   
  11.   (define (primes? n)
  12.     (define (f ps)
  13.       (let ((p (car ps)))
  14.         (cond ((> (* p p) n) #t)
  15.               ((= (modulo n p) 0) #f)
  16.               (else (f (cdr ps))))))
  17.     (f primes))
  18.   
  19.   (define (nth-prime n)
  20.     (! (list-ref primes n)))
  21.   
  22.   (provide nth-prime))
复制代码

论坛徽章:
0
5 [报告]
发表于 2008-09-21 17:44 |显示全部楼层
我不是很明白你的意思。

如果直接选 lazy scheme,是可以运行的。我回的第一贴用的就是这个环境



如果把语言选为 module,则得到一条错误。



可能我模块那里没写对?

[ 本帖最后由 win_hate 于 2008-9-21 17:49 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-09-21 19:10 |显示全部楼层
我下个官方的 svn 版本捣鼓一下。你用的是那个版本吗?

就我现在这个版本,只要在代码的开头加入


  1. (require (lib "lazy.ss" "lazy"))
复制代码


则 mzscheme 就变成 lazy 的了。

[ 本帖最后由 win_hate 于 2008-9-21 19:15 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-09-21 19:26 |显示全部楼层
没有我可用的版本(XUbuntu),x86_64 那个是红帽的,估计不好用。

论坛徽章:
0
8 [报告]
发表于 2008-09-21 22:17 |显示全部楼层
svn check out 的版本(11826),4.1.0.3

现在用 lang 可以用了,谢谢!

[ 本帖最后由 win_hate 于 2008-9-21 22:25 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-09-24 16:10 |显示全部楼层
n 比较小的时候用这种方法可能没什么好处。但用大一点的 n,比如 1000, 在我这里测,差别很大。你看看我的截图:

s1.png (44.89 KB, 下载次数: 86)

s1.png

s2.png (42.41 KB, 下载次数: 80)

s2.png

论坛徽章:
0
10 [报告]
发表于 2008-09-24 16:20 |显示全部楼层
学习 Haskell,你的第一个代码我能看明白,第二个就看不懂了。帮我解释一下吧


  1. sieve :: [Integer] -> [Integer]
  2. sieve (x:xs) = x : sieve (xs' ++ xs''')            
  3.              where
  4.                 (xs', xs'') = break (>= x*x) xs      
  5.                 xs''' = filter (\y -> y `mod` x /= 0) xs''

  6. primes = 2 : sieve [3,5..]
复制代码


  • xs'++xs''',中的 ++ 是什么意思?
  • (xs', xs'') = break (>= x*x) xs,这里是给 xs' 和 xs'' 绑定值吗?如果是,分别绑定了什么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP