2016-04-11 2 views
1

У меня есть следующий код в Clojure (с core.logic):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), потому что его две дочери идут в «school2», где у каждого другого родителя есть хотя бы один ребенок, который не пойдет в одну школу других.

Возможно ли это с 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, чтобы получить уникальные результаты. Оттуда мы можем сделать первый элемент, filter, из всего, что имеет счет больше 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 быстрее, чем без него. –

Смежные вопросы