prolog中的水壶

时间:2011-10-03 21:39:08

标签: prolog water-jug-problem

这是一个水壶问题。较大的水桶容纳5个,较小的水桶容纳3个。我想在较大的桶中得到4个。

问题是,当我跑步时,我无法得到任何答案,它会产生错误。它似乎不是一个明显的错误,算法简单直接。

有人可以帮我找到它有什么问题吗?

check_safe(X,Y):- X>=0,X=<3,Y>=0,Y=<5.

%empty the 3 bucket

move(state(X,Y),state(0,Y)):- X>0,check_safe(0,Y).

%empty the 5 bucket

move(state(X,Y),state(X,0)):- Y>0,check_safe(X,0).

%fill the 3 bucket

move(state(X,Y), state(3,Y)):- X<3, X>=0,check_safe(3,Y).

%fill the 5 bucket

move(state(X,Y),state(X,5)):- Y>=0, Y<5,check_safe(X,5).

%transfer from 3 to 5 until the larger bucket is full

move(state(X,Y),state(NewX,5)):- X+Y>= 5, X>0,Y>=0, NewX=X+Y-5,check_safe(NewX,5).

%transfer from 3 to 5 until the smaller bucket is empty

move(state(X,Y),state(0,NewY)):- X+Y<5, X>0,Y>=0, NewY=X+Y,check_safe(0,NewY).

%transfer from 5 to 3 until the smaller is full

move(state(X,Y),state(3,NewY)):- Y>0,X>=0,X+Y>=5, NewY=Y+X-3,check_safe(3,NewY).

%transfer from 5 to 3 until the larger is empty

move(state(X,Y),state(NewX,0)):-Y>0,X>=0, X+Y<5, NewX=Y+X,check_safe(NewX,0).


path(X,X,_,[X]).
path(X,Y,BeenStates,Path):-
    move(X,Somewhere),not(member(Somewhere,BeenStates)),
    path(Somewhere,Y,[Somewhere|BeenStates],Path2), Path = [X|Path2].


puzzle:- path(state(0,0),state(0,5),[state(0,0)],PathList),X>=0,X=<5,
    writeOut(PathList).

% Here's an easy little predicate for printing a list.
writeOut([]).
writeOut([H|T]):-write(H),nl, writeOut(T).

2 个答案:

答案 0 :(得分:5)

你没有在作业中使用“是”。

您的puzzle\0谓词有两个未绑定的变量:X&amp; Y

你的path\4谓词有问题。

试试这些:

path([state(X, 4)|Xs],[state(X, 4)|Xs]):- !.
path([X|Xs],Rs):-
    move(X,Y),not(member(Y,[X|Xs])),
    path([Y,X|Xs],Rs).

puzzle:- path([state(0,0)],PathList),
    write(PathList), nl, fail.

以下是我对此问题的解决方案:

move(s(X,Y),s(Z,5)) :- Z is X - (5 - Y), Z >= 0.
move(s(X,Y),s(Z,0)) :- Z is X + Y, Z =< 3.
move(s(X,Y),s(3,Z)) :- Z is Y - (3 - X), Z >=0.
move(s(X,Y),s(0,Z)) :- Z is X + Y, Z =< 5.

move(s(0,Y),s(3,Y)).
move(s(X,0),s(X,5)).
move(s(X,Y),s(X,0)) :- Y > 0.
move(s(X,Y),s(0,Y)) :- X > 0.

moves(Xs) :- moves([s(0,0)],Xs).
moves([s(X0,Y0)|T], [s(X1,4),s(X0,Y0)|T])
    :- move(s(X0,Y0),s(X1,4)), !.
moves([s(X0,Y0)|T],Xs) :-
    move(s(X0,Y0),s(X1,Y1)), 
    not(member(s(X1,Y1),[s(X0,Y0)|T])),
    moves([s(X1,Y1),s(X0,Y0)|T],Xs).

?- moves(Xs), write(Xs), nl, fail.

我得到了这些解决方案:

[s(0,4),s(3,1),s(0,1),s(1,0),s(1,5),s(3,3),s(0,3),s(3,0),s(0,0)]
[s(3,4),s(2,5),s(2,0),s(0,2),s(3,2),s(0,5),s(1,5),s(3,3),s(0,3),s(3,0),s(0,0)]
[s(3,4),s(2,5),s(2,0),s(0,2),s(3,2),s(0,5),s(3,5),s(3,0),s(0,0)]
[s(0,4),s(3,1),s(0,1),s(1,0),s(1,5),s(3,3),s(0,3),s(3,0),s(3,2),s(0,5),s(0,0)]
[s(3,4),s(2,5),s(2,0),s(0,2),s(3,2),s(0,5),s(0,0)]
[s(0,4),s(3,1),s(0,1),s(1,0),s(1,5),s(3,3),s(0,3),s(3,0),s(3,5),s(0,5),s(0,0)]

显然,倒数第二,是最短的,是最好的。

答案 1 :(得分:0)

**

  

水壶问题:

**

%database
    visited_state(integer,integer).

%predicates
    state(integer,integer).

%clauses
    state(2,0).

state(X,Y):- X < 4,
    not(visited_state(4,Y)),
    assert(visited_state(X,Y)),
    write("Fill the 4-Gallon Jug: (",X,",",Y,") --> (", 4,",",Y,")\n"),
    state(4,Y).

state(X,Y):- Y < 3,
    not(visited_state(X,3)),
    assert(visited_state(X,Y)),
    write("Fill the 3-Gallon Jug: (", X,",",Y,") --> (", X,",",3,")\n"),
    state(X,3).

state(X,Y):- X > 0,
    not(visited_state(0,Y)),
    assert(visited_state(X,Y)),
    write("Empty the 4-Gallon jug on ground: (", X,",",Y,") --> (", 0,",",Y,")\n"),
    state(0,Y).

state(X,Y):- Y > 0,
    not(visited_state(X,0)),
    assert(visited_state(X,0)),
    write("Empty the 3-Gallon jug on ground: (", X,",",Y,") --> (", X,",",0,")\n"),
    state(X,0).

state(X,Y):- X + Y >= 4,
    Y > 0,
    NEW_Y = Y - (4 - X),
    not(visited_state(4,NEW_Y)),
    assert(visited_state(X,Y)),
    write("Pour water from 3-Gallon jug to 4-gallon until it is full: (", X,",",Y,") --> (", 4,",",NEW_Y,")\n"),
    state(4,NEW_Y).


state(X,Y):- X + Y >=3,
    X > 0,
    NEW_X = X - (3 - Y),
    not(visited_state(X,3)),
    assert(visited_state(X,Y)),
    write("Pour water from 4-Gallon jug to 3-gallon until it is full: (", X,",",Y,") --> (", NEW_X,",",3,")\n"),
    state(NEW_X,3).

state(X,Y):- X + Y>=4,
    Y > 0,
    NEW_X = X + Y,
    not(visited_state(NEW_X,0)),
    assert(visited_state(X,Y)),
    write("Pour all the water from 3-Gallon jug to 4-gallon: (", X,",",Y,") --> (", NEW_X,",",0,")\n"),
    state(NEW_X,0).

state(X,Y):- X+Y >=3,
    X > 0,
    NEW_Y = X + Y,
    not(visited_state(0,NEW_Y)),
    assert(visited_state(X,Y)),
    write("Pour all the water from 4-Gallon jug to 3-gallon: (", X,",",Y,") --> (", 0,",",NEW_Y,")\n"),
    state(0,NEW_Y).

state(0,2):- not(visited_state(2,0)),
    assert(visited_state(0,2)),
    write("Pour 2 gallons from 3-Gallon jug to 4-gallon: (", 0,",",2,") --> (", 2,",",0,")\n"),
    state(2,0).

state(2,Y):- not(visited_state(0,Y)),
    assert(visited_state(2,Y)),
    write("Empty 2 gallons from 4-Gallon jug on the ground: (", 2,",",Y,") --> (", 0,",",Y,")\n"),
    state(0,Y).

goal:-
makewindow(1,2,3,"4-3 Water Jug Problem",0,0,25,80),
state(0,0).

**

> Output:
state(2,5).

**