Говоря в общем, звучит так, как будто у вас есть две коллекции фактов, и вы просто хотите определить правило, которое выполняется для каждой уникальной совпадающей пары.
Наборы фактов 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
, с другой стороны, проверяет, действительно ли эти два термина совпадают, и не объединяет их.