方案中的埃拉托色尼筛选在其过滤过程中使用局部状态的突变

2023-12-13

While 回答最近question我想出了以下代码,实现了埃拉托斯特尼筛的变体,反复剔除初始的2...n顺序,尽早停止:

(define (sieve2 n)
  (let ((ls (makelist n)))
    (let loop ((ls ls) 
               (next (sievehelper2 ls n)))
      (if (null? next)
          ls
          (cons (car ls) 
                (loop next (sievehelper2 ls n)))))))

(define (sievehelper2 list n)
  (if (> (* (car list) (car list)) n)
      '()
      (filterfunc (not-divisible-by (car list)) 
                  list)))

(define filterfunc filter)

(define (not-divisible-by n)
  (let ((m n))   ; the current multiple of n
    (lambda (x)
      (let ((ret (not (= x m))))
        (if (>= x m) (set! m (+ m n)) #f)
        ret))))

(define (makelist n)
  (range 2 (+ 1 n)))

Running (sieve 50)在 球拍 结果'(2 3 3 5 5 7 7 11 11 13 17 19 23 29 31 37 41 43 47) though.

它有一些错误,正如结果中显而易见的那样,我没有立即看出它在哪里。这可能是我犯的一些愚蠢的错误,也可能是所使用的算法部分存在一些根本性错位的表现,我不能说哪个是哪个。

请问这个错误是什么?如何修复?

需要明确的是,我并不是要求对代码进行算法改进,我想要计算结构表达在其中保留。此外,我在相关问题中看到的挑战是设计缺失的功能 - 并改变sieve本身——同时保持sievehelper功能as given,最多进行一些细微的更改,如该问题的代码所示。这也是我想提出的要求this问题。

我也不满意two打电话给sievehelper2 in sieve2。也许以某种方式修复代码结构也会使错误消失?


问题就在这里:

(loop next (sievehelper2 ls n))

列表ls第二次通过sievehelper2在这次通话中;但sievehelper2需要处理next:

(define (sieve2 n)
  (let ((ls (makelist n)))
    (let loop ((ls ls) 
               (next (sievehelper2 ls n)))
      (if (null? next)
          ls
          (cons (car ls) 
                (loop next (sievehelper2 next n)))))))

通过此更改,筛子似乎按预期工作:

sieve2.rkt> (sieve2 50)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)

摆脱外部可能有助于代码清晰let in sieve2,并且只拨打一次sievehelper2:

(define (sieve3 n)
  (let loop ((filtered '())
             (candidates (makelist n)))
    (if (null? candidates)
        filtered
        (cons (car candidates) 
              (loop (cdr candidates) (sievehelper2 candidates n))))))

这也按预期工作:

sieve2.rkt> (sieve3 50)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)

一些改进

我不满意sieve3多于。虽然我认为只显示一个电话sievehelper2有助于清晰,代码仍然可以变得更清晰。

最初sieve3 had a result变量已更改为filtered. result描述性不够,没有帮助,我认为这种改变是一种进步;毕竟,filtered确实包含过滤的结果candidates列表。虽然,初始值filtered从这个意义上来说是没有意义的,因为candidates尚未被过滤。

更让我困扰的是构造:

(cons (car candidates) 
      (loop (cdr candidates) (sievehelper2 candidates n)))

目前还不是很清楚(car candidates)是一个正在被收集的素数,并且(cdr candidates)是部分过滤的候选列表,或者目标是在完全过滤的候选列表上找到素数。

这是一个改进版本sieve使用显式累加器primes保存遇到的素数。什么时候sievehelper2返回一个空列表,我们知道filtered列表已完全过滤掉非素数。最后,找到的素数和完全过滤的候选列表可以附加在一起并返回(但不是在反转找到的素数列表之前,因为最近找到的素数被放在前面)primes). This sieve过程还具有尾递归的优点:

(define (sieve n)
  (let loop ((primes '())
             (filtered (makelist n)))
    (let ((next (sievehelper2 filtered n)))
      (if (null? next)
          (append (reverse primes) filtered)
          (loop (cons (car filtered) primes)
                next)))))
sieve2.rkt> (sieve 50)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

方案中的埃拉托色尼筛选在其过滤过程中使用局部状态的突变 的相关文章

  • 如何获取 SICP、Scheme、练习 2.78 等中的 put 和 get 函数

    我正在尝试在 SICP 中做练习 2 78 但 put 和 get 函数未知 我尝试过多种语言 比如相当大 racket r5rs mit scheme mzscheme等 我什至下载了SICP支持 http www neilvandyke
  • 模拟Scheme中Python的范围

    如何在Scheme中创建连续数字的列表 在Python中创建一个从1到10的整数列表是range 1 11 方案有等效的吗 mzscheme version gives Welcome to Racket v5 2 1 Edit Per h
  • Lisp 中的 (定义 (平均 ....))

    我只是在玩scheme lisp 并正在考虑如何纠正我自己的定义average 我不确定如何做一些我认为需要的事情 定义一个接受任意数量参数的过程 计算这些参数 将参数列表传递给 以将它们加在一起 有人有定义的例子吗average 我似乎对
  • 方案中的尾递归幂函数

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

    我想做的就是使用 when 语句返回一个值 我想要以下功能 if x return y 我正在尝试使用 when x y 但是when语句并没有以退出函数并返回y的方式进行计算 它只是愉快地继续下一行 有没有办法做到这一点而不需要制作一个看
  • 球拍博士中的位图[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 drracket 中的框架 gui 上加载位图 请给出必要的代码和参考文献 我承认 我很难在文档中找到正确的位置来指向您 这是
  • Java 8 Stream,获取头部和尾部

    Java 8 引入了Stream http download java net jdk8 docs api java util stream Stream html类似于 Scala 的类Stream http www scala lang
  • 使用 forge(或其他 JavaScript 方法)生成随机大素数

    我需要在 JavaScript 中生成一个随机大 大约 4096 位 素数 并且我已经在使用 forge Forge 必须有某种生成器来完成此类任务 因为它实现了 RSA 而 RSA 也依赖于随机素数 然而 当你只想获得一个随机素数 类似于
  • 如何让球拍不打印?

    我正在 Racket 中编写一个程序 我正在使用它运行racket foo rkt 这是可行的 除了程序顶层每个表达式的结果都会被打印 即使没有调用打印函数 就好像程序是逐行输入到 REPL 中的 但在这种情况下 我根本不尝试使用 REPL
  • 我在函数的最后一次递归调用中得到“方案应用程序而不是过程”

    所以这是代码 define time prime test n newline display n start prime test n runtime define start prime test n start time if pri
  • 找到一个数是素数,为什么检查到n/2更好。避免n后半部分的数字的原因是什么

    要检查一个数是否是素数 最简单的方法是尝试将这个数除以 2 到 n 如果任何操作得到余数为 0 那么我们就说给定的数不是素数 但最好只进行划分和检查直到 n 2 我知道更好的方法是直到 sqrt n 我想知道跳过后半部分的原因 假设我们是否
  • 在编译时生成素数

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

    如果 Python 有一个类似于 Lisp Scheme 的宏工具 比如元Python https code google com p metapython 你会如何使用它 如果您是一名 Lisp Scheme 程序员 您会使用宏来做什么
  • 打印从 1 到 100 的质数

    此 C 代码打印出以下素数 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 但我不认为这就是我的书所希望的写作方式 它提到了一些关于数字的平方根的内容
  • 将数字转换为英文字母列表

    我有下面的函数 它将数字输入转换为这些数字的部分翻译的单词输出 使用乘积和商 它将数字的单词表示相加 同时将数字分组 例如 number name 87969087 gt 87 million 969 thousand 87 number
  • Prolog中计算数字是否为素数

    我正在尝试计算输入是否是素数 但出了问题 这是我的代码 primeNumber X prime prime A 1 prime prime A B R is A mod B R 1 R A prime prime X B B lt A Ne
  • 使用 Racket FFI 进行快速阵列访问

    我正在尝试在 Racket 中编写 OpenCV FFI 并达到了需要有效操作数组的地步 然而 我所有使用 Racket FFI 访问数组的尝试都会导致代码效率非常低 有没有办法使用 FFI 快速访问 C 数组 在 Racket 中 这种类
  • Racket 与Scheme 有何不同?

    Racket 是Scheme 的后代 Racket 与 R6RS 有何不同 它添加了什么 删除了什么 或者只是有所不同 我知道 Racket 不仅仅是一种语言 它还是一个语言平台 但我指的是主要的 Racket 方言 Racket 最终基于
  • 如何更改 DrRacket 中 R6RS 的打印行为以像 #langracket 一样打印结果

    当我在 IDE 版本 5 3 5 2013 06 18 f 中运行程序时 对于 lang racket eg lang racket 4 5 10 2 When pressing Run gt the interaction window
  • 素数生成器算法

    我一直在尝试解决素数生成算法的SPOJ问题 这是问题 彼得想为他的密码系统生成一些素数 帮助 他 你的任务是生成两个给定之间的所有素数 数字 Input 输入以单行中测试用例的数量 t 开始 t Output 对于每个测试用例 打印所有素数

随机推荐