Clojure:避免埃拉托斯特尼筛中的堆栈溢出?

2024-04-17

这是我在 Clojure 中实现的埃拉托斯特尼筛法(基于 SICP 流课程):

(defn nats-from [n]
  (iterate inc n))

(defn divide? [p q]
  (zero? (rem q p)))

(defn sieve [stream]
  (lazy-seq (cons (first stream)
            (sieve (remove #(divide? (first stream) %) 
               (rest stream))))))

(def primes (sieve (nats-from 2)))

现在,当我取前 100 个素数时,一切都OK了:

(take 100 primes)

但是,如果我尝试采取前 1000 个素数,程序因堆栈溢出而中断。 我想知道是否有可能以某种方式改变函数筛以成为尾递归,并且仍然保留算法的“流”?

有什么帮助吗???


首先,这不是埃拉托斯特尼筛......有关详细信息,请参阅我的评论。

其次,对势均力敌的投票表示歉意,因为你的问题并不是我指出的问题的实际重复......我的错。

对正在发生的事情的解释

当然,区别在于您正在尝试构建一个增加的筛子,其中的范围remove调用工作是无限的,因此不可能只包装一个doall周围。解决方案是实施我最近经常链接到的论文中的“真正的”增量 SoE 之一——Melissa E. O'Neill 的论文真正的埃拉托色尼筛子 http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf.

Christophe Grand 编写了这种类型的特别漂亮的 Clojure sieve 实现,并且可以使用here http://clj-me.cgrand.net/2009/07/30/everybody-loves-the-sieve-of-eratosthenes/为了引起所有可能感兴趣的人的钦佩。强烈推荐阅读。

至于问题的根源,我最初认为你的问题是重复的,其中包含对你有用的解释:参见here https://stackoverflow.com/questions/2980587/clojure-tail-recursive-sieve-of-eratosthenes and here https://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow。再次对仓促结束的投票表示歉意。

为什么尾递归没有帮助

由于问题特别提到将筛选函数尾递归作为可能的解决方案,我想我应该在这里解决这个问题:一般来说,转换惰性序列的函数不应该是尾递归的.

这是需要牢记的非常重要的一点,也是许多没有经验的 Clojure(或 Haskell)程序员会犯的错误。原因是尾递归函数只有在“准备好”时(在计算的最后)才返回其值。 (迭代过程可以在任何特定迭代结束时返回一个值或继续进行下一次迭代。)相比之下,生成惰性序列的函数应该立即返回一个惰性序列对象,该对象封装了一些代码位可以在需要时要求生成序列的头部或尾部。

因此,堆叠惰性转换问题的答案不是使任何内容成为尾递归,而是合并转换。在这种特殊情况下,可以通过使用自定义方案来融合基于优先级队列或映射的过滤操作来获得最佳性能(请参阅上述文章 http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf了解详情)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clojure:避免埃拉托斯特尼筛中的堆栈溢出? 的相关文章

  • 方案中的尾递归幂函数

    我在方案中编写尾递归幂函数时遇到问题 我想使用辅助函数来编写该函数 我知道我需要一个参数来保存累计值 但在那之后我就陷入了困境 我的代码如下 define pow tr a b define pow tr h result if b 0 r
  • 枚举和 Clojure

    在Java C世界中 人们经常使用枚举 如果我使用的是使用枚举的 Java 库 我可以在它们和关键字之间进行转换 例如 使用 java lang Enum valueOf e aget Ljava lang Enum e getEnumCo
  • 在 Python 中快速确定小于 10 亿的数字是否为素数

    我目前在 python 中检查数字素数的算法对于 1000 万到 10 亿之间的数字来说速度很慢 我希望它能够得到改进 因为我知道我永远不会得到超过 10 亿的数字 背景是我无法获得足够快的实现来解决项目 Euler 的问题 60 我在 7
  • 使用 forge(或其他 JavaScript 方法)生成随机大素数

    我需要在 JavaScript 中生成一个随机大 大约 4096 位 素数 并且我已经在使用 forge Forge 必须有某种生成器来完成此类任务 因为它实现了 RSA 而 RSA 也依赖于随机素数 然而 当你只想获得一个随机素数 类似于
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t
  • Clojure 宏expand

    Why does macroexpand arm getHand getFinger 扩展到 arm getHand getFinger while macroexpand gt arm getHand getFinger 扩展到 getF
  • Clojure:无法找到静态字段

    给出以下代码 map Integer parseInt 1 2 3 4 为什么除非我换行 否则会出现以下异常Integer parseInt在匿名函数中并手动调用它 Integer parseInt clojure lang Compile
  • 如何编写 Clojure 宏来从字符串创建正则表达式?

    我正在创建一个方便的宏 部分便利在于可以仅使用字符串来指定正则表达式 而不是使用 re 表示法 我无法弄清楚的一部分是如何让宏获取字符串并将其重写为 Clojure 正则表达式 例如 生成 re 符号 我认为这是一个语法 转义问题 我的第一
  • 卷积函数可以写成尾递归形式吗?

    我有一个函数 我想以尾递归形式编写 该函数计算求和的方法数k通过滚动s双面模具n次 我已经在上面看到了这个函数的数学解这个答案 https math stackexchange com questions 397689 why convol
  • 改进迭代文本解析的 clojure lazy-seq 使用

    我正在编写一个 Clojure 实现这次编码挑战 http biostar stackexchange com questions 1759 code golf mean length of fasta sequences 尝试找出 Fas
  • 确保 Clojure 中只有一个服务实例正在运行/启动/停止的规范方法?

    我正在用 Neo4j 支持的 Clojure 编写一个有状态服务器 它可以服务套接字请求 例如 HTTP 当然 这意味着我需要能够从该服务器内启动和停止套接字服务器 在设计方面 我希望能够在此服务器中声明一个 服务 并启动和停止它 我在 C
  • 设置、让、宏、坚果

    我正在尝试从 html 内容构建一个快速目录 为了简短起见 代码非常简单 defn toc content doseq i take 5 iterate inc 1 let h str h i println content h where
  • 埃拉托色尼筛法 - 实现返回一些非质数值?

    我用 Java 实现了埃拉托斯特尼筛法 通过伪代码 public static void sieveofEratosthenes int n boolean numArray numArray new boolean n for int i
  • 在编译时生成素数

    我对如何在编译时生成素数数组感兴趣 我相信唯一的方法是使用元编程 在 C 中 不确定这在其他语言中如何工作 快速说明 我不想只是说int primes x 2 3 5 7 11 因为我想在竞争性编程中使用这种方法 其中源文件不能大于10KB
  • 如何在 Jetty 中以编程方式设置 gzip?

    我正在使用 Noir 和 clojure 编写一个网络应用程序 它使用 Jetty Jetty 有两种使用 gzip 的方法 一种用于静态 一种用于动态 它们在https stackoverflow com a 9113129 104021
  • Python,质数检查器[重复]

    这个问题在这里已经有答案了 你好 我正在创建一个函数来检查一个数字是否是素数 但它告诉我 9 是一个素数 def eprimo num if num lt 2 return False if num 2 return True else f
  • 如何安装 leiningen 插件?

    如何安装 leiningen 插件 例如 leiningen run 我看到这个叫做 clojars org 的东西 以及如何 推 它 但我没有看到任何关于从中 拉 的东西 如果 Clojars 上有可用的插件 例如 lein run 只需
  • 我如何在环中模拟 json post 请求?

    我正在使用橄榄石 https github com xeqi peridot https github com xeqi peridot测试我的环应用程序 它工作正常 直到我尝试使用 json 数据模拟 post 请求 require ch
  • 如何使用clojure中的map函数打印哈希映射列表的每个元素?

    我正在构建一个哈希映射列表 然后将其传递给另一个函数 当我尝试使用打印列表中的每个哈希映射时map它不工作 我可以打印完整列表或获取第一个元素等 defn m a println a map println a 以下仅适用于 repl m
  • 与doseq(或for)并行遍历集合的有效方法?

    doseq e coll1 myfunc e 如果您只关心副作用 那么速度非常快 如果我想要怎么办myfunc 并行 地从多个集合中获取元素 即 applymyfunc到每个集合的第一个元素 然后到所有第二个元素 然后到所有第三个元素 依此

随机推荐

  • 自定义WinForms按钮不改变图像?

    我创建了一个自定义按钮 名为 AcceptButton 继承自 System Windows Forms Button 在构造函数上 我设置了一些属性 但最重要的是一个图像 绿色复选标记 如下所示 this Image Proyecto C
  • 如何使用 Razor 将部分视图视图模型项目保存在主视图视图模型中?

    这可能是一个棘手的问题 但就这样吧 假设我有一个主视图 我们称之为MainView cshtml Now MainView cshtml有一个专用的 ViewModel 称为MainViewModel cs它保存一个变量Model Exam
  • Corba 事件客户端 ETIMEDOUT

    我使用omniOrb 和Python 构建了一个CORBA 事件服务客户端 我在使用 Java 客户端时遇到了同样的问题 我非常确定我遇到了与这篇文章相同的事情 因为我的 strace 看起来非常相似 但他没有确切解释他是如何修复它的 Ja
  • 对于 Buffer 等运算符来说,打开和关闭边界的含义是什么?

    我不明白需要打开或关闭边界的 Buffer 运算符的重载 我指的重载是 public static IObservable
  • 如何使用 python 和 Opencv 计算图像中的点数?

    I want to count number of dots in an image The image looks like 我参考了这个 SOF 链接计算图像中的彩色点 https stackoverflow com questions
  • 即使使用stream_set_blocking,PHP SSH2流内容仍为空?

    我正在开发一个工具 它使用 PECL SSH2 扩展通过 SSH2 从远程主机读取 iptables 配置 我能够成功连接到主机 进行身份验证并执行命令 我遇到的问题是有时该流不包含任何数据 Load the current firewal
  • TwoSum 算法:如何改进?

    我想做一个算法并发现这个问题leetcode http www leetcode com 给定一个整数数组 找到两个数字 使它们加起来等于特定的目标数字 函数twoSum 应返回两个数字的索引 以便它们相加达到目标 其中index1 必须小
  • Jython,仅使用 Java 中的 Python 方法?

    阅读和使用时本文 http www rexx com dkuhlman jython course 03 html example the jython classes它假设我们有一个完整的对象定义 包含类和从 python 到 java
  • 查找日期的两个周期之间重叠的天数

    我有两个表 每个表都保存日期期间 从 date1 到 date2 我将在表1和表2中查找两个日期期间之间的重叠天数 Example table1 id FromDate ToDate 1 2000 01 01 2000 02 04 2 20
  • 映射减少计数示例

    我的问题是关于mapreduce programming in java 假设我有 WordCount java 示例 一个标准mapreduce program 我希望map函数收集一些信息 并返回形成如下的reduce函数map
  • 如何从单独的文件下载用于 cmake 中交叉编译的工具链?

    我有一个项目 根目录中有一个 CMakeLists txt 文件 该项目在 Linux 和 OSX 上编译得很好 现在我想为 MIPS OpenWRT 交叉编译它 我想尽可能地自动化它 所以我将使用以下代码来下载工具链并设置编译器变量 Ex
  • 停止并重新启动计时器

    我想停止这个计时器 然后从停止的地方重新启动它 secondsTimer Timer scheduledTimer timeInterval 1 0 target self selector selector addSeconds user
  • 覆盖 FILE_LOG_PATTERN (如果可能的话每个环境)

    我想覆盖 Spring Boot 的默认文件和控制台日志模式以包含一些自定义 MDC 字段 有没有一种简单的方法可以使用application properties yaml 如果没有的话 这将是一个很好的功能 否则我可能不得不复制 Boo
  • 比较当前文件版本和上一个远程存储库

    如何区分我的工作文件版本与远程存储库中的某些先前版本 假设我今天拉取 对本地副本执行 6 8 次提交 然后想要查看我的最新工作版本 给定文件 与远程或任何其他版本上的最新版本之间的差异 要查看 最新工作版本 我将其作为您的工作副本 之间的差
  • 使用 sharekit 在 Facebook 上添加图像和描述

    我正在使用 sharekit 在 Facebook 上分享文本 我想在文本附近添加一张图片 如下图所示 知道如何做到这一点吗 还有其他合适的库 例如 sharekit 吗 谢谢 将 og image 元标记添加到 head html 块中
  • 如何获取使用 AngularDart 的路线?

    这是我的代码 import package angular angular dart class AppModule extends Module AppModule type AppController type LoginControl
  • Biopython无法直接访问异质残基

    我可以使用以下方法直接获取蛋白质 1n31 的残基 residue structure 0 A 100 然而 当我尝试访问异质残基时 例如 residue structure 0 A 2003 我收到错误消息 File
  • 顺序订阅可观察数组

    在这里 我用过forkJoin从 rxjs 并行订阅可观察数组 但我想一一订阅 最好的解决方案是什么 下面是我的代码 var observables Observable forkJoin observables subscribe gt
  • 从 Vaadin 8 Grid 获取列表

    Problem 我有一个 Vaadin 8 Grid 但我找不到提取其中项目的方法 描述 从网格开始 Grid
  • Clojure:避免埃拉托斯特尼筛中的堆栈溢出?

    这是我在 Clojure 中实现的埃拉托斯特尼筛法 基于 SICP 流课程 defn nats from n iterate inc n defn divide p q zero rem q p defn sieve stream lazy