3 кувшина воды в прологе не работает - PullRequest
1 голос
/ 27 января 2012

Мне нужно решить 3 кувшина с водой, но с небольшой хитростью. Мне не нужно использовать алгоритм, но нужно иметь «функцию», которая позволяет пользователю перемещать литры из кувшина в другой с начальным и конечным состояниемчто это написано и им.

Например, он пишет начальное (10,0,0,0, r), и первое состояние составляет 10 литров в первом и ноль в двух других, также он пишет окончательное (0,3,3,3, l) и конечное состояние имеет 3 литра в двух меньших кувшинах и ноль в первом.

«Движения» между кувшинами происходят, когда он пишет go (7,3, r) где он двигается на 3 литра вправо (справа налево, мы получаем форму кувшина большего или меньшего размера) от большего к второму кувшину, -7 - это оставленные литра, а 3 - литра, которые нужно переместитьr - это направление.

И я написал этот код пролога, но каждое состояние "ложь" есть. У кого-нибудь есть идеи, почему ??

:- 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.

Ответы [ 2 ]

1 голос
/ 30 января 2012

Трудно понять, что вы написали. Если начальное состояние 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) говорит "налейте из 7-кувшина 3 литра воды в кувшин справа от него", но если это так, зачем вам вообще указывать количество ?? Разве это не противоречит обычной спецификации проблемы кувшинов, когда у вас нет возможности измерять, а просто даны возможности кувшинов? Вместо этого это означает «вылейте всю воду из кувшина« 7 »в кувшин» 3 »? Если это так, r не имеет функции.

Поэтому, пожалуйста, проясните вашу проблему. И, наконец, каковы вместимость ваших кувшинов?

EDIT: Ну, после разъяснений в правилах ниже о правилах я бы написал следующее:

%% 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]
?- ....
1 голос
/ 27 января 2012

Я скопировал ваш код и скомпилировал с 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. Вы должны применить все подсказки , которые вы получили с вашим предыдущим вопросом .

Факторизация вашего кода, это поможет вам понять, что происходит: в newstate / 2 9 правил, почти идентичных. Единственные изменения, за исключением ошибок (опять же, строчные идентификаторы, которые являются ошибочно введенными переменными), - это разные константы. Кажется, что состояние / 5 действительно содержит значения, связанные с «ходами». Вы должны разделить их (то есть последние 2 аргумента) и перейти к newstate (который должен стать как newstate (OldState, NumLitres, Direction, NewState)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...