1

我有 3 壶水的问题要解决,但有一个小技巧。我不必使用算法,而是要有一个“功能”,允许用户将升从一个壶移动到另一个壶,其初始和最终状态是它所写的也由他。

例如,他写了 initial(10,0,0,0,r) 并且第一个状态是第一个是 10 升,其他两个是零,他还写了 final(0,3,3,3,l) 和 final state 在两个较小的罐子里有 3 升,在第一个罐子里是零。

壶之间的“移动”发生在他写 go(7,3,r) 时,他向右移动 3 升(从右到左,壶的形状从大到小)从大到第二个壶,-7是剩下的升,3 是要移动的升,r 是方向-。

我已经写了这个序言代码,但是每个 go-state 都是错误的..有人知道为什么吗?

:- dynamic go/3.
:- dynamic cur_state/1,init/5.
:- dynamic end_state/1, final/5.

cur_state(State):-State = state(10,0,0,7,l).
end_state(State):-State = state(0,3,3,0,r).

pour(state(D1,D2,D3,N,l),move(D,C,r),state(D,C,D3,N,r)) :-
        D is D1-N,
        C is D2+N.
pour(state(D1,D2,D3,N,r),move(D,C,l),state(D,C,D3,N,l)) :-
        D is D1-N,
        C is D2.
pour(state(D1,D2,D3,N,l),move(D,C,r),state(D,D2,C,N,r)) :-
        D is D1-N,
        C is D3+N.
pour(state(D1,D2,D3,N,l),move(D,C,r),state(D1,D,C,N,r)) :-
        D is D2-N,
        C is D3+N.
pour(state(D1,D2,D3,N,r),move(D,C,l),state(D1,D,C,N,l)) :-
        D is D2-N,
        C is D1+N.
pour(state(D1,D2,D3,N,r),move(D,C,l),state(D1,D,c,N,l)) :-
        D is D2-N,
        C is D3.
pour(state(D1,D2,D3,N,l),move(D,C,r),state(C,D2,D,N,r)) :-
        D is D3-N,
        C is D1.
pour(state(D1,D2,D3,N,r),move(D,C,l),state(D1,C,D,N,l)) :-
        D is D3-N,
        C is D2+N.
pour(state(D1,D2,D3,N,r),move(D,C,l),state(C,D2,D,N,l)) :-
        D is D3-N,
        C is D1+N.

carry(7,0).
carry(3,0).
carry(10,0).
carry(4,0).
carry(7,3).

legal(10,X,Y):-X+Y=<10.
legal(X,Y,Z):-X+Y+Z=<10.
legal(X,7,Y):-X+Y=<3.
legal(X,Y,3):-X+Y=<7.

newstate(state(D1,D2,D3,N,l),state(D11,D22,D33,N1,r)):-
        carry(M,C),
        M=<7,C=<3,
        D22 is D2+N,
        D11 is D1-N,
    D3 is D33,
    N1 is N,
        D2=<7,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,r),state(D11,D22,D33,N1,l)):-
        carry(M,C),
        M=<10,C=<100,
        D11 is D1-N,
    D22 is D2,
    D33 is D3,
        D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,l),state(D11,D22,D33,N1,r)):-
        carry(M,C),
        M=<10,C<3,
        D11 is D1-N,
        D33 is D3+N,
    D22 is D2,
        D1=<10,D3=<3,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,r),state(D11,D22,D33,N1,l)):-
        carry(M,C),
        M=<7,C=<3,
        D22 is D2-N,
        D33 is D1+N,
        D11 is D1,
        D2=<7,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,l),state(D11,D22,D33,N1,r)):-
        carry(M,C),
        M=<7,C=0,
        D22 is D2-N,
        D33 is D3+N,
        D11 is D1,
    D2=<7,D3=<3,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,r),state(D11,D22,D33,N1,l)):-
        carry(M,C),
        M=<7,C=<100,
        D22 is D2-N,
    D33 is D3,
    D11 is D1,    
    D2=<7,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,r),state(D11,D22,D33,N1,l)):-
        carry(M,C),
        M=<3,C=<7,
        D22 is D2+N,
        D33 is D3-N,
        D11 is D1,
    D3=<3,D2=<7,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,r),state(D11,D22,D33,N1,l)):-
        carry(M,C),
        M=<3,C=<100,
        D11 is D1+N,
        D33 is D3-N,
        D22 is D2,
    D3=<3,D1=<10,
    legal(D1,D2,D3).

newstate(state(D1,D2,D3,N,l),state(D11,D22,D33,N1,r)):-
        carry(M,C),
        M=<3,C=<100,
        D33 is D3-N,
        D22 is D2,
    D11 is D1,  
    D3=<3,
    legal(D1,D2,D3).


eisodos(_):- cur_state(State),write(State),nl.

init(S1,S2,S3,S4,S5):-assert(cur_state(State):-State =                 state(S1,S2,S3,S4,S5)),write('Arxikh:'),
write(state(S1,S2,S3,S4,S5)),retractall(init(S1,S2,S3,S4,S5)),nl.

final(S1,S2,S3,S4,S5):-assert(end_state(State):-State =  state(S1,S2,S3,S4,S5)),write('Telikh:'),
write(state(S1,S2,S3,S4,S5)),retractall(final(S1,S2,S3,S4,S5)),nl.

go(Move1,Move2,Move3):-cur_state(State),newstate(State,NextState),
    pour(State,move(Move1,Move2,Move3), NextState),
    retractall(cur_state(State):-State = state(_,_,_,_,_)),asserta(cur_state(NextState)),
    ((end_state(NextState),write('Bravo!!!!')) ;(write(' ---*Eiste sthn katastash --- :'),write(NextState))),nl.
4

2 回答 2

1

很难理解你写的东西。如果初始状态是ini(10,0,0,0,r),最后两个参数是什么?你只有三个罐子,不是吗?为什么最终状态是fin(0,3,3,3,r)3最后一个是什么r意思??

你有三个水壶,所以你的状态只有三个值:s(A,B,C). 您似乎希望在旅途中动态地重新定义它。美好的。您的go(...)谓词将调用retract/assert并且必须处理逻辑。如果您希望您的用户能够说“向右倒”,为什么还要坚持让他写下水壶中还剩多少水?这似乎是错误的,您的系统必须计算该值,并用它更新您当前的动态数据库。另外,从哪里“向右倾” ??在我看来,您的go(7,3,r)意思是“将 3 升水从 '7' 壶中倒入它右侧的壶中”,但如果是这样,你为什么需要指定数量?这不是与水壶问题的通常规范相反吗有任何测量能力,而是被赋予了水壶的容量吗?它是不是意味着“将你能从'7'壶中的所有水倒入'3'壶中”?如果是,r则没有任何功能。

所以请澄清你的问题。最后,你水壶的容量是多少?

编辑:好吧,在下面关于规则的评论中澄清之后,我将其编码如下:

%% to be called: initial(10-10,7-0,3-0).
%% to be called: final(10-0,7-3,3-3).

initial(C1-W1,C2-W2,C3-W3):- % capacity-water_content
  retractall( jug(_,_) ), 
  asserta( jug(C1,W1) ),
  asserta( jug(C2,W2) ),
  asserta( jug(C3,W3) ).

final(C1-W1,C2-W2,C3-W3):- 
  retractall( end_jug(_,_) ), 
  asserta( end_jug(C1,W1) ),
  asserta( end_jug(C2,W2) ),
  asserta( end_jug(C3,W3) ).

jugsState(L) :- findall(X-W, jug(X,W), L). % see the state

go(Cfrom,0):-  !, % pour out the water
  retract( jug(Cfrom,_) ), 
  asserta( jug(Cfrom,0) ),
  is_final_state.

go(Cfrom,Cto):-
  retract( jug(Cfrom,Wfrom) ),
  retract( jug(Cto,Wto) ),
  Space is Cto-Wto,
  (  Wfrom >= Space
  -> Wleft is Wfrom - Space,
     asserta( jug(Cfrom,Wleft) ),
     asserta( jug(Cto,Cto) )
  ;  Wnew is Wto+Wfrom,
     asserta( jug(Cfrom,0) ),
     asserta( jug(Cto,Wnew) ) ),
  is_final_state.

is_final_state :- true.

现在剩下的就是定义is_final_state哪个会检查jug事实,看看是否达到了最终状态,如果是就打印出祝贺信息,然后true总是返回。或类似的东西。样品运行可以是例如

?- initial(10-10,7-0,3-0).
?- final(10-0,7-3,3-3).
?- go(10,7).
?- go(7,3).
?- go(7,0).
?- jugsState(X).
X = [7-0, 3-3, 10-3]
?- ....
于 2012-01-30T19:24:15.430 回答
1

我复制了你的代码并用 SWI-Prolog 编译,我得到了这些消息:

?- Warning: /home/carlo/prolog/jug1.pl:20:
    Singleton variables: [D3]
Warning: /home/carlo/prolog/jug1.pl:57:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:66:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:75:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:84:
    Singleton variables: [N1]
Warning: /home/carlo/prolog/jug1.pl:93:
    Singleton variables: [N1]
ERROR: /home/carlo/prolog/jug1.pl:102:
    evaluable `n' does not exist
ERROR: /home/carlo/prolog/jug1.pl:111:
    evaluable `n' does not exist
ERROR: /home/carlo/prolog/jug1.pl:120:
    evaluable `n' does not exist
% /home/carlo/prolog/jug1.pl compiled 0,01 sec, 32 clauses

肤浅的代码检查揭示了其他缺陷,例如第 23 行的小写“c”。您应该应用您在上一个问题中获得的所有提示

分解你的代码,这将帮助你理解发生了什么:newstate/2 有 9 条规则,几乎相同。唯一的变化,除了错误(同样是拼写错误的变量的小写标识符),是不同的常量。似乎 state/5 确实拥有与“移动”相关的值。您应该分离这些(即最后 2 个参数)并传递给 newstate(应该变成 newstate(OldState, NumLitres, Direction, NewState))。

于 2012-01-27T08:44:16.633 回答