如何在Clojure for循环运行时更改:while条件?

时间:2014-01-04 21:51:16

标签: for-loop clojure

我正在寻找满足某些条件的最大数字,这些数字是所有三位数字的乘积。

直截了当的方式是:

(apply max (filter 
            my-test? 
            (for [x (range 100 1000)
                  y (range x 1000)]
              (* x y))))

但这涉及计算所有900 * 900产品中的一半。如果我发现,例如,(* 380 455)与我的my-test?谓词匹配,我不需要搜索任何因子小于380的产品。当然,我还想从列表中搜索如果我这样做,那就是最小到最小。

在psuedo-Clojure中,我想说这样的话:

(for [x (range 999 99 -1) :while (>= x P)
      y (range x 99 -1) :while (>= y P)]
  (* x y))

P是我每次找到匹配时神奇地设置为(min x y)的内容。

有没有办法在Clojure中做到这一点?

(我知道我可以以对角方式搜索数字,考虑到我已经设置的这个特定问题。但是,我现在正试图解决一般情况下找出如何告诉for循环一些分支机构需要修剪。)

2 个答案:

答案 0 :(得分:5)

@omeil建议使用loop / recur进程,这样可以更好地 for循环不是为此而构建的。

(loop [x 999 y 999 min 99 candidates []]
    (cond (<= x min)          candidates ; exit condition
          (<= y min)          (recur (dec x) 999 min candidates) ; step x
          (my-test? (* x y)) (recur x (dec y) (max min y) (conj candidates (* x y)))
          :else               (recur x (dec y) min candidates) ; step y
     ))

答案 1 :(得分:1)

一个非常丑陋的解决方案是使用atom

(let [P (atom 0)]
  (for [x (range 999 99 -1) :while (>= x @P)
        y (range x 99 -1)   :while (>= y @P)]
    (do
      (reset! P (+ x y))
      (* x y))))

我认为会阻碍的一点是for循环并不关心“输出”是什么,所以我无法看到它如何能够原生地获取该信息

“正确”的解决方案可能是一个递归的解决方案,允许您传递(a.k.a.更新)您的最小值。