我正在研究Project Euler问题,其中涉及分解数字,并编写了以下函数来执行此操作。
(defn get-factors [value]
(let [max-factor (->> (Math/sqrt value)
(Math/floor)
(Math/round))
ifactors #{}]
(loop [n 2 factors ifactors]
(do
(println (format ">> N: %d, Factors: %s" n factors))
(cond
(when (> n max-factor) ; exit of we have passed the max-factor
(do
(println (format "--Exiting(%d): %s" n factors))
factors)) ; return factors
(when (= 0 (mod value n)); have we found a factor?
(do
(println (format"--Factor(%d)" n))
(recur (inc n) (conj factors n (/ value n))))) ; recurse: add _n_ and reciprocal _n_ to list
:default (do ; otherwise
(println (format"--default(%d): %s" n (= 0 (mod value n))))
(recur (inc n) factors)) ; recurse: increment _n_, dont modify factors
)))))
但是,该函数返回nil
并且我的println语句以奇怪的顺序进行评估。以下是(get-factors 12)
的REPL输出,该输出应返回#{2,3,4,6}
:
>> N: 2, Factors: #{}
--default(2): true
>> N: 3, Factors: #{}
--default(3): true
>> N: 4, Factors: #{}
--Exiting(4): #{}
--Factor(4)
>> N: 5, Factors: #{3 4}
--Exiting(5): #{3 4}
正如您所看到的,即使前一个案例的(= 0 (mod value n))
评估为true,也会触发默认状态。同样,退出条件被命中两次。评估的最后一个案例应该是n = 3,但你可以看到最多n = 5的输出。
我显然做了一些根本错误的事情,但我没有看到什么。 (相关,有没有更好的方法来构建列表?)
答案 0 :(得分:1)
首先,有一个隐含的"当" (或" if")在任何cond
的测试部分中,因此您不应该在该测试中使用when
。
其次,您使用单个表单when
表单作为cond
的整个分支,因此,cond
没有看到它预期的第二个表单测试是真的。
查看适当的cond
:
答案 1 :(得分:0)
如果正如其他人所建议的那样,你会删除所有的问题 - when
和do
以及println
- 你的程序是有效的!
一些建议:
quot
代替/
获取整数商。 (->> value (Math/sqrt) ... )
。 :else
,而非:default
或其他任何内容在cond
中引入catch-all条款。