我觉得最好的方法不是嵌套而是预先计算。综观我们与零个测试基础案例:
(mystery 0 2) ; ==> 2
(nystery 3 0) ; ==> 3
因此,每一个的至少一个参数是零时间则返回其他参数。让我们试着用非零值,记得你看,我们已经做了值的第二之前,你只是它的结果打开它:
(mystery 1 3) ; ==
(+ 2 (mystery 0 2)) ; == (we switch known value)
(+ 2 2)
; ==> 4
(mystery 4 1) ; == (we substitute with the expression)
(+ 2 (mystery 3 0)) ; == (we switch known value)
(+ 2 3)
; ==> 5
因为我们知道基本情况总是返回我们没有其他的价值需要预先计算。下面是这样做的:
(mystery 3 9) ; == (we substitute with the expression)
(+ 2 (mystery 2 8) ; == (we substitute with the expression)
(+ 2 (+ 2 (mystery 1 7))) ; == (we substitute with the expression)
(+ 2 (+ 2 (+ 2 (mystery 0 6))) ; == (we substitute with the expression, n, which is 6)
(+ 2 (+ 2 (+ 2 6))) ; == (we substitute (+ 2 6))
(+ 2 (+ 2 8)) ; == (we substitute (+ 2 8))
(+ 2 10) ; == (we substitute (+ 2 10)
; ==> 12
我们可以概括会发生什么。 n
和m
的最低值将决定递归何时结束。在每一步它会加2和递归。因此,它是制作一个奇特的方式:
(define (double-min n m)
(let ((vmin (min n m))
(vmax (max n m)))
(+ (* 2 vmin) (- vmax vmin))))
这又是因为如果n > m
添加两个数字,然后2*m+(n-m) = m+m+(n-m) = m+n
非常感谢,让它更清晰 – bgb102
这个答案是错误的,很难遵循。 '(神秘0)'应该是'',而不是'0'。 “神秘”实现了另外的问题标题暗示,而不是“双分”。 –
jerry
@jerry与OPs代码一样,Mystery不**执行加法操作。如果'n'或'm'为零,则结果为零。默认情况下,将两个参数减1后的递归结果相加。因此,基本情况是当两者中的最小者为零时,使函数计算它的最小参数的两倍。因此'(* 2(min n m))'。使用预先计算的值来替代是推断纯递归函数的最简单方法。 – Sylwester