'How can I find the input from a list which yields the maximum result from some query in SWI-Prolog?
I'm just picking up Prolog now, so I'm unfamiliar with the normal way of doing most things.
Essentially I have a rule which gives a value from an input:
ScoreFromInput(Input, Score) :- ...
And I have a list of inputs, which are just numbers. I'm having trouble figuring out how to find the input which yields the maximum score.
This is what I have right now, but I think it recurses infinitely:
bestInput(BestInput) :-
%#Bind the list of valid inputs
legalInputs(ValidInputs),
%# -1000 is a dummy score, it should get replaced on the first call to bestInputHelper
bestInputHelper(ValidInputs,-1000,BestInput).
%#I think this rule should work if the first input in the list is not the best one
bestInputHelper([Input|RestOfInputs],BestScore,BestInput):-
bestInputHelper(RestOfInputs,RestBestScore,BestInput),
ScoreFromInput(Input,BestScore),
RestBestScore > BestScore.
%#And this one if it is the best input
bestInputHelper([Input|RestOfInputs],BestScore,Input):-
bestInputHelper(RestOfInputs,RestBestScore,_RestBestInput),
ScoreFromInput(Input,BestScore),
RestBestScore =< BestScore.
This is what I have so far, but I imagine there is a much more straightforward way of doing it. Any help is appreciated! Thanks!
Solution 1:[1]
Despite Chris's lack of familiarity with Prolog, the approach he outlined may be a more efficient way of finding the input with the maximum score than mat's. Instead of doing a quadratic number of comparisons, an approach like Chris's is possible that linearly scans the possible inputs.
Here maxScoreOfList/3 will return the best item Z and the best score B for a list of valid inputs as the third argument. The predicate will fail on an empty list.
maxScoreOfList(Z,B,[H|T]) :-
scoreFromInput(H,S),
maxScoreOfListAux(Z,B,H,S,T).
A "helper" function is needed as follows, which illustrates the "trick" of adding some extra arguments so that when the end of the input list is reached, the outputs Z and B can be bound to the best item and score found "so far":
maxScoreOfListAux(Z,B,Z,B,[ ]).
maxScoreOfListAux(Z,B,X,S,[H|T]) :-
scoreFromInput(H,Q),
( S >= Q
-> ( Y = X, R = S )
; ( Y = H, R = Q )
),
maxScoreOfListAux(Z,B,Y,R,T).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | hardmath |
