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

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(使用前将#替换为@)

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

  • JavaScript:使用递归检查数字是否为素数

    我对如何解决这个问题有点困惑 我需要所有素数才能返回 true 如果不返回 false 我看到我的逻辑包括 2 并且返回 0 所以它自动返回 false 因为 2 余数为 0 function isPrime num div 2 BASE
  • 对方案中的列表进行排序

    如何编写一个排序算法 以升序返回列表 ex 1 3 5 2 9 回报 1 2 3 5 9 大多数Scheme 实现都附带一个对列表进行排序的过程 如果您的实现没有提供这一功能 那么为您提供一个并不困难 下面是快速排序算法的实现 gt def
  • 按方案中的第一个元素对列表列表进行排序

    例如 我正在研究按第一个元素对列表列表进行排序 排序 列表 2 1 6 7 4 3 1 2 4 5 1 1 预期输出 gt 1 1 2 1 6 7 4 3 1 2 4 5 我使用的算法是冒泡排序 我修改了它来处理列表 但是 该代码无法编译
  • 如何重写Scheme中的“begin”?

    As the 维基百科 http en wikipedia org wiki Scheme programming language Standard forms文章解释说 begin在Scheme中是一种库形式 可以使用更基本的形式重写
  • 查找 lambda 表达式中的自由变量

    有谁知道如何找出 lambda 表达式中的自由变量 自由变量是不属于 lambda 参数的变量 我当前的方法 这对我毫无帮助 是简单地使用 car 和 cdr 来遍历表达式 我的主要问题是确定一个值是否是一个变量或者它是否是方案原语之一 有
  • 为什么我的 Scheme 函数返回错误“应用程序:不是过程”?

    我想获得 a b c 的第二个值 但我不想使用 cadr 我可以得到正确的答案 car cdr a b c b 但是当我构建该函数时 define test lambda list car cdr list test a b c 我收到以下
  • 如何找到 MIT 方案中出现错误的地方?

    当你在 MIT 方案中遇到错误时 它不会告诉你错误发生在哪里 例如 它只打印如下内容 Unbound variable top left To continue call RESTART with an option number REST
  • 方案/球拍:画布操作

    1 正如标题所述 当我调整窗口大小时 我绘制的对象消失 但矩形保持原样 2 原点从左上角开始 但我希望它在左下角 3 除了绘图库之外 我找不到任何缩放功能 所以如果我希望实现这样的功能 一个选项是通过绘制更大的对象并刷新画布来 缩放 def
  • (Chez) 用于隐藏 lambda 的方案宏

    我想编写一个宏来创建速记语法来隐藏更详细的 lambda 表达式 但我很难理解如何编写宏 我意识到这是反对使用它们的一个论据 给出这个例子 define alist example x 1 2 3 y 4 5 6 z 7 8 9 defin
  • 方案:为什么内部定义比外部定义快?

    我尝试运行下面的程序 define odd internal x define even x if zero x t odd internal sub1 x if zero x f even sub1 x define odd extern
  • 查找两个数字之间素数个数的快速算法

    我的问题简化为找到两个给定数字之间的素数数量 我的范围可以大到1 to 1000 因此我需要一些数学优化 显然 在这种情况下 筛法会太慢 是否有任何可以应用的数学优化 例如 采用这个大空间的较小子集并对其余数字进行推断 P S 看起来我可能
  • 不知道如何解决 SICP 练习 1.11

    练习1 11 http mitpress mit edu sicp full text book book Z H 11 html thm 1 11 一个功能f由以下规则定义f n n if n lt 3 and f n f n 1 2f
  • Clojure:避免埃拉托斯特尼筛中的堆栈溢出?

    这是我在 Clojure 中实现的埃拉托斯特尼筛法 基于 SICP 流课程 defn nats from n iterate inc n defn divide p q zero rem q p defn sieve stream lazy
  • Swift 处理数字真的很慢吗?

    当我在玩快速教程时 我开始编写一个自定义的isPrime方法来检查给定的Int是否是素数 写完后我发现它可以正常工作 但发现执行起来有点慢isPrime一些quite大量 仍然远低于Int max 所以我在 objc 中编写了同样的代码 代
  • 创建后缀号码球拍

    我正在尝试在 Racket 中试验我可以做的事情 并且我想在数字后加上字母 对于这个例子 我只想代表10000 as 10K and 1000000 as 1M 有没有办法 用宏或其他方式 我可以扩展1M to 1 1000000 或者有什
  • 模拟Scheme中Python的范围

    如何在Scheme中创建连续数字的列表 在Python中创建一个从1到10的整数列表是range 1 11 方案有等效的吗 mzscheme version gives Welcome to Racket v5 2 1 Edit Per h
  • 方案语言:合并两个数字

    如何将列表中的两个整数合并为一个 方案中 例子 11 223 gt 11223 假设列表恰好有两个元素 并且都是数字 define merge numbers lst let 1st number gt string first lst 2
  • Python while 循环查找素数

    作为 Python 的第一个练习 我尝试编写一个使用循环来查找素数的程序 一切都适用于 for 循环 所以我尝试使用 while 循环 这可行 但程序返回一些不正确的数字 import math looking for all primes
  • 如何将一个数表示为4个素数之和?

    这是问题所在 四个素数的和 http acm uva es p v101 10168 html 指出 输入的每一行包含一个整数 N N 输入示例 24 36 46 示例输出 3 11 3 73 7 13 1311 11 17 7 我第一眼就
  • 方案中的多维向量?

    我之前问过一个关于方案中数组的问题 结果它们被称为向量 但在其他方面基本上与您期望的相同 有没有一种简单的方法可以在 PLT 方案中处理多维 arrays 向量 出于我的目的 我想要一个名为make multid vector或者其他的东西

随机推荐