пролог сопоставляет элементы из списка с предикатами - PullRequest
0 голосов
/ 07 июня 2018

Я новичок в прологе и пытаюсь решить мою выдумку, следуя проблеме пролога.

У меня есть некоторые люди

person(john, 36).
person(jane, 3).
person(amber, 32).
person(emmy, 2).
person(clement, 37).
person(patrick, 15).
person(emilie, 20).

У меня есть список соединений, представляющих продукты, которые можетбудь здоров (хорош).

foods([food(frechfries, _), food(apple, good), food(burger,_),
    food(kiwi, good), food(banana, good), food(potato, good), food(orange, good),
    food(cereal, good), food(hotdog, _), food(steak, _), food(coca, _), food(water, good)]).

Я бы хотел сопоставить каждый предмет одному человеку, чтобы раздать один и только один продукт каждому человеку.Для этого у меня есть следующее правило:

distribute(P, F, Results) :- person(P, _), findall(Item, memberchk(Item, F), Results).

К сожалению, каждый получает первый элемент списка

Выход

Если япопробуйте удалить использованный элемент с этим правилом:

distribute(P, F, Results) :- person(P, _), findall(Item, memberchk(Item, F), Results), delete(F, Item, F).

Я получаю тот же результат.Кто-нибудь видит, чего мне не хватает?

1 Ответ

0 голосов
/ 07 июня 2018

Говоря в общем, звучит так, как будто у вас есть две коллекции фактов, и вы просто хотите определить правило, которое выполняется для каждой уникальной совпадающей пары.

Наборы фактов person и food.Как я уже упоминал в комментарии, определение продуктов как одного факта со списком будет немного неловким.Я бы определил food так же, как вы определяете person, то есть как отдельные факты.

person(john, 36).
person(jane, 3).
person(amber, 32).
person(emmy, 2).
person(clement, 37).
person(patrick, 15).
person(emilie, 20).

food(frechfries, _).
food(apple, good).
food(burger,_).
food(kiwi, good).
food(banana, good).
food(potato, good).
food(orange, good).
food(cereal, good).
food(hotdog, _).
food(steak, _).
food(coca, _).
food(water, good).

Теперь мы можем подумать об определении совпадения.Вы можете думать об этом следующим образом:

Успешное совпадение состоит из списка пар человек-еда, в которых каждый человек и каждый продукт появляются только один раз (уникально выбираются из соответствующих коллекций) и каждый человек представлен.

Поскольку мы пытаемся выбрать каждого человека и еду по-своему, я думаю, что select/3 будет хорошим выбором в качестве основного механизма для достижения желаемой цели.

person_food_pairs(PeopleFoodPairings) :-
    findall(Person, person(Person, _), People),
    findall(Food, food(Food, _), Foods),
    length(People, NumberOfPeople),
    length(Foods, NumberOfFoods),
    NumberOfPeople =< NumberOfFoods,
    person_food_pairing(People, Foods, PeopleFoodPairings).

person_food_pairing([], _, []).
person_food_pairing(People, Foods, [Person-Food|RemainingPairs]) :-
    select(Person, People, RemainingPeople),
    select(Food, Foods, RemainingFoods),
    person_food_pairing(RemainingPeople, RemainingFoods, RemainingPairs).

Будет много комбинаций, так много решений!Я не видел никаких других условий, которые у вас были бы, чтобы ограничить это.Кроме того, вы можете пропустить этот набор строк, и код будет по-прежнему давать те же результаты из-за определения person_food_pairing/2:

    length(People, NumberOfPeople),
    length(Foods, NumberOfFoods),
    NumberOfPeople =< NumberOfFoods,

Однако тогда код будет выполнять много ненужного выполнения.просто чтобы окончательно определить, что это не может сделать сопряжение.Таким образом, эти строки помогают определить этот случай на ранней стадии.Если, как отмечено в комментариях, у вас есть условия, которые включают в себя некоторые атрибуты человека и еды, вам нужно будет нести эти атрибуты до тех пор, пока вы не выполните сопряжение.

person_food_pairs(PeopleFoodPairings) :-
    findall(Person-Age, person(Person, Age), People),  % Include age
    findall(Food-Health, food(Food, Health), Foods),   % Include health factor
    length(People, NumberOfPeople),
    length(Foods, NumberOfFoods),
    NumberOfPeople =< NumberOfFoods,
    person_food_pairing(People, Foods, PeopleFoodPairings).

person_food_pairing([], _, []).
person_food_pairing(People, Foods, [Person-Food|RemainingPairs]) :-
    select(Person-Age, People, RemainingPeople),  % Select person-age pair
    select(Food-Health, Foods, RemainingFoods),   % Select food-health pair
    (Age < 20 -> Health == good ; true),          % Condition to include
    person_food_pairing(RemainingPeople, RemainingFoods, RemainingPairs).

Обратите внимание на использование ==/2 здесь, а не объединение =/2.Причина этого в том, что вы хотите, чтобы _ не совпадало с good.Если вы используете объединение, то Prolog успешно объединит переменную _ с атомом good.==/2, с другой стороны, проверяет, действительно ли эти два термина совпадают, и не объединяет их.

...