3 кувшина воды в прологе не работает
Мне нужно решить 3 кувшина с водой, но с небольшим фокусом. Мне не нужно использовать алгоритм, но нужно иметь "функцию", которая позволяет пользователю перемещать литры из кувшина в другой с начальным и конечным состоянием, которое было написано. также им.
Например, он пишет начальное (10,0,0,0,r), и первое состояние составляет 10 литров в первом и ноль в двух других, также он пишет окончательное (0,3,3,3,l) и окончательное Штат имеет 3 литра в двух меньших кувшинах и ноль в первом.
"Перемещение" между кувшинами происходит, когда он пишет "go" (7,3,r), где он двигается на 3 литра вправо (справа налево, форма кувшина больше или меньше) от большего к второму кувшину, -7 это литры, которые остались, и 3 - это литры, которые нужно переместить, а r - направление.
И я написал этот код пролога, но каждое go-состояние ложно. У кого-нибудь есть идеи, почему??
:- 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 ответа
Трудно понять, что ты написал. Если начальное состояние 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
не имеет функции.
Поэтому, пожалуйста, проясните вашу проблему. И, наконец, каковы возможности ваших кувшинов?
РЕДАКТИРОВАТЬ: Ну, после разъяснений в комментариях ниже о правилах, я бы кодировал это следующим образом:
%% 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]
?- ....
Я скопировал ваш код и скомпилировал с 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)).