I'm new to Prolog and I'm going through some trouble to understand what's wrong with my code.
I'm trying to make a food recommender. Basically, the user enters whether they want breakfast, lunch or dessert and a list of their tastes. The program then counts the number of matches between their tastes and the characteristics of every food and returns the food with the most matches.
I'm using recursion to go through the list of food and everything works as intended until it reaches the end with the empty list of food and then starts to fill it again, returning to the initial state of the problem. I'm not understanding why is the program doing this and I can't find a solution.
recommend(breakfast, Tastes, Result) :-
findall(Breakfast, breakfast(Breakfast), Breakfasts),
getBestMatch(Breakfasts, Tastes, Result, -1).
recommend(lunch, Tastes, Result) :-
findall(Lunch, lunch(Lunch), Lunches),
getBestMatch(Lunches, Tastes, Result, -1).
recommend(dessert, Tastes, Result) :-
findall(Dessert, dessert(Dessert), Desserts),
getBestMatch(Desserts, Tastes, Result, -1).
% Recursive predicate. Goes through the list of food and calls the matches predicate to count the
% matches and compares it to the current best match. When the food list is empty, it should stop.
% Result should be the name of the best matching food. I think here's where the error is.
getBestMatch([], _, _, _).
getBestMatch([H|T], Tastes, Result, BestMatch) :-
matches(H, Tastes, Matches),
Matches > BestMatch
-> getBestMatch(T, Tastes, H, Matches)
; getBestMatch(T, Tastes, Result, BestMatch).
% Counts the number of matches between the food's characteristics and the tastes.
matches(Food, Tastes, Matches) :-
characteristics(Food, Characteristics),
intersection(Tastes, Characteristics, MatchList),
length(MatchList, Matches).
% These are some examples of how I have declared the food and its characteristics
lunch(lasagna).
lunch(pizza).
dessert(cake).
characteristics(lasagna, [warm, salty, pasta, italian, meat]).
characteristics(pizza, [warm, salty, cheese, italian]).
characteristics(cake, [cold, sweet, vegetarian]).
And here's a fragment of the trace.
Call: (12) getBestMatch([pizza], [italian, cheese], lasagna, 1) ? creep
Call: (13) matches(pizza, [italian, cheese], _4220) ? creep
Call: (14) characteristics(pizza, _4262) ? creep
Exit: (14) characteristics(pizza, [warm, salty, cheese, italian]) ? creep
Call: (14) lists:intersection([italian, cheese], [warm, salty, cheese, italian], _4376) ? creep
Exit: (14) lists:intersection([italian, cheese], [warm, salty, cheese, italian], [italian, cheese]) ? creep
Call: (14) length([italian, cheese], _4474) ? creep
Exit: (14) length([italian, cheese], 2) ? creep
Exit: (13) matches(pizza, [italian, cheese], 2) ? creep
Call: (13) 2>1 ? creep
Exit: (13) 2>1 ? creep
Call: (13) getBestMatch([], [italian, cheese], pizza, 2) ? creep
Exit: (13) getBestMatch([], [italian, cheese], pizza, 2) ? creep
Exit: (12) getBestMatch([pizza], [italian, cheese], lasagna, 1) ? creep
Exit: (11) getBestMatch([lasagna, pizza], [italian, cheese], _2882, -1) ? creep
Exit: (10) recommend(lunch, [italian, cheese], _2882) ? creep
true.
I've tried looking through similar questions but none of them works for me.
PS: Sorry if this question or the code sample is too large, this was my first question here and I couldn't figure out how to simplify it more.