2

我在考虑如何构建*+, 并最终构建+inc,然后在另一个方向上应用相同的模式,使用较低的函数(f a b)b 次,你会得到一个不断增加的超乘函数的阶梯。所以我决定尝试编写一个不断增加的超算子的无限列表。我想出了这个,这非常接近!:

(defn operator-staircase
  []
  (iterate
   (fn [f]
     (fn [a b]
       (loop [bottom b
              result a]
         (if (>= 0 bottom)
           result
           (recur
            (dec bottom)
            (f a result))))))
   (fn [a b]
     (inc b))))

(def ops (operator-staircase))
((nth ops 0) 3 5) ;; -->  6  (inc is arity one so it must ignore one of the args?)
((nth ops 1) 3 5) ;; -->  8  (correct addition)
((nth ops 2) 3 5) ;; -->  18  (oops, one off!  otherwise correctly multiplies.)  
                                Basically implements (fn [a b] (* a (inc b)))
((nth ops 3) 3 5) ;; ---->  1092 (Wow)

我唯一不知道怎么做的就是result以一般的方式定义首字母!我之所以这样做是a因为它有点用,但是对于加法,例如它必须是 0,而乘法应该是 1。

如何result在上面的循环中定义初始值,以便它在所有情况下都能以一般方式工作?

提前致谢!

4

2 回答 2

1

我认为如果你想从 开始inc,你只能有意义地定义一元运算符。所以第0步是“加一”;第一步是“N次:加一”,基本上就是#(+ % %);第二步是“N次:加N”,即#(* % %);第三步是“N次:乘以N”,即#(pow % %)……以此类推。

如果你想定义二元运算符,我认为你只是从而+不是从开始inc,然后像你一样推导出其余的。

于 2013-03-21T06:05:09.647 回答
0

我认为阿莫洛伊说的是正确的。这是我的序列版本,从+amalloy 的建议开始。与您的另一个区别是我的计数器变量从 at(dec b)而不是开始b。原因是如果你把eg想象a*3成“a对自身相加3次”,这仍然只是加法函数的2次应用(即a+a+a)。通过这些更改,我得到了我认为您期望的结果。

(def operator-staircase
  (iterate
    (fn [f]
      (fn [a b]
        (loop [acc a
               counter (dec b)]
        (if (>= 0 counter)
          acc
          (recur (f a acc) (dec counter))))))
    +))

;; in comments, * is multiplication, ** is exponentiation (chained multiplication), *** is chained exponentiation, etc
(println ((nth operator-staircase 0) 3 2)) ; 5 = 3+2 = (inc (inc 3)))
(println ((nth operator-staircase 1) 3 2)) ; 6 = 3*2 = 3+3
(println ((nth operator-staircase 2) 3 2)) ; 9 = 3**2 = 3*3 = 3+3+3
(println ((nth operator-staircase 3) 3 2)) ; 27 = 3***2 = 3**3 = 3*3*3
;(println ((nth operator-staircase 4) 3 2)) ; takes too long to compute, but presumably 7625597484987 = 3****2 = 3***3 = 3**(3**3)
(println ((nth operator-staircase 0) 2 3)) ; 5 = 2+3 = (inc (inc (inc 2)))
(println ((nth operator-staircase 1) 2 3)) ; 6 = 2*3 = 2+2+2
(println ((nth operator-staircase 2) 2 3)) ; 8 = 2**3 = 2*2*2 = 2+2+2+2
(println ((nth operator-staircase 3) 2 3)) ; 16 = 2***3 = 2**(2**2) = 2*2*2*2

让我们稍微分解一下前几次迭代:

(defn apply-n-times [f n arg]
  (if (= n 0) arg
    (recur f (dec n) (f arg))))

(defn plus [m n]
  (apply-n-times inc n m))

(defn times [m n]
  (apply-n-times (partial plus m) (dec n) m))

(defn exp [m n]
  (apply-n-times (partial times m) (dec n) m))

(defn expexp [m n]
  (apply-n-times (partial exp m) (dec n) m))

同样,有必要应用(dec n)时间而不是n. 如果我应用n时间,那么第三个参数必须是 0times和 1 exp,而不是m所有时间,所以不会有一致性。

apply-n-times功能允许我们更简洁地定义您的操作员楼梯:

(def os2
  (iterate
    (fn [f]
      (fn [m n]
        (apply-n-times (partial f m) (dec n) m)))
    +))

这个给出与前面定义相同的结果。但是我仍然不能再往下走一步+,按照inc相同的顺序来定义。plus如果你看一下和上面的其他函数( times, exp, )之间的区别expexp,我想你可以看到结构不一样。

于 2013-03-22T14:26:42.853 回答