分区特定集

时间:2014-10-18 01:10:56

标签: clojure

我想使用clojure来划分特定的集合:

例如: 有一个向量[1 2 3 4 5]。此处还有一个地图,如{2 1, 3 1},这意味着生成包含2个元素的1个集合,以及包含3个元素的1个集合。

(some_function {2 1, 3 1} [1 2 3 4 5])
;; I only want to these: 
 (([1 2 3] [4 5]) 
 ([1 2 4] [3 5]) 
 ([1 2 5] [3 4]) 
 ([1 2] [3 4 5]) 
 ([1 3 4] [2 5]) 
 ([1 3 5] [2 4]) 
 ([1 3] [2 4 5]) 
 ([1 4 5] [2 3]) 
 ([1 4] [2 3 5]) 
 ([1 5] [2 3 4]))

以前,我曾考虑使用(combo/partitions [1 1 2])来生成所有案例,然后根据条件进行过滤,但是当你有一个像[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]这样的大型向量并且像{{{{}}这样的地图时效率很低1}}。我只是想在第一时间生成我需要的东西,我该怎么做这个工作?

1 个答案:

答案 0 :(得分:2)

在您给出的具体示例中,有5,717,712个分区满足这些约束,并且没有约束的可能性更大。因此,组合学效率低下并不是那么重要;我认为你只是低估了有多少可能性。

组合功能是实现您正在寻找的更直接组合的更好工具。

在您的示例中,

(def specific-partitions
  (let [initial-list [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]]   
    (for [c1 (combinations initial-list 5)
          :let [remainder1 (remove (set c1) initial-list)]
          c2 (combinations remainder1 6)
          :let [remainder2 (remove (set c2) remainder1)]]
      [c1 c2 remainder2])))

=>(take 10 specific-partitions)

([(1 2 3 4 5) (6 7 8 9 10 11) (12 13 14 15 16 17)] 
 [(1 2 3 4 5) (6 7 8 9 10 12) (11 13 14 15 16 17)] 
 [(1 2 3 4 5) (6 7 8 9 10 13) (11 12 14 15 16 17)] 
 [(1 2 3 4 5) (6 7 8 9 10 14) (11 12 13 15 16 17)] 
 [(1 2 3 4 5) (6 7 8 9 10 15) (11 12 13 14 16 17)]
 [(1 2 3 4 5) (6 7 8 9 10 16) (11 12 13 14 15 17)] 
 [(1 2 3 4 5) (6 7 8 9 10 17) (11 12 13 14 15 16)]
 [(1 2 3 4 5) (6 7 8 9 11 12) (10 13 14 15 16 17)]
 [(1 2 3 4 5) (6 7 8 9 11 13) (10 12 14 15 16 17)]
 [(1 2 3 4 5) (6 7 8 9 11 14) (10 12 13 15 16 17)])

它仍然是相当多的分区,但至少你现在正在直接生成它们。

从这个例子中,您可以将此技术概括为一个函数,该函数采用描述分区结构的任意映射,就像您在问题中描述的那样。

如果您的初始集具有重复元素,那么我在此处撰写的特定代码将无法正常工作;这需要稍微不同的删除方法。