免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-21 00:31 |只看该作者 |倒序浏览
Sieve of Eratosthenes 算法描述见 http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

Haskell 实现如下:

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

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


加了平方优化后的版本

  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..]
复制代码


实际上,第二个版本有严重的性能问题(break 会导致大量的内存操作)以至于还没有第一个快。

真正优化的版本(by win_hate):

  1. isPrime :: Integer -> [Integer] -> Bool
  2. isPrime p (x:xs)
  3.     | x*x > p           = True
  4.     | p `mod` x == 0    = False
  5.     | otherwise         = isPrime p xs

  6. primes = 2 : [ p | p <- [3,5..], isPrime p primes ]
复制代码


BTW,这个还可以再稍加优化。

[ 本帖最后由 MMMIX 于 2009-5-20 14:15 编辑 ]

论坛徽章:
0
2 [报告]
发表于 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

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
3 [报告]
发表于 2008-09-21 01:59 |只看该作者

回复 #2 win_hate 的帖子

我觉着 integers 的定义可以优化下
PLT Scheme 实现(需要在 DrScheme 中将语言设为 Module)

  1. #lang lazy

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

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


  1. > (list-ref primes 50)
  2. 233
复制代码

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

论坛徽章:
0
4 [报告]
发表于 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
5 [报告]
发表于 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 编辑 ]

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
6 [报告]
发表于 2008-09-21 10:50 |只看该作者
原帖由 win_hate 于 2008-9-21 10:17 发表
那个 #lang lazy 在 mzscheme 中好用吗?我这里试了不行。

mzscheme 不清楚(应该也行),我向来都是直接用 DrScheme 的
在 DrScheme 中应该把语言设为 Module,然后通过 #lang 选择具体要用的语言,这也是推荐的作法。

论坛徽章:
0
7 [报告]
发表于 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))
复制代码

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
8 [报告]
发表于 2008-09-21 16:21 |只看该作者
原帖由 win_hate 于 2008-9-21 11:21 发表
谢谢!


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


其实用 #lang 也是可以的,不过直接用 (list-ref primes 50) 是没有输出的,但是可以用 (display (list-ref primes 50)) 显示结果。

论坛徽章:
0
9 [报告]
发表于 2008-09-21 17:44 |只看该作者
我不是很明白你的意思。

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



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



可能我模块那里没写对?

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

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
10 [报告]
发表于 2008-09-21 18:28 |只看该作者
原帖由 win_hate 于 2008-9-21 17:44 发表


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


估计是版本的问题,我看你用的还是 3.72, 我测试时用的是 4.1

collects/lazy/lang/reader.ss 这个文件在我这是有的,内容很简单:

  1. (module reader syntax/module-reader
  2.   lazy)
复制代码

[ 本帖最后由 MMMIX 于 2008-9-21 18:31 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP