Reputation: 1441
I'm trying to solve the following logic puzzle using Prolog:
Determine the first and last name of each driver in the race, the sponsor for each race car, and in what position each driver ended the race.
Using a similar approach as the one found here: http://www.anselm.edu/internet/compsci/faculty_staff/mmalita/HOMEPAGE/logic/aa6.txt
I came up with the following answer:
race(Drivers) :- Drivers = [[howard,_,_,_],[barry,_,_,_],[ryan,_,_,_],
[sydney,_,_,_],[adam,_,_,_],[_,straight,_,_],[_,chariot,_,_],
[_,right,_,_],[_,element,_,_],[_,rafe,_,_],[_,_,flashautomotive,_],
[_,_,crankmotoroil,_],[_,_,napaautoparts,_],[_,_,fleetbodyworks,_],
[_,_,tredcotires,_],[_,_,_,1],[_,_,_,2],[_,_,_,3],[_,_,_,4],[_,_,_,5]],
member([barry,straight,C,D], Drivers), C \= fleetbodyworks,
C \= napaautoparts, D \= 4,
member([howard,_,G,H], Drivers), G \= crankmotoroil, H \= 5, H =:= X - 1,
member([ryan,J,K,_], Drivers), J \= right, K \= napaautoparts,
member([sydney,N,_,P], Drivers), N \= element,
member([Q,chariot,_,T], Drivers), Q \= adam, T = 1,
member([_,right,_,X], Drivers),
member([_, _, _, crankmotoroil, DD], Drivers), DD =:= P + 1,
member([EE,_,napaautoparts,HH], Drivers), HH = 4, EE \= barry,
member([_,_,flashautomotive,LL], Drivers), LL = 3.
When loading this into the Windows SWI-Prolog IDE, it gives no errors, but while debugging it produces this result:
[debug] [1] 12 ?- race(X)
| .
T Call: (13) race(_G4168)
T Fail: (13) race(_G4168)
false.
I'm obviously quite new to Prolog, but I'm wondering what might be causing this to fail and how to fix it (because the debugger as I understand how to use it is not very helpful in this instance). Also, is there a cleaner way to solve similar logic problems?
Upvotes: 1
Views: 283
Reputation: 1441
Here is a working solution based on CapelliC's answer. Using the help of I initially misread part of the problem and forgot some rules, so the errors are fixed and the additional rules are added in this solution.
race(Drivers) :-
Drivers = [
[_,_,_,1],
[_,_,_,2],
[_,_,_,3],
[_,_,_,4],
[_,_,_,5]
],
member([barry,straight,Barrysponsor,Barryplace], Drivers),
member([howard,_,Howardsponsor,Howardplace], Drivers),
member([ryan,Ryanlastname,Ryansponsor,_], Drivers),
member([sydney,Sydneylastname,_,Sydneyplace], Drivers),
member([adam,Adamlastname,Adamsponsor,Adamplace], Drivers),
member([Chariotfirstname,chariot,_,1], Drivers),
member([Rightfirstname,right,Rightsponsor,Rightplace], Drivers),
member([_,element,_,_], Drivers),
member([_,rafe,_,_], Drivers),
member([_,_,crankmotoroil,Crankmotoroilplace], Drivers),
member([Napaautopartsfirstname,_,napaautoparts,4], Drivers),
member([_,_,flashautomotive,3], Drivers),
member([Tredcotiresfirstname,Tredcotireslastname,tredcotires,Tredcotiresplace], Drivers),
member([_,_,fleetbodyworks,_], Drivers),
Barrysponsor \= fleetbodyworks, Barrysponsor \= napaautoparts, Barryplace \= 4,
Howardsponsor \= crankmotoroil, Howardplace \= 5, Howardplace =:= Rightplace + 1,
Ryanlastname \= right, Ryansponsor \= napaautoparts,
Adamplace \= 2, Adamsponsor \= tredcotires,
Adamlastname \= right, Adamlastname \= rafe,
Sydneylastname \= element,
Chariotfirstname \= adam,
Rightfirstname \= adam, Rightplace \= 2, Rightsponsor \= tredcotires,
Crankmotoroilplace =:= Sydneyplace - 1,
Napaautopartsfirstname \= barry,
Tredcotiresfirstname \= adam, Tredcotiresplace \= 2,
Tredcotireslastname \= rafe, Tredcotireslastname \= right.
Upvotes: 0
Reputation: 60004
Your representation of the 'search space' is not correct: in the example you linked, note that only one of the value slots is bound to a constant. Such constant will serve effectively to identify other variable elements after they get their correct place given the constraints.
Moreover, let Prolog applies the 'permutation game' performed by various member/2, and only after check for identities, differences, etc... After you get a solution, you can try to optimize the search process moving up the check, but always after the pertinent slots have been assigned...
A good choice would be to use the numeric field, so you can apply arithmetic in obvious way to enforce constraints. So, I tried to modify your code:
race(Drivers) :-
Drivers = [
[_,_,_,1],
[_,_,_,2],
[_,_,_,3],
[_,_,_,4],
[_,_,_,5]
],
member([barry,straight,C,D], Drivers),
member([howard,_,G,H], Drivers),
member([ryan,J,K,_], Drivers),
member([sydney,N,_,P], Drivers),
member([Q,chariot,_,T], Drivers),
member([_,right,_,X], Drivers),
member([_,_,crankmotoroil,DD], Drivers),
member([EE,_,napaautoparts,HH], Drivers),
member([_,_,flashautomotive,LL], Drivers),
C \= fleetbodyworks, C \= napaautoparts, D \= 4,
G \= crankmotoroil, H \= 5, H =:= X - 1,
J \= right, K \= napaautoparts,
N \= element,
Q \= adam, T = 1,
% DD =:= P + 1,
HH = 4, EE \= barry,
LL = 3.
Note the comment line: if you uncomment it, no solution is available... Commenting out restrictions is the simpler debugging tool available for this simple minded schema.
Upvotes: 2