【发布时间】:2014-09-06 10:15:38
【问题描述】:
我正在尝试计算一个数字的因数,给定素数,例如:
REPL=> (find-factors 1176 #{2 3 7})
#{7 24 4 21 1176 294 56 168 196 6 28 588 3 12 2 14 392 98 147 42 8 49 84}
我正在使用 reduce 并声明内部步骤函数,但似乎代码可以更简洁。我很感激有关如何使代码更惯用的任何建议。
(defn mul-all [find-for prod-multiples factors]
(let [step (fn [[prod-multiples factors] mult]
(let [step2 (fn [[prod-mults factors] mult2]
(let [multiple (* mult mult2)]
(if (zero? (rem find-for multiple))
[(into prod-mults [mult mult2 multiple]) (into factors [multiple])]
[(reduce disj prod-mults [mult mult2]) factors])))]
(reduce step2 [prod-multiples factors] prod-multiples)))]
(reduce step [prod-multiples factors] factors)))
(defn find-factors [find-for prime-factors]
(loop [result (mul-all find-for prime-factors prime-factors)]
(if (zero? (count (first result)))
(second result)
(recur (mul-all find-for (first result) (second result))))))
-------编辑---------
@A。韦伯 - 感谢您的代码。我习惯了命令式编程,所以我用 Groovy 重写了你的示例以了解它在做什么。 findFactorsInject() 方法使用Groovy 的inject() 方法,相当于Clojure 中的reduce。
static List recurFn(Set a, Integer n, Integer p ) {
println "a $a n $n p $p"
if(n%p == 0) {
a.addAll(a.collect{Integer it ->it*p})
recurFn(a, (Integer)(n/p), p);
} else {
return [a, n]
}
}
static findFactors(Integer findFor, Set<Integer> primes) {
List result = []
for(Integer prime in primes) {
if(result.size() == 0) {
result = recurFn([1] as Set, findFor, prime)
} else {
result = recurFn((Set)result[0], (Integer)result[1], prime)
}
}
return result
}
static findFactorsInject(Integer findFor, Set<Integer> primes) {
primes.inject ([[1] as Set, findFor],
{ List accumulate, Integer prime ->
recurFn((Set)accumulate[0], (Integer)accumulate[1], prime)
})
}
static main(args) {
println findFactors(1176, ( (Set) [2, 3, 7 ] as Set))
println findFactorsInject(1176, ( (Set) [2, 3, 7 ] as Set))
}
【问题讨论】:
标签: clojure