2016-04-11 7 views
1

Ich habe den folgenden Code in Clojure (mit core.logic):Clojure core.logic alle Mitglieder finden, die alle Prädikate erfüllt?

(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])) 

Was ich will, ist es, alle Eltern zu finden, wo alle Kinder auf die gleiche Schule gehen. Also, auf der obigen Liste läuft, wäre meine erwartete Rückkehr ('Bernard), weil seine zwei Töchter die "Schule2" gehen, wo jeder andere Elternteil mindestens ein Kind hat, das nicht zur gleichen Schule von anderen geht.

Ist dies mit core.logic möglich? Wenn ja, wie kann ich das tun?

Antwort

1

Vergessen Sie nie, dass Sie vollen Zugriff auf Clojure haben, wenn Sie Core.logic verwenden. Lassen Sie sich jeden Elternteil mit einer Schule zuzuordnen, und Arbeitsform gibt:

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]} 

verwenden ich den Standard Clojure Funktion set die einzigartigen Ergebnisse zu erhalten. Von dort können wir group-by das erste Element, filter heraus alles, was eine Zählung größer als 1 hat, und die Ergebnisse werden die Eltern sein, die alle ihre Kinder an eine Schule senden (als Schlüssel, also müssen wir das first Element nehmen von jedem Artikel).

(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))) 

Lass es uns testen!

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

Ich weiß, dass ich mich nur gefragt habe, ob ich das tun könnte, ohne andere Clojure-Funktionen zu verwenden. Der Grund ist, dass ich dieses Problem auf ein riesiges Dataset anwenden und sehen wollte, ob core.logic schneller wäre als ohne es. –

Verwandte Themen