Swi Prolog - 使用列表实现水壶程序
Swi Prolog - Implementing water Jug Program with Lists
抱歉之前,刚开始发帖,试图让这个列表递归通过每个操作,保持它的访问列表项,然后如果元素不在该状态的列表中则检查递归将改为。我需要找出为什么这没有按预期工作,它似乎得到结果 7,0、0,0、0,4 和 7,4 并且检查似乎在一个 [=13= 中显示相同的 4 个结果] 这个程序,随机吐出其中一个,是动作顺序错误,因为我知道你必须从最困难的条件开始匹配,目标是使用调用解决(状态(0,0))来填充它。然后你应该在最后的调用中得到 5 in the jug,并打印出显示它使用的路径的列表,然后找到另一个解决方案,因为在 7L jug 中有 5L 的地方只能有两个。
action(state(L,R), P, state(7,R)) :-
L < 4,
not(lists:member(state(7,R),P)),
print(state(7,R)).
action(state(L,R), P, state(L,4)) :-
R < 4,
not(lists:member(state(L,4),P)),
print(state(L,4)).
action(state(L,R), P, state(0,R)) :-
L > 0,
not(lists:member(state(0,R),P)),
print(state(0,R)).
action(state(L,R), P, state(L,0)) :-
R > 0,
not(lists:member(state(L,0),P)),
print(state(L,0)).
action(state(L,R), P, state(7,C)) :-
not(lists:member(state(7,C),P)),
C is L + R -7,
C > 7,
print(state(7,C)).
action(state(L,R), P, state(C,4)) :-
not(lists:member(state(C,4),P)),
C is L + R -4,
C > 4,
print(state(C,4)).
action(state(L,R), P, state(0,C)) :-
not(lists:member(state(0,C),P)),
C is L + R,
C @=< 4,
print(state(0,C)).
action(state(L,R), P, state(C,0)) :-
not(lists:member(state(C,0),P)),
C is L + R,
C @=< 7,
print(state(C,0)).
solve(X) :-
reachedgoal(X,[],A).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,P,State2),
not(lists:member(State2,P)),
reachedgoal(State2,[State1|P],L).
有一些小的逻辑错误,在计算值之前检查重复操作没有意义。
solve(X) :-
reachedgoal(X,[],_).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,P,State2),
\+ member(State2,P),
reachedgoal(State2,[State1|P],L).
action(state(_L,R),P,state(7,R)) :- % fill left jug (7l)
\+ member(state(7,R),P),
print(state(7,R)),nl.
action(state(L,_R),P,state(L,4)) :- % fill right jug (4l)
\+ member(state(L,4),P),
print(state(L,4)),nl.
action(state(_L,R),P,state(0,R)) :- % empty left jug
\+ member(state(0,R),P),
print(state(0,R)),nl.
action(state(L,_R),P,state(L,0)) :- % empty right jug
\+ member(state(L,0),P),
print(state(L,0)),nl.
action(state(L,R),P,state(7,C)) :- % from right jug to left jug until left full
C is L + R - 7,
C > 0, C =< 4,
\+ member(state(7,C),P),
print(state(7,C)),nl.
action(state(L,R),P,state(C,4)) :- % from left jug to right jug until right full
C is L + R - 4,
C > 0, C =< 7,
\+ member(state(C,4),P),
print(state(C,4)),nl.
action(state(L,R),P,state(0,C)) :- % from left jug to right jug until left empty
C is L + R,
C =< 4,
\+ member(state(0,C),P),
print(state(0,C)),nl.
action(state(L,R),P,state(C,0)) :- % from right jug to left jug until right empty
C is L + R,
C =< 7,
\+ member(state(C,0),P),
print(state(C,0)),nl.
这会产生:
| ?- solve(state(0,0)).
state(7,0)
state(7,0)
state(7,4)
state(7,4)
state(0,4)
state(0,4)
state(4,0)
state(4,4)
state(4,4)
state(7,1)
state(7,1)
state(0,1)
state(0,1)
state(1,0)
state(1,4)
state(1,4)
state(5,0)
yes
重复是因为操作中的条件不足(见下文)。
检查每个动作中的重复状态是浪费的,因为您也在 reachedgoal/3
中检查它,并且在最后打印列表会更好更干净。
solve :-
solve(state(0,0),RevStates), reverse(RevStates,States),
write(States), nl.
solve(X,States) :-
reachedgoal(X,[],States).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,State2),
\+ member(State2,P),
reachedgoal(State2,[State1|P],L).
action(state(L,R),state(7,R)) :- % fill left jug (7l)
L < 7.
action(state(L,R),state(L,4)) :- % fill right jug (4l)
R < 4.
action(state(L,R),state(0,R)) :- % empty left jug
L > 0.
action(state(L,R),state(L,0)) :- % empty right jug
R > 0.
action(state(L,R),state(7,C)) :- % from right jug to left jug until left full
R > 0, L < 7,
C is L + R - 7, C > 0, C =< 4.
action(state(L,R),state(C,4)) :- % from left jug to right jug until right full
L > 0, R < 4,
C is L + R - 4, C > 0, C =< 7.
action(state(L,R),state(0,C)) :- % from left jug to right jug until left empty
L > 0, C is L + R, C =< 4.
action(state(L,R),state(C,0)) :- % from right jug to left jug until right empty
R > 0, C is L + R, C =< 7.
现在没有重复:
| ?- solve.
[state(0,0),state(7,0),state(7,4),state(0,4),state(4,0),state(4,4),state(7,1),state(0,1),state(1,0),state(1,4)]
yes
抱歉之前,刚开始发帖,试图让这个列表递归通过每个操作,保持它的访问列表项,然后如果元素不在该状态的列表中则检查递归将改为。我需要找出为什么这没有按预期工作,它似乎得到结果 7,0、0,0、0,4 和 7,4 并且检查似乎在一个 [=13= 中显示相同的 4 个结果] 这个程序,随机吐出其中一个,是动作顺序错误,因为我知道你必须从最困难的条件开始匹配,目标是使用调用解决(状态(0,0))来填充它。然后你应该在最后的调用中得到 5 in the jug,并打印出显示它使用的路径的列表,然后找到另一个解决方案,因为在 7L jug 中有 5L 的地方只能有两个。
action(state(L,R), P, state(7,R)) :-
L < 4,
not(lists:member(state(7,R),P)),
print(state(7,R)).
action(state(L,R), P, state(L,4)) :-
R < 4,
not(lists:member(state(L,4),P)),
print(state(L,4)).
action(state(L,R), P, state(0,R)) :-
L > 0,
not(lists:member(state(0,R),P)),
print(state(0,R)).
action(state(L,R), P, state(L,0)) :-
R > 0,
not(lists:member(state(L,0),P)),
print(state(L,0)).
action(state(L,R), P, state(7,C)) :-
not(lists:member(state(7,C),P)),
C is L + R -7,
C > 7,
print(state(7,C)).
action(state(L,R), P, state(C,4)) :-
not(lists:member(state(C,4),P)),
C is L + R -4,
C > 4,
print(state(C,4)).
action(state(L,R), P, state(0,C)) :-
not(lists:member(state(0,C),P)),
C is L + R,
C @=< 4,
print(state(0,C)).
action(state(L,R), P, state(C,0)) :-
not(lists:member(state(C,0),P)),
C is L + R,
C @=< 7,
print(state(C,0)).
solve(X) :-
reachedgoal(X,[],A).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,P,State2),
not(lists:member(State2,P)),
reachedgoal(State2,[State1|P],L).
有一些小的逻辑错误,在计算值之前检查重复操作没有意义。
solve(X) :-
reachedgoal(X,[],_).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,P,State2),
\+ member(State2,P),
reachedgoal(State2,[State1|P],L).
action(state(_L,R),P,state(7,R)) :- % fill left jug (7l)
\+ member(state(7,R),P),
print(state(7,R)),nl.
action(state(L,_R),P,state(L,4)) :- % fill right jug (4l)
\+ member(state(L,4),P),
print(state(L,4)),nl.
action(state(_L,R),P,state(0,R)) :- % empty left jug
\+ member(state(0,R),P),
print(state(0,R)),nl.
action(state(L,_R),P,state(L,0)) :- % empty right jug
\+ member(state(L,0),P),
print(state(L,0)),nl.
action(state(L,R),P,state(7,C)) :- % from right jug to left jug until left full
C is L + R - 7,
C > 0, C =< 4,
\+ member(state(7,C),P),
print(state(7,C)),nl.
action(state(L,R),P,state(C,4)) :- % from left jug to right jug until right full
C is L + R - 4,
C > 0, C =< 7,
\+ member(state(C,4),P),
print(state(C,4)),nl.
action(state(L,R),P,state(0,C)) :- % from left jug to right jug until left empty
C is L + R,
C =< 4,
\+ member(state(0,C),P),
print(state(0,C)),nl.
action(state(L,R),P,state(C,0)) :- % from right jug to left jug until right empty
C is L + R,
C =< 7,
\+ member(state(C,0),P),
print(state(C,0)),nl.
这会产生:
| ?- solve(state(0,0)).
state(7,0)
state(7,0)
state(7,4)
state(7,4)
state(0,4)
state(0,4)
state(4,0)
state(4,4)
state(4,4)
state(7,1)
state(7,1)
state(0,1)
state(0,1)
state(1,0)
state(1,4)
state(1,4)
state(5,0)
yes
重复是因为操作中的条件不足(见下文)。
检查每个动作中的重复状态是浪费的,因为您也在 reachedgoal/3
中检查它,并且在最后打印列表会更好更干净。
solve :-
solve(state(0,0),RevStates), reverse(RevStates,States),
write(States), nl.
solve(X,States) :-
reachedgoal(X,[],States).
reachedgoal(state(5,_),L,L).
reachedgoal(State1,P,L) :-
action(State1,State2),
\+ member(State2,P),
reachedgoal(State2,[State1|P],L).
action(state(L,R),state(7,R)) :- % fill left jug (7l)
L < 7.
action(state(L,R),state(L,4)) :- % fill right jug (4l)
R < 4.
action(state(L,R),state(0,R)) :- % empty left jug
L > 0.
action(state(L,R),state(L,0)) :- % empty right jug
R > 0.
action(state(L,R),state(7,C)) :- % from right jug to left jug until left full
R > 0, L < 7,
C is L + R - 7, C > 0, C =< 4.
action(state(L,R),state(C,4)) :- % from left jug to right jug until right full
L > 0, R < 4,
C is L + R - 4, C > 0, C =< 7.
action(state(L,R),state(0,C)) :- % from left jug to right jug until left empty
L > 0, C is L + R, C =< 4.
action(state(L,R),state(C,0)) :- % from right jug to left jug until right empty
R > 0, C is L + R, C =< 7.
现在没有重复:
| ?- solve.
[state(0,0),state(7,0),state(7,4),state(0,4),state(4,0),state(4,4),state(7,1),state(0,1),state(1,0),state(1,4)]
yes