Во время наводнения 5 супружеских пар оказались отрезанными от суши водой. В их распоряжении была одна лодка, которая могла одновременно вместить только 3-х человек. Каждый супруг был настолько ревнив, что не мог позволить своей супруге находиться в лодке или на любом берегу с другим мужчиной (или мужчинами) в его отсутствие. Найти способ переправить на сушу этих мужчин и их жен в целости и сохранности.
Исходный код программы:
domains
mw=m(integer);w(integer) %zenshina ili muzchina s nomerom
mwlist=mw* %spisok lyudei s nomerami
w=s(string);i(integer)%dlya hraneniya opisaniya proizvedennoi perepravi
wlist=w*
c=c(mwlist,mwlist,mwlist,wlist)%sostoyanie opredelyaetsya kak polozenie sleva,v lodke,sprava,i opisanie preiudushego deistviya
clist=c*
predicates
step(mwlist,mwlist,mwlist,mwlist,mwlist,mwlist,string,wlist).
delete(mw,mwlist,mwlist).
member(mw,mwlist).
vstrechalos(mwlist,clist).
depth(clist,string).
answer(clist,string).
permutation(mwlist,mwlist).
insert(mw,mwlist,mwlist).
zena_bez_muza(mwlist).
opp(string,string).
print(wlist).
clauses
%opisani daleko ne vse vozmoznii hodi, no etih dostatochno dlya resheniya zadachi
step(Sleva,[],Sprava,Sleva1,[w(I)],[m(I)|Sprava],sleva,[s("semeinaya para"),i(I),s("perepravlyaetsya s levogo berega na pravii, zena ostaetsya v lodke")]):-
member(w(I),Sleva),member(m(I),Sleva),
delete(w(I),Sleva,Temp),delete(m(I),Temp,Sleva1).
step(Sleva,[w(I)],Sprava,Sleva1,[w(I),w(J)],Sprava,sprava,[i(I),s("-ya zena perepravlyaetsya s pravogo berega na levii, k nei saditsya "),i(J),s("zena")]):-
member(w(J),Sleva),
delete(w(J),Sleva,Sleva1).
step(Sleva,[w(I)],Sprava,Sleva1,[w(I),m(I)],Sprava,sprava,[i(I),s("-ya zena perepravlyaetsya s pravogo berega na levii, k nei saditsya ee muz")]):-
member(m(I),Sleva),delete(m(I),SLeva,Sleva1).
step(Sleva,[w(I),w(J)],Sprava,Sleva,[w(I)],[w(J)|Sprava],sleva,[i(I),s("-ya i "),i(J),s("-ya zeni perepravlyayustsya s levogo beregan na pravii, "),i(I),s("-ya zena ostaetsya v lodke")]):-
member(m(J),Sprava).
step(Sleva,[w(I),w(J)],Sprava,Sleva,[w(J)],[w(I)|Sprava],sleva,[i(I),s("-ya i "),i(J),s("-ya zeni perepravlyayustsya s levogo beregan na pravii, "),i(J),s("-ya zena ostaetsya v lodke")]):-
member(m(I),Sprava).
step(Sleva,[A,B],Sprava,Sleva,[w(I)],[m(I)|Sprava],sleva,[s("semeinaya para"),i(I),s("perepravlyaetsya s levogo berega na pravii, zena ostaetsya v lodke")]):-
member(w(I),[A,B]),member(m(I),[A,B]),not(zena_bez_muza(Sprava)).
step(Sleva,[A,B],Sprava,Sleva,[],[w(I),m(I)|Sprava],sleva,[s("semeinaya para"),i(I),s("perepravlyaetsya s levogo berega na pravii")]):-
member(w(I),[A,B]),member(m(I),[A,B]),not(zena_bez_muza(Sprava)).
%predicat proverki, est li na beregu zena bez svoego muza
zena_bez_muza(List):-member(w(I),List),not(member(m(I),List)).
%udalenie zadannogo elementa iz spiska
delete(H,[H|Tail],Tail):-!.
delete(X,[H|Tail],[H|NewTail]):-delete(X,Tail,NewTail).
%proverka prinadlezit li zadannii element spisku
member(H,[H|_]).
member(H,[_|Tail]):-member(H,Tail).
opp(sleva,sprava).
opp(sprava,sleva).
%sam predicat poiska, a imenno poiska v glubinu, Pervii parametr - spisok proidennih sostoyanii v obratnom poryadke, vtoroi tekushee polozenii lodki
depth([c([],[],Right,Move)|Tail],Napravlenie):-!,answer([c([],[],Right,Move)|Tail],Napravlenie). %esli dostigli zelaemogo sostoyaniya, to vivodim otvet
depth([c(Left,Lodka,Right,Move)|Tail],Nap):-step(Left,Lodka,Right,NewLeft,NewLodka,NewRight,Nap,NewMove),%inache smotrim kakoi mozno sdelat shag
not(vstrechalos(NewLeft,Tail)),%smotrim, chtobi posle etogo shaga ne poluchilos polozeniya na levom beregu, kotoroe uze vstrechalos ranshe, a to budet zaciklivanie
opp(Nap,Nap1),depth([c(NewLeft,NewLodka,NewRight,NewMove),c(Left,Lodka,Right,Move)|Tail],Nap1).%prodolzaem poisk iz novoi pozicii, ne zabivaya dobavit ee s spisok proidennih sostoyanii i izmenit napravlenie
%chtobi proverit ne vstrechalos li uze tekushee polozenii na levom beregu v spiske proidennih sostoyanii ravenstvo primenyat nelzya, net garantii chto potyadok takoi ze
%poetomu sozdaem predicat, proveryayushii yavlyaetsya li vtoroi spisok perestanovkoi pervogo
permutation([],[]).
permutation([H|Tail],P):-permutation(Tail,NewTail),%esli mozno perestavit hvost spiska
insert(H,NewTail,P).%posle chego vstavit v rezultat pervii element spiska i v itoge poluchit vtoroi parametr P, to yavlyaetsya perestanovkoi
%predicat, dobavlyayushii element na proizvolnoe mesto spiska
insert(X,L,[X|L]).
insert(X,[H|Tail],[H|NewTail]):-insert(X,Tail,NewTail).
%predicat proverki, vstrechalos li uze tekushee sostoyanie levogo berega v spiske proidennih sostoyanii
vstrechalos(X,[c(A,_,_,_)|_]):-permutation(A,X),!.
vstrechalos(X,[_|Tail]):-vstrechalos(X,Tail).
%predicat vivoda otveta. Vivodit nado v obratnom poryadke. Strelochki pokazivayut napravlenie lodki v dannii moment
answer([],_).
answer([c(A,Lodka,B,Move)|Tail],sleva):-!,answer(Tail,sprava),nl,nl,nl,print(Move),
write("\nPolozenie sleva: ",A,"\nPolozenie sprava: ",B,"\nLodka sleva, v nei: ",Lodka),nl.
answer([c(A,Lodka,B,Move)|Tail],sprava):-!,answer(Tail,sleva),nl,nl,nl,print(Move),
write("\nPolozenie sleva: ",A,"\nPolozenie sprava: ",B,"\nLodka sprava, v nei: ",Lodka),nl.
print([]).
print([s(S)|Tail]):-write(S," "),print(Tail).
print([i(I)|Tail]):-write(I," "),print(Tail).
goal
depth([c([m(1),w(1),m(2),w(2),m(3),w(3),m(4),w(4),m(5),w(5)],[],[],[s("Podoshli k beregu")])],sleva),nl,nl,nl.
|