Prolog works depth first, so that means that it will keep looking to append the list further with toys into the list, and never looks whether the total price already is reached, and thus adding more elements makes no sense.
We can solve this by calculating the price in reverse: we can use the library(clpfd)
and define the relation between the price of the list with the toy and the price without the toy, and add a constraint that the price we are looking for should always be larger than zero if we recurse, like:
:- use_module(library(clpfd)).
calculatePrice([], 0).
calculatePrice([H|T], PHT) :-
PHT #> 0,
toy(H, PH),
PHT #= PT + PH,
calculatePrice(T, PT).
We then obtain for example:
?- calculatePrice(L, 21).
L = [train, train, train, doll] ;
L = [train, train, train, car, car] ;
L = [train, train, doll, train] ;
L = [train, train, car, train, car] ;
L = [train, train, car, car, train] ;
L = [train, doll, train, train] ;
...
?- calculatePrice([train, train], P).
P = 10.
?- calculatePrice(L, P).
L = [],
P = 0 ;
L = [train],
P = 5 ;
L = [train, train],
P = 10 ;
L = [train, train, train],
P = 15 ;
L = [train, train, train, train],
P = 20 ;
L = [train, train, train, train, train],
P = 25
...
The constraint PHT #> 0
is necessary here. You can see PHT
when we query with for example calculatePrice(L, 21)
as the "amount we have left to spend". In case that amount is less than or equal to zero, we can not spent any money anymore, and thus this constraint should fail.