2

This is my first time here and I know there are already posts about this but don't seem to be the same way I am suppose to code it. I just keep getting the answer false.

I enter : solve(0,0). Result is false.

Code.

solve(5,_).
solve(X,Y):- X < 7,
   \+ member((7,Y),L),  
   concat(E,[(X,Y)],L),
   write('Fill 7 litre jug from tap.\n'),
   solve(7,Y).
solve(X,Y):- Y < 4,
   \+ member((X,4),L),
   concat(E,[(X,Y)],L),
   write('Fill 4 litre jug from tap.\n'),
   solve(X,4).
solve(X,Y):- X+Y >= 7,
   Y > 0,
   Z is Y - (7 - X),
   \+ member((7,Z),L),
   concat(E,[(X,Z)],L),
   write('Fill 7 litre jug with 4 litre jug.\n'),
   solve(7,Z).
solve(X,Y):- X+Y >= 4,
   X > 0,
   Z is X - (4 - Y),
   \+ member((Z,4),L),
   concat(E,[(Z,Y)],L),
   write('Fill 4 litre jug with 7 litre jug.\n'),
   solve(Z,4).
solve(X,Y):- X+Y < 4,
   Y > 0,
   Z is X + Y,
   \+ member((Z,0),L),
   concat(E,[(Z,Y)],L),
   write('Empty 4 litre jug into 7 litre jug.\n'),
   solve(Z,0).
solve(X,Y):- X+Y < 7,
   X > 0,
   Z is X+Y,
   \+ member((0,Z),L),
   concat(E,[(X,Z)],L),
   write('Empty 7 litre jug into 4 litre jug.\n'),
   solve(0,Z).
solve(X,Y):- X > 0,
   \+ member((0,Y),L),
   concat(E,[(X,Y)],L),
   write('Empty 7 litre jug.\n'),
   solve(0,Y).
solve(X,Y):- Y > 0,
   \+ member((X,0),L),
   concat(E,[(X,Y)],L),
   write('Empty 4 litre jug.\n'),
   solve(X,0).

member(X,[X|L]).
member(X,[L|L]):- 
   member(X,L).

concat([],L,L).
concat([X|A],B,[X|L]):- 
   concat(A,B,L).

Any help is much appreciated. Thanks.

false
  • 10,264
  • 13
  • 101
  • 209
  • 1
    `member(X,[L|L]):- member(X,L).` should probably be `member(X,[Y|L]):-X \= Y, member(X,L).` but SWI prolog has a built in predicate for this, so it's not needed. Also, each time you have this: `solve(X,Y):- X < 7, \+ member((7,Y),L),...`, the list `L` hasn't been instantiated, so `\+ member((7,Y),L)` will always fail. – lurker Nov 25 '13 at 19:31
  • Yea I took that out. Thought I might have needed to override it in a way. Thanks. – JohnMcDonagh22 Nov 25 '13 at 19:34
  • See my other comment about the member check. – lurker Nov 25 '13 at 19:35
  • Yes I seen it. Thanks. I knew the problem was with member I just don't understand how. I'm only fairly new to prolog. I'm trying to check if `(7,Y)` is in the list and if it is not to add it to it. – JohnMcDonagh22 Nov 25 '13 at 19:40
  • Yep, in that case, the list you're checking isn't instantiated, so that part of the logic seems to have a flaw. When it's not instantiated, Prolog will instantiate it for you with something that makes `member` succeed, which means `\+ member` will fail. – lurker Nov 25 '13 at 19:50

1 Answers1

0

I guess you want to do a simple depth first search with loop avoidance. At least I take the member check as a check for an existing loop in the search.

Now your code is for a predicate solve/2 and it reads as follows:

[..]
solve(X,Y):- X+Y < 4,
   Y > 0,
   Z is X + Y,
   \+ member((Z,0),L),
   concat(E,[(Z,Y)],L),
   write('Empty 4 litre jug into 7 litre jug.\n'),
   solve(Z,0).
[..]

The problem is that you don't pass around L and E. You should also get a warning when consulting your Prolog text, it will probably say that E is a singleton variable.

I guess a solution that uses a predicate solve/3 instead a predicate solve/2 will work better. You can pass the already visited states in the third argument. The code would then look as follows:

[..]
solve(X,Y,L):- X+Y < 4,
   Y > 0,
   Z is X + Y,
   \+ member((Z,0),L),
   concat(E,[(Z,Y)],L),
   write('Empty 4 litre jug into 7 litre jug.\n'),
   solve(Z,0,E).
[..]

Hope this helps.

Bye

P.S.: The concat/3 is not necessary, just say E = [(Z,0)|L], or eliminate E equation althogether and just modify the call of solve/3 in the body to solve(Z,0,[(Z,0)|L]).