Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure实现for循环的方法是什么?_Clojure - Fatal编程技术网

Clojure实现for循环的方法是什么?

Clojure实现for循环的方法是什么?,clojure,Clojure,在这个问题中,您将得到一个值V和一个唯一整数列表。您的工作是找到大小为4的不同子集的数量,这些子集的总和为V。列表中的每个元素只能使用一次。如果找不到这样的子集,则改为输出0 例如,如果整数是[3,4,5,6,7,8,9,10],且值是30,则输出应为5。这些子集是: [3, 8, 9, 10] [4, 7, 9, 10] [5, 6, 9, 10] [5, 7, 8, 10] [6, 7, 8, 9]. 解决这个问题并不难,最直接的方法是嵌套for循环四次。Clojure的方法是什么?我会使

在这个问题中,您将得到一个值V和一个唯一整数列表。您的工作是找到大小为4的不同子集的数量,这些子集的总和为V。列表中的每个元素只能使用一次。如果找不到这样的子集,则改为输出0

例如,如果整数是
[3,4,5,6,7,8,9,10]
,且值是
30
,则输出应为5。这些子集是:

[3, 8, 9, 10]
[4, 7, 9, 10]
[5, 6, 9, 10]
[5, 7, 8, 10]
[6, 7, 8, 9].

解决这个问题并不难,最直接的方法是嵌套for循环四次。Clojure的方法是什么?

我会使用
Clojure.map.combinations/combinations
来获得所有的4元素子集,然后
过滤出那些不等于V的子集。

我会这样做:

(ns example.solve
(:require[clojure.math.combinations:as combo]))
(defn求解
[新南威尔士州]
(过滤器(组件(部分=v)
(部分还原+)
(组合/组合s/n)))
我在我的示例中使用,因为这是从列表中获取4个元素的所有组合的最简单方法

下面是使用
solve
的示例:

=> (solve [3 4 5 6 7 8 9 10] 4 30)
((3 8 9 10) (4 7 9 10) (5 6 9 10) (5 7 8 10) (6 7 8 9))

有趣的是,这个问题允许(双重?)递归解决方案,它只涉及求和和和计数(而不实际生成子集)

如果您查看初始元素3,那么部分解决方案是从序列其余部分的3个元素中获取的和的数量,其中和为27,这是同一问题的较小形式,因此可以递归求解。递归的底部是在查找从1个元素生成的和时,这归结为一个简单的检查,以查看所需的和是否在列表中

解决方案的另一部分包括查看下一个元素4,查找列表中除4等于26之外的其他元素的和,依此类推。。。这一部分也可以递归处理

将其作为递归函数放在一起,如下所示,为示例序列生成所需的答案5

(defn solve [xs n len]
  (if (seq xs)
    (if (= len 1)
       (if (some #{n} xs) 1 0)
       (+ (solve (rest xs)
                 (- n (first xs))
                 (dec len))
          (solve (rest xs) 
                 n
                 len)))
    0))

(solve [3 4 5 6 7 8 9 10] 30 4)               
;=> 5

就直接回答这个问题而言,下面是如何使用索引和for循环来实现这一点:

(defn solve-for [xs v]
  (for [ndx0 (range 0          (- (count xs) 3))
        ndx1 (range (inc ndx0) (- (count xs) 2))
        ndx2 (range (inc ndx1) (- (count xs) 1))
        ndx3 (range (inc ndx2) (count xs))
        :when (= v (+ (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3)))]
    (list (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3))))

FWIW,这比使用
clojure.math.combinationals
的方法快70%左右,但速度是双递归解的两倍

非常好,只是为了说明答案:
(解[3,4,5,6,7,8,9,10]430)((3,8,9,10)(4,7,9,10)(5,6,9,10)(5,7,8,10)(6,7,8,9))
@JamesSharp-Thanx!在我的答案中添加了你的例子。comp函数非常出色!谢谢。我重构了你的函数以返回实际的解决方案:很好!我喜欢您的重构具有相同的形状,但将+替换为concat,并在需要时构建列表。谢谢你的洞察力!如果我们知道这些数字都是正数,这也允许一些短路。@Yes。也许如果所有这些都是负面的。此外,<代码>(SEQ XS)< /代码>测试可以扩展为考虑<代码> LeN<代码>。
组合数学
解决方案是理解IMHO最简单的方法,而这一方法似乎很快。