edges(s,a,1).
edges(s,b,3).
edges(a,b,1).
edges(a,f,6).
edges(b,c,6).
edges(b,f,6).
edges(b,h,3).
edges(c,d,5).
edges(c,h,2).
edges(c,l,4).
edges(d,l,2).
edges(e,a,1).
edges(f,e,7).
edges(f,h,2).
edges(h,l,1).
edges(h,g,7).
edges(l,g,5).
hs(s,8).
hs(a,7).
hs(b,4).
hs(c,6).
hs(d,4).
hs(e,2).
hs(f,3).
hs(h,4).
hs(l,2).
hs(g,0).
min_search([Temp|Rest],[],Result):-
!,
min_search(Rest,Temp,Result).
min_search([],MinCost,MinCost):-!.
min_search([[P,Cost]|Rest],[_,TempMin],Result):-
Cost<TempMin,!,min_search(Rest,[P,Cost],Result).
min_search([_|Rest],MinP,Result):-
min_search(Rest,MinP,Result).
calc_cost(From,To,G_Costs,Result1,Result2):-
member([From,G1],G_Costs),
edges(From,To,C1),
hs(To,H),
updateG(G_Costs,ReG_Costs,To,Cost):-
select([To,_],G_Costs,RestG),!,
ReG_Costs=[[To,Cost]|RestG].
updateG(G_Costs,ReG_Costs,To,Cost):-
ReG_Costs=[[To,Cost]|G_Costs].
updatePath(Pathes,RePathes,From,To):-
select([_,To],Pathes,RestPathes),!,
RePathes=[[From,To]|RestPathes].
updatePath(Pathes,RePathes,From,To):-
RePathes=[[From,To]|Pathes].
path_print([],_).
path_print
(P
,Pathes
):-member
([Old
,P
],Pathes
),path_print
(Old
,Pathes
),write([P
,'->']).
one_search(From,To,
Opend,Closed,Pathes,G_Costs,
ReOpend,ReClosed,RePathes,ReG_Costs):-
not(member([To,_],Opend)),
not(member([To,_],Closed)),
!,
calc_cost(From,To,G_Costs,C1,C2),
ReOpend=[[To,C1]|Opend],
ReClosed=Closed,
updatePath(Pathes,RePathes,From,To),
updateG(G_Costs,ReG_Costs,To,C2).
one_search(From,To,
Opend,Closed,Pathes,G_Costs,
ReOpend,ReClosed,RePathes,ReG_Costs):-
select([To,NowCost],Opend,RestOpend),
calc_cost(From,To,G_Costs,C1,C2),
C1<NowCost,
!,
ReOpend=[[To,C1]|RestOpend],
ReClosed=Closed,
updatePath(Pathes,RePathes,From,To),
updateG(G_Costs,ReG_Costs,To,C2).
one_search(From,To,
Opend,Closed,Pathes,G_Costs,
ReOpend,ReClosed,RePathes,ReG_Costs):-
select([To,NowCost],Closed,RestClosed),
calc_cost(From,To,G_Costs,C1,C2),
C1<NowCost,
ReOpend=[[To,C1]|Opend],
ReClosed=RestClosed,
updatePath(Pathes,RePathes,From,To),
updateG(G_Costs,ReG_Costs,To,C2).
next_search(_,[],Opend,Closed,Pathes,G_Costs):-!,
a_star(Opend,Closed,Pathes,G_Costs).
next_search(From,[To|Rest],Opend,Closed,Pathes,G_Costs):-
one_search(From,To,Opend,Closed,Pathes,G_Costs,
ReOpend,ReClosed,RePathes,ReG_Costs),!,
next_search(From,Rest,ReOpend,ReClosed,RePathes,ReG_Costs).
next_search(From,[_|Rest],Opend,Closed,Pathes,G_Costs):-
next_search(From,Rest,Opend,Closed,Pathes,G_Costs).
a_star(Opend,_,Pathes,_):-
min_search(Opend,[],[From,_]),
From==g,
path_print(g,Pathes).
a_star(Opend,Closed,Pathes,G_Costs):-
min_search(Opend,[],[From,_]),
select([From,Cost],Opend,RestOpend),
NextClosed=[[From,Cost]|Closed],
next_search(From,Tos,RestOpend,NextClosed,Pathes,G_Costs).
main:-a_star([[s,8]],[],[[[],s]],[[s,0]]).
ZWRnZXMocyxhLDEpLgplZGdlcyhzLGIsMykuCmVkZ2VzKGEsYiwxKS4KZWRnZXMoYSxmLDYpLgplZGdlcyhiLGMsNikuCmVkZ2VzKGIsZiw2KS4KZWRnZXMoYixoLDMpLgplZGdlcyhjLGQsNSkuCmVkZ2VzKGMsaCwyKS4KZWRnZXMoYyxsLDQpLgplZGdlcyhkLGwsMikuCmVkZ2VzKGUsYSwxKS4KZWRnZXMoZixlLDcpLgplZGdlcyhmLGgsMikuCmVkZ2VzKGgsbCwxKS4KZWRnZXMoaCxnLDcpLgplZGdlcyhsLGcsNSkuCgoKaHMocyw4KS4KaHMoYSw3KS4KaHMoYiw0KS4KaHMoYyw2KS4KaHMoZCw0KS4KaHMoZSwyKS4KaHMoZiwzKS4KaHMoaCw0KS4KaHMobCwyKS4KaHMoZywwKS4KCm1pbl9zZWFyY2goW1RlbXB8UmVzdF0sW10sUmVzdWx0KTotCiAgICAhLAoJbWluX3NlYXJjaChSZXN0LFRlbXAsUmVzdWx0KS4KCm1pbl9zZWFyY2goW10sTWluQ29zdCxNaW5Db3N0KTotIS4KbWluX3NlYXJjaChbW1AsQ29zdF18UmVzdF0sW18sVGVtcE1pbl0sUmVzdWx0KTotCglDb3N0PFRlbXBNaW4sISxtaW5fc2VhcmNoKFJlc3QsW1AsQ29zdF0sUmVzdWx0KS4KbWluX3NlYXJjaChbX3xSZXN0XSxNaW5QLFJlc3VsdCk6LQoJICAgbWluX3NlYXJjaChSZXN0LE1pblAsUmVzdWx0KS4KCmNhbGNfY29zdChGcm9tLFRvLEdfQ29zdHMsUmVzdWx0MSxSZXN1bHQyKTotCgltZW1iZXIoW0Zyb20sRzFdLEdfQ29zdHMpLAoJZWRnZXMoRnJvbSxUbyxDMSksCglocyhUbyxIKSwKCVJlc3VsdDEgaXMgRzErQzErSCwKCVJlc3VsdDIgaXMgRzErQzEuCgp1cGRhdGVHKEdfQ29zdHMsUmVHX0Nvc3RzLFRvLENvc3QpOi0KCXNlbGVjdChbVG8sX10sR19Db3N0cyxSZXN0RyksISwKCVJlR19Db3N0cz1bW1RvLENvc3RdfFJlc3RHXS4KdXBkYXRlRyhHX0Nvc3RzLFJlR19Db3N0cyxUbyxDb3N0KTotCglSZUdfQ29zdHM9W1tUbyxDb3N0XXxHX0Nvc3RzXS4KCnVwZGF0ZVBhdGgoUGF0aGVzLFJlUGF0aGVzLEZyb20sVG8pOi0KCXNlbGVjdChbXyxUb10sUGF0aGVzLFJlc3RQYXRoZXMpLCEsCglSZVBhdGhlcz1bW0Zyb20sVG9dfFJlc3RQYXRoZXNdLgp1cGRhdGVQYXRoKFBhdGhlcyxSZVBhdGhlcyxGcm9tLFRvKTotCglSZVBhdGhlcz1bW0Zyb20sVG9dfFBhdGhlc10uCgpwYXRoX3ByaW50KFtdLF8pLgpwYXRoX3ByaW50KFAsUGF0aGVzKTotbWVtYmVyKFtPbGQsUF0sUGF0aGVzKSxwYXRoX3ByaW50KE9sZCxQYXRoZXMpLHdyaXRlKFtQLCctPiddKS4KCm9uZV9zZWFyY2goRnJvbSxUbywKCSAgT3BlbmQsQ2xvc2VkLFBhdGhlcyxHX0Nvc3RzLAoJICBSZU9wZW5kLFJlQ2xvc2VkLFJlUGF0aGVzLFJlR19Db3N0cyk6LQoJbm90KG1lbWJlcihbVG8sX10sT3BlbmQpKSwKCW5vdChtZW1iZXIoW1RvLF9dLENsb3NlZCkpLAoJISwKCWNhbGNfY29zdChGcm9tLFRvLEdfQ29zdHMsQzEsQzIpLAoJUmVPcGVuZD1bW1RvLEMxXXxPcGVuZF0sCglSZUNsb3NlZD1DbG9zZWQsCgl1cGRhdGVQYXRoKFBhdGhlcyxSZVBhdGhlcyxGcm9tLFRvKSwKCXVwZGF0ZUcoR19Db3N0cyxSZUdfQ29zdHMsVG8sQzIpLgoKCm9uZV9zZWFyY2goRnJvbSxUbywKCSAgT3BlbmQsQ2xvc2VkLFBhdGhlcyxHX0Nvc3RzLAoJICBSZU9wZW5kLFJlQ2xvc2VkLFJlUGF0aGVzLFJlR19Db3N0cyk6LQoJc2VsZWN0KFtUbyxOb3dDb3N0XSxPcGVuZCxSZXN0T3BlbmQpLAoJY2FsY19jb3N0KEZyb20sVG8sR19Db3N0cyxDMSxDMiksCglDMTxOb3dDb3N0LAoJISwKCVJlT3BlbmQ9W1tUbyxDMV18UmVzdE9wZW5kXSwKCVJlQ2xvc2VkPUNsb3NlZCwKCXVwZGF0ZVBhdGgoUGF0aGVzLFJlUGF0aGVzLEZyb20sVG8pLAoJdXBkYXRlRyhHX0Nvc3RzLFJlR19Db3N0cyxUbyxDMikuCgpvbmVfc2VhcmNoKEZyb20sVG8sCgkgIE9wZW5kLENsb3NlZCxQYXRoZXMsR19Db3N0cywKCSAgUmVPcGVuZCxSZUNsb3NlZCxSZVBhdGhlcyxSZUdfQ29zdHMpOi0KCXNlbGVjdChbVG8sTm93Q29zdF0sQ2xvc2VkLFJlc3RDbG9zZWQpLAoJY2FsY19jb3N0KEZyb20sVG8sR19Db3N0cyxDMSxDMiksCglDMTxOb3dDb3N0LAoJUmVPcGVuZD1bW1RvLEMxXXxPcGVuZF0sCglSZUNsb3NlZD1SZXN0Q2xvc2VkLAoJdXBkYXRlUGF0aChQYXRoZXMsUmVQYXRoZXMsRnJvbSxUbyksCgl1cGRhdGVHKEdfQ29zdHMsUmVHX0Nvc3RzLFRvLEMyKS4KbmV4dF9zZWFyY2goXyxbXSxPcGVuZCxDbG9zZWQsUGF0aGVzLEdfQ29zdHMpOi0hLAoJbmwsCgl3cml0ZShPcGVuZCksbmwsCgl3cml0ZShHX0Nvc3RzKSxubCwKCXdyaXRlKFBhdGhlcyksbmwsCglhX3N0YXIoT3BlbmQsQ2xvc2VkLFBhdGhlcyxHX0Nvc3RzKS4KCm5leHRfc2VhcmNoKEZyb20sW1RvfFJlc3RdLE9wZW5kLENsb3NlZCxQYXRoZXMsR19Db3N0cyk6LQoJb25lX3NlYXJjaChGcm9tLFRvLE9wZW5kLENsb3NlZCxQYXRoZXMsR19Db3N0cywKCQkgIFJlT3BlbmQsUmVDbG9zZWQsUmVQYXRoZXMsUmVHX0Nvc3RzKSwhLAoJbmV4dF9zZWFyY2goRnJvbSxSZXN0LFJlT3BlbmQsUmVDbG9zZWQsUmVQYXRoZXMsUmVHX0Nvc3RzKS4KbmV4dF9zZWFyY2goRnJvbSxbX3xSZXN0XSxPcGVuZCxDbG9zZWQsUGF0aGVzLEdfQ29zdHMpOi0KCW5leHRfc2VhcmNoKEZyb20sUmVzdCxPcGVuZCxDbG9zZWQsUGF0aGVzLEdfQ29zdHMpLgoKCmFfc3RhcihPcGVuZCxfLFBhdGhlcyxfKTotCgltaW5fc2VhcmNoKE9wZW5kLFtdLFtGcm9tLF9dKSwKCUZyb209PWcsCglwYXRoX3ByaW50KGcsUGF0aGVzKS4KCgphX3N0YXIoT3BlbmQsQ2xvc2VkLFBhdGhlcyxHX0Nvc3RzKTotCgltaW5fc2VhcmNoKE9wZW5kLFtdLFtGcm9tLF9dKSwKCXNlbGVjdChbRnJvbSxDb3N0XSxPcGVuZCxSZXN0T3BlbmQpLAoJTmV4dENsb3NlZD1bW0Zyb20sQ29zdF18Q2xvc2VkXSwKCWZpbmRhbGwoVG8sZWRnZXMoRnJvbSxUbyxfKSxUb3MpLAoJbmV4dF9zZWFyY2goRnJvbSxUb3MsUmVzdE9wZW5kLE5leHRDbG9zZWQsUGF0aGVzLEdfQ29zdHMpLgptYWluOi1hX3N0YXIoW1tzLDhdXSxbXSxbW1tdLHNdXSxbW3MsMF1dKS4=