Clojure初學者在這裏。下面是一些代碼,我想了解,從http://iloveponies.github.io/120-hour-epic-sax-marathon/sudoku.html(一個相當不錯的開始Clojure的過程中的一個頁面):`for`如何在這個遞歸Clojure代碼中工作?
Subset sum is a classic problem. Here’s how it goes. You are given:
a set of numbers, like #{1 2 10 5 7}
and a number, say 23
and you want to know if there is some subset of the original set that sums up to the target.
We’re going to solve this by brute force using a backtracking search.
Here’s one way to implement it:
(defn sum [a-seq]
(reduce + a-seq))
(defn subset-sum-helper [a-set current-set target]
(if (= (sum current-set) target)
[current-set]
(let [remaining (clojure.set/difference a-set current-set)]
(for [elem remaining
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
solution))))
(defn subset-sum [a-set target]
(subset-sum-helper a-set #{} target))
So the main thing happens inside subset-sum-helper. First of all, always check if we have found
a valid solution. Here it’s checked with
(if (= (sum current-set) target)
[current-set]
If we have found a valid solution, return it in a vector (We’ll see soon why in a vector). Okay,
so if we’re not done yet, what are our options? Well, we need to try adding some element of
a-set into current-set and try again. What are the possible elements for this? They are those
that are not yet in current-set. Those are bound to the name remaining here:
(let [remaining (clojure.set/difference a-set current-set)]
What’s left is to actually try calling subset-sum-helper with each new set obtainable
in this way:
(for [elem remaining
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
solution))))
Here first elem gets bound to the elements of remaining one at a time. For each elem,
solution gets bound to each element of the recursive call
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
And this is the reason we returned a vector in the base case, so that we can use for
in this way.
果然,(subset-sum #{1 2 3 4} 4)
回報(#{1 3} #{1 3} #{4})
。
但是爲什麼第3行的subset-sum-helper
要返回[current-set]
?難道這不會返回([#{1 3}] [#{1 3}] [#{4}])
的最終答案嗎?
我嘗試刪除封閉括號中的3號線,使得函數開頭是這樣的:
(defn subset-sum-helper [a-set current-set target]
(if (= (sum current-set) target)
current-set
(let ...
現在(subset-sum #{1 2 3 4} 4)
回報(1 3 1 3 4)
,這使得它看起來像let
積累不是三套#{1 3}, #{1 3}和#{4},而只是「裸數」,給出(1 3 1 3 4)
。
因此subset-sum-helper
在遞歸計算中使用列表理解for
,我不明白髮生了什麼。當我嘗試這個可視化計算遞歸,我發現自己在問,「所以,當
(subset-sum-helper a-set
(conj current-set elem)
target)
,因爲沒有答案,可以給它的出發點不返回答案會發生什麼?」 (我最好的猜想是它返回[]
或類似的東西。)我不明白教程編寫者在寫作時意味着什麼,「這就是我們在基本情況下返回矢量的原因,因此我們可以使用for
這條路。」
我將不勝感激任何幫助,你可以給我。謝謝!
我現在 – tangrammer