- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(define (BOR x y)
(cond
((equal? x #t) #t)
((equal? y #t) #t)
(else #f))
)
(define (reduce op list)
(cond
((null? list)
(cond
((BOR (equal? op +) (equal? op -)) 0)
((BOR (equal? op *) (equal? op /)) 1)
((equal? op BOR) #f)
((equal? op BAND) #t)
(else #f)))
(else (op (car list) (reduce op (cdr list)))))
)
(display (reduce + '(1 2 3 4 5)))
(newline)
(display (reduce - '(100 20 30)))
(newline)
为了可见性,我加入了“BOR”。这是我的输出:
120
110
我的定义似乎是有效的,但没有按照我的意愿评估减法和除法。我尝试删除 BOR,在检查空列表后留下 6 个条件进行检查,输出没有任何变化。
您可能会注意到行为有点像这样:
(reduce - '(100 20 30 5 40)) is called.
This returns (+ (- (+ (- 100 20) 30) 5) 40).
Which is equivalent to 100 - 20 + 30 - 5 + 40 = 145.
这种触发器行为仅在我除法或减法时发生。我所有的其他操作都执行得很好。这是我的作业,所以请不要直接回答。也许我错过了方案递归的一些关键行为模式?任何帮助将不胜感激。
最佳答案
操作 + 和 * 已经在 Scheme 中定义为接受 0 个参数并在这些情况下返回恒等函数。减法和除法函数没有这个属性,主要是因为它们有一个参数的特殊情况,因为让 (/2)
返回 1/2
更方便> 比返回 2
更方便,(- 2)
返回 -2
比 2
更方便。
形式 or
和 and
不是函数,但也被定义为可以接受任意数量(包括零)的参数。如果至少有一个参数为真,则 or
返回 true,因此在没有参数时返回 #f
。 and
如果至少有一个参数为 false,则返回 false,因此在不带参数调用时返回 #t
。
加法和乘法具有交换律和结合律,因此您可以毫无问题地将恒等元添加到要归约的序列的任一端。例如,无论如何插入括号,0+a+b+c 都将与 a+b+c+0 相同。但是,减法和除法没有这个性质。一般来说,a-b-c 与 c-b-a 不同,0-a-b 与 a-b-0 不同。
这意味着您的 reduce 函数需要说明元素的组合顺序,以及应该在何处注入(inject)标识元素(或初始元素)。这是一般折叠的典型特征,而不仅仅是 reduce
。
我知道您说过您不想要解决方案,因为这是家庭作业,但我认为这段代码与您自己的代码完全不同,所以这不是什么大问题。不仅如此,Stack Overflow 的答案应该对每个人都有用,而不仅仅是最初的提问者。最后,reduce 是一个非常常见的函数,不难找到它的实现。
(define (reduce fn list init)
(if (null? list) init
(fn (car list)
(reduce fn (cdr list) init))))
这是一个 right-associative 折叠,它将 init
注入(inject)到列表中最后一个元素的右边。也就是说,对于 (reduce fn '(a b c) i)
,你得到
(fn a (fn b (fn c i)))
这意味着你可以做到
(reduce + '(...) 0)
(reduce - '(...) 0)
(reduce * '(...) 1)
(reduce / '(...) 1)
对于 bool 情况,您需要像 and
和 or
这样的函数,但这些很简单:
(define (%or x y)
(or x y))
(define (%and x y)
(and x y))
然后你可以做
(reduce %or '(...) #t)
(reduce %and '(...) #f)
请注意,在除法和减法的情况下,右结合 reduce 将标识元素放在您想要的位置,因为您最终将 '(a b c d)
变成了
(a - (b - (c - (d - 0))))
(a / (b / (c / (d / 1))))
但是,这很可能不是您想要的,因为这意味着您会得到所描述的“触发器”行为。例如,
a/(b/c) = (ac)/b ≠ (a/b)/c
对于除法和减法,您可能需要左结合归约。这些实际上恰好在 Scheme 中更有效一些,因为它们可以尾递归地实现,因此使用更少的堆栈空间。
(define (reduce fn init list)
(if (null? list) init
(reduce fn (fn init (car list)) (cdr list))))
这是左关联折叠对我来说最自然的方式,因为初始值位于列表的左侧,所以我们有 ((((i • a) • b) • c)
。当然,问题是对于除法和减法,我们确实希望将“初始”值放在末尾。您可以编写一个版本来做到这一点,但它有点复杂,因为您必须检查三种情况:(i) 没有元素的列表;(ii) 有一个元素的列表;以及 (iii) 至少有两个元素的列表:
(define (reduce fn list final)
(cond
((null? list)
init)
((null? (cdr list))
(fn (car list) init))
(else
;; do a normal left-associative reduce over the
;; list, but add the final element at the end.
(let red ((init (fn (car list) (cadr list)))
(list (cddr list))
(if (null? list) (fn init final)
(red (fn init (car list)) (cdr list))))))))
关于recursion - 在方案列表中定义 "reduce",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26242546/
虽然我在理解递归方面没有任何问题,但我似乎无法理解汉诺塔问题的递归解决方案。这是来自 Wikipedia 的代码: procedure Hanoi(n: integer; source, dest,
虽然我在理解递归方面没有任何问题,但我似乎无法理解汉诺塔问题的递归解决方案。这是来自 Wikipedia 的代码: procedure Hanoi(n: integer; source, dest,
The Third Commandment的 The Little Schemer状态: When building a list, describe the first typical elemen
编辑 有关映射递归的“正确”Groovy 式方法,请参阅下面的@tim 解决方案。由于 Map findRecursive 在 Groovy 中尚不存在,如果您发现自己在应用程序的各个部分都需要此功能
这是尝试求解 3*3 的线性方程并打印结果,但在注释行中遇到了问题: 我在程序外部定义了 LinearSolution 模块,我应该在程序内部定义它吗?有什么区别? 为什么说该语句是递归的,你知道,当
我正在学习 Clojure 并从复制 Python 程序的功能开始,该程序将通过遵循(非常简单的)隐马尔可夫模型来创建基因组序列。 一开始,我坚持使用我已知的串行编程方式并大量使用 def 关键字,从
我有一个记录: type node = { content : string; parent : node option;
我发现 Java 8 已经显着清理了将文件内容读取到字符串中的过程: String contents = new String(Files.readAllBytes(Paths.get(new URI
我目前正在用 Java 编写一个图形库,我想要一个工具来可视化一些图形。我发现了 Graph-viz,它恰好是一种很好的(尽管有缺陷)做到这一点的方法。 在我的模型中,图由节点和边组成。每个节点都有一
昨天我遇到了这个pipes Common Lisp 库。它在某种程度上看起来很像 clojure 的惰性序列抽象,因此我决定使用它来实现 Common Lisp 中递归惰性斐波那契序列定义的经典(且优
昨天我遇到了这个pipes Common Lisp 库。它在某种程度上看起来很像 clojure 的惰性序列抽象,因此我决定使用它来实现 Common Lisp 中递归惰性斐波那契序列定义的经典(且优
我在开发一个递归函数时遇到了问题,该函数将查看两个列表是否彼此相等,包括查看子列表。到目前为止,我有: (defun are-equal2 (X Y) (cond ((null X) nil)
在 Abelson/Sussman 的经典著作《计算机程序的结构和解释》中,在关于树递归和斐波那契数列的第 1.2.2 节中,他们展示了这张图片: 计算第 5 个斐波那契数时生成的树递归过程 然后他们
SICP中的Section 1.2.1 中的作者在下面给出了这样的代码示例,以显示如何使用迭代过程解决阶乘问题: (define (factorial n) (fact-iter 1 1 n))
我继承了 的遗产Fortran 77 我现在的代码 试试 前往 编译 Fortran 2003 标准。我对 Fortran (我知道 C 和 Python)一无所知,我正在学习它。 下面的代码片段会导
这个警告来自哪里: Warning: `recursive` is deprecated, please use `recurse` instead 我在这里看到过:https://r-pkgs.or
Section 2.2 of the Happy user manual建议您使用左递归而不是右递归,因为右递归是“低效的”。基本上他们是说,如果您尝试解析一长串项目,右递归将溢出解析堆栈,而左递归使
问题 我有一个递归 CTE 查询,但是在创建循环时它失败了。我已经修复了简单的循环(例如 1 -> 2 -> 1),但无法修复更复杂的循环(例如 1 -> 2 -> 3 -> 2)。 查询详情 测试表
看完麻省理工学院的动态规划讲座后,我想练习一下斐波那契数列。我首先编写了朴素的递归实现,然后添加了内存。这是内存版本: package main import ( "fmt" ) func f
按照以下步骤,Cloudformation 堆栈可以进入递归锁: 在不导入值的情况下设置 CF(并创建堆栈) 使用相同的 CF 模板创建 soms 输出值(并更新堆栈) 在同一 CF 模板(和更新堆栈
我是一名优秀的程序员,十分优秀!