父母/子女的最低共同祖先是? Clojure中的层次结构

时间:2016-01-21 15:29:53

标签: clojure lowest-common-ancestor

假设我们有这个父/子层次结构:

(derive ::integer ::decimal)
(derive ::positive-integer ::integer)
(derive ::long ::integer)

实现在这样的层次结构中找到最低共同祖先的方法的Clojure惯用法是什么?即:

(lca ::positive-integer ::long) ; => ::integer

我最初的想法包括使用递归函数遍历每个参数的parents组合,但我怀疑可能有更好的方法。

我的动机是将它用作多方法的调度函数,该方法根据参数的类型将2个参数和调度分配给最适合的实现。

1 个答案:

答案 0 :(得分:1)

函数ancestors会返回一个集合,因此您需要(require [clojure.set :as s])

现在写:

(defn lca [h1 h2]
  (let [a1 (into #{} (conj (ancestors h1) h1))
        a2 (into #{} (conj (ancestors h2) h2))
        ac (s/intersection a1 a2)]
    (apply (partial max-key (comp count ancestors)) ac)))

让我们试一试!

stack-prj.hierarchy> (derive ::integer ::decimal)
nil
stack-prj.hierarchy> (derive ::positive-integer ::integer)
nil
stack-prj.hierarchy> (derive ::long ::integer)
nil
stack-prj.hierarchy> (lca ::positive-integer ::long)
:stack-prj.hierarchy/integer

以下是它的工作原理:我使用ancestors获取每种类型的祖先集。我将类型本身添加到结果集中(因为我认为(lca ::integer ::long)应该使用integer而不是decimal),对于这两种类型。使用set intersection,我将所有共同祖先存储到变量conj中。

在共同的祖先中,我想知道其中哪一个拥有 most 祖先。 ac是一个函数,它接受一种类型并返回它拥有的祖先数。我将(comp count ancestors)部分应用于此函数,然后将结果函数(使用max-key)应用于集合apply。结果是具有最多祖先的共同祖先,或最不常见的祖先

(请注意,ac如果你将两种类型传递给它而没有任何共同的祖先会给出错误!你应该自己决定如何处理这种情况。)