2016-04-11 11 views
1

私は(core.logic付き)Clojureのに次のコードを持っている:Clojure core.logicすべての述語を満たすすべてのメンバーを見つけるか?

(db-rel parent x y) 
(db-rel go-to-school x y) 

(def schools 
    (db 
    [parent 'Adam 'Ana] 
    [parent 'Adam 'Andre] 
    [parent 'Adam 'Alan] 
    [parent 'Bernard 'Bia] 
    [parent 'Bernard 'Beatrice] 
    [parent 'Carl 'Carlos] 
    [parent 'Carl 'Connie] 

    [go-to-school 'School1 'Ana] 
    [go-to-school 'School1 'Andre] 
    [go-to-school 'School2 'Alan] 
    [go-to-school 'School2 'Bia] 
    [go-to-school 'School2 'Beatrice] 
    [go-to-school 'School1 'Carlos] 
    [go-to-school 'School2 'Connie])) 

私が欲しいものは、すべての子どもたちが同じ学校に行くすべての親を見つけることです。上のリストを実行すると、私の期待リターンは('Bernard)になります。なぜなら、彼の2人の娘は、他のすべての親が少なくとも1人の子供を同席していない "学校2"に行くからです。

これはcore.logicで可能ですか?もしそうなら、どうしたらいいですか?

答えて

1

Core.logicを使用しているときは、Clojureにフルアクセスできます。学校で、それぞれの親を関連付けてみよう、とそこに仕事のフォーム:

stack-prj.logic-school> (set 
(pldb/with-db schools 
    (run* [par sch] 
    (fresh [kid] 
     (go-to-school sch kid) 
     (parent par kid))))) 
#{[Bernard School2] [Adam School2] [Carl School2] [Carl School1] [Adam School1]} 

私はユニークな結果を得るために、標準的なClojureの機能setを使用。そこから、group-by最初の要素filterは1より大きい数を持つすべてのものを取り除くことができ、結果はすべての子供を1つの学校に送る親である(キーとして、first要素を取る必要があります)各項目から)。

(defn parent-with-one-school [] 
    (->> (set 
     (pldb/with-db schools 
      (run* [par sch] 
      (fresh [kid] 
       (go-to-school sch kid) 
       (parent par kid))))) 
     (group-by first) 
     (filter #(= 1 (count (second %)))) 
     (map first))) 

テストしましょう!

stack-prj.logic-school> (parent-with-one-school) 
(Bernard) 
+0

他のClojure関数を使用せずにこれを実行できるかどうかはわかりました。理由は、この問題を巨大なデータセットに適用し、core.logicがなくても高速であるかどうかを確認するためです。 –

関連する問題