recipe function in prolog

Viewed 276

Say you have recipes in prolog saved as

step(meal name, stepnumber, stepexaplanation, ingredients (list) , utensils). 

So for every meal name you have multiple steps with all the explanations to make the meal. How would you then make a function that calls getStepText(X,Y,Z).? So if you ask:

?- getStepText('pancakes',2,Y). 

It will return the text of the second step for the meal pancakes.

1 Answers
step('pancakes', 1, 'mix butter and sugar in a bowl', [butter, sugar], [bowl]). 
step('pancakes', 2, 'add eggs', [eggs], []). 
step('pancakes', 3, 'mix flour and bakingpowder', [flour, baking_powder], []). 

getStepText(Dish,Num,Text):-
    step(Dish, Num, Text, _, _).

?- getStepText('pancakes',2,Y). 
Y = 'add eggs' ;
false.

If you are using SWI Prolog you can use the inbuild predicate findall/3 to find all of your steps. Don't forget to sort them.

getSteps(X,S):- 
    findall(N,step(X,N,_,_,_),Bag), 
    sort(Bag,S). 

?- getSteps('pancakes',Y). 
Y = [1, 2, 3] ;
false.

If you don't want to use findall/3 you can define a helper predicate getSteps/3. This predicate assumes all steps are incremental and start with 1.

getSteps(X,S):- 
    getSteps(X,S,1).

getSteps(X, [], N):-
    \+ step(X, N, _, _, _). 
getSteps(X, [N|T], N):-
    step(X, N, _, _, _),
    NN is N+1,
    getSteps(X, T, NN).

?- getSteps('pancakes',Y). 
Y = [1, 2, 3] ;
false.

Explanation: you basically run a counter N from 1 (set when calling) until you can't find any step with the current number N. The first rule tests for the end: if you don't have a step for the current N "return" the empty list [].

Otherwise when you find a step with the number N, try to find the steplist T for the next value NN (which is N+1) and - once found - put N on top of the list T.

Related